001    package railo.runtime.type.scope.storage;
002    
003    import railo.commons.io.IOUtil;
004    import railo.commons.io.log.Log;
005    import railo.commons.io.res.Resource;
006    import railo.commons.io.res.util.ResourceUtil;
007    import railo.commons.lang.StringUtil;
008    import railo.runtime.PageContext;
009    import railo.runtime.config.Config;
010    import railo.runtime.config.ConfigImpl;
011    import railo.runtime.config.ConfigWeb;
012    import railo.runtime.converter.ScriptConverter;
013    import railo.runtime.interpreter.CFMLExpressionInterpreter;
014    import railo.runtime.op.Caster;
015    import railo.runtime.type.Struct;
016    import railo.runtime.type.StructImpl;
017    import railo.runtime.type.dt.DateTime;
018    import railo.runtime.type.dt.DateTimeImpl;
019    import railo.runtime.type.scope.ScopeContext;
020    
021    /**
022     * client scope that store it's data in a resource
023     */
024    public abstract class StorageScopeFile extends StorageScopeImpl {
025    
026            private static final long serialVersionUID = -7519591903822909934L;
027    
028            public static final String STORAGE_TYPE = "File"; 
029            
030            private static ScriptConverter serializer=new ScriptConverter();
031            protected static CFMLExpressionInterpreter evaluator=new CFMLExpressionInterpreter();
032            
033            private Resource res;
034    
035            /**
036             * Constructor of the class
037             * @param pc
038             * @param name
039             * @param sct
040             */
041            protected StorageScopeFile(PageContext pc,Resource res,String strType,int type,Struct sct) {
042                    super(
043                                    sct==null?(sct=new StructImpl()):sct,
044                                    doNowIfNull(pc,Caster.toDate(sct.get(TIMECREATED,null),false,pc.getTimeZone(),null)),
045                                    doNowIfNull(pc,Caster.toDate(sct.get(LASTVISIT,null),false,pc.getTimeZone(),null)),
046                                    -1,
047                                    type==SCOPE_CLIENT?Caster.toIntValue(sct.get(HITCOUNT,"1"),1):0,
048                                    strType,type);
049                    
050                    this.res =res;// pc.getConfig().getClientScopeDir().getRealResource(name+"-"+pc.getCFID()+".script");
051                    
052            }
053            private static DateTime doNowIfNull(PageContext pc,DateTime dt) {
054                    if(dt==null)return new DateTimeImpl(pc.getConfig());
055                    return dt;
056            }
057    
058            /**
059             * Constructor of the class, clone existing
060             * @param other
061             */
062            protected StorageScopeFile(StorageScopeFile other,boolean deepCopy) {
063                    super(other,deepCopy);
064                    this.res=other.res;
065            }
066    
067            @Override
068            public void touchBeforeRequest(PageContext pc) {
069                    setTimeSpan(pc);
070                    super.touchBeforeRequest(pc);
071            }
072    
073            @Override
074            public void touchAfterRequest(PageContext pc) {
075                    setTimeSpan(pc);
076                    super.touchAfterRequest(pc);
077                    store(pc.getConfig());
078            }
079            
080            
081            
082            @Override
083            public void store(Config config) {
084                    //if(!super.hasContent()) return;
085                    try {
086                            if(!res.exists())ResourceUtil.createFileEL(res, true);
087                            IOUtil.write(res, (getTimeSpan()+System.currentTimeMillis())+":"+serializer.serializeStruct(sct, ignoreSet), "UTF-8", false);
088                    } 
089                    catch (Throwable t) {}
090            }
091            
092            protected static Struct _loadData(PageContext pc,Resource res, Log log) {
093                    if(res.exists()) {
094                            try {
095                                    String str=IOUtil.toString(res,"UTF-8");
096                                    int index=str.indexOf(':');
097                                    if(index!=-1){
098                                            long expires=Caster.toLongValue(str.substring(0,index),-1L);
099                                            // check is for backward compatibility, old files have no expires date inside. they do ot expire
100                                            if(expires!=-1) {
101                                                    str=str.substring(index+1);
102                                                    /*if(checkExpires && expires<System.currentTimeMillis()){
103                                                            print.o("expired("+new Date(expires)+"):"+res);
104                                                            return null;
105                                                    }
106                                                    else {
107                                                            str=str.substring(index+1);
108                                                            print.o("not expired("+new Date(expires)+"):"+res);
109                                                            print.o(str);
110                                                    }*/
111                                            }
112                                    }
113                                    Struct s = (Struct) evaluator.interpret(pc,str);
114                                    ScopeContext.info(log,"load existing file storage ["+res+"]");
115                                    return s;
116                            } 
117                            catch (Throwable t) {
118                                    ScopeContext.error(log, t);
119                            }
120                    }
121                    ScopeContext.info(log,"create new file storage ["+res+"]");
122                    return null;
123            }
124            
125            
126            
127            public void unstore(Config config) {
128                    try {
129                            if(!res.exists())return;
130                            res.remove(true);
131                    } 
132                    catch (Throwable t) {}
133            }
134            
135            protected static Resource _loadResource(ConfigWeb config, int type,String name, String cfid) {
136                    ConfigImpl ci = (ConfigImpl)config;
137                    Resource dir= type==SCOPE_CLIENT?ci.getClientScopeDir():ci.getSessionScopeDir();
138                    return   dir.getRealResource(getFolderName(name,cfid,true));
139            }
140            
141    
142            
143            /**
144             * return a folder name that match given input
145             * @param name
146             * @param cfid
147             * @param addExtension
148             * @return
149             */
150            public static String getFolderName(String name, String cfid,boolean addExtension) {
151                    if(addExtension) return getFolderName(name, cfid, false)+".scpt";
152                    if(!StringUtil.isEmpty(name))
153                            name=encode(name);//StringUtil.toVariableName(StringUtil.toLowerCase(name));
154                    else 
155                            name="__empty__";
156                    return name+"/"+cfid.substring(0,2)+"/"+cfid.substring(2);
157            }
158            
159            
160            @Override
161            public String getStorageType() {
162                    return STORAGE_TYPE;
163            }
164            
165            
166    }