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                                    type==SCOPE_CLIENT?doNowIfNull(pc,Caster.toDate(sct.get(TIMECREATED,null),false,pc.getTimeZone(),null)):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            /**
068             * @see railo.runtime.type.scope.storage.StorageScopeImpl#touchBeforeRequest(railo.runtime.PageContext)
069             */
070            public void touchBeforeRequest(PageContext pc) {
071                    setTimeSpan(pc);
072                    super.touchBeforeRequest(pc);
073            }
074    
075            /**
076             * @see railo.runtime.type.scope.storage.StorageScopeImpl#touchAfterRequest(railo.runtime.PageContext)
077             */
078            public void touchAfterRequest(PageContext pc) {
079                    setTimeSpan(pc);
080                    super.touchAfterRequest(pc);
081                    store(pc.getConfig());
082            }
083            
084            
085            
086            /**
087             * @see railo.runtime.type.scope.storage.StorageScopeImpl#store(railo.runtime.config.Config)
088             */
089            public void store(Config config) {
090                    //if(!super.hasContent()) return;
091                    try {
092                            if(!res.exists())ResourceUtil.createFileEL(res, true);
093                            IOUtil.write(res, (getTimeSpan()+System.currentTimeMillis())+":"+serializer.serializeStruct(sct, ignoreSet), "UTF-8", false);
094                    } 
095                    catch (Throwable t) {}
096            }
097            
098            protected static Struct _loadData(PageContext pc,Resource res, Log log) {
099                    if(res.exists()) {
100                            try {
101                                    String str=IOUtil.toString(res,"UTF-8");
102                                    int index=str.indexOf(':');
103                                    if(index!=-1){
104                                            long expires=Caster.toLongValue(str.substring(0,index),-1L);
105                                            // check is for backward compatibility, old files have no expires date inside. they do ot expire
106                                            if(expires!=-1) {
107                                                    str=str.substring(index+1);
108                                                    /*if(checkExpires && expires<System.currentTimeMillis()){
109                                                            print.o("expired("+new Date(expires)+"):"+res);
110                                                            return null;
111                                                    }
112                                                    else {
113                                                            str=str.substring(index+1);
114                                                            print.o("not expired("+new Date(expires)+"):"+res);
115                                                            print.o(str);
116                                                    }*/
117                                            }
118                                    }
119                                    Struct s = (Struct) evaluator.interpret(pc,str);
120                                    ScopeContext.info(log,"load existing file storage ["+res+"]");
121                                    return s;
122                            } 
123                            catch (Throwable t) {
124                                    ScopeContext.error(log, t);
125                            }
126                    }
127                    ScopeContext.info(log,"create new file storage ["+res+"]");
128                    return null;
129            }
130            
131            
132            
133            public void unstore(Config config) {
134                    try {
135                            if(!res.exists())return;
136                            res.remove(true);
137                    } 
138                    catch (Throwable t) {}
139            }
140            
141            protected static Resource _loadResource(ConfigWeb config, int type,String name, String cfid) {
142                    ConfigImpl ci = (ConfigImpl)config;
143                    Resource dir= type==SCOPE_CLIENT?ci.getClientScopeDir():ci.getSessionScopeDir();
144                    return   dir.getRealResource(getFolderName(name,cfid,true));
145            }
146            
147    
148            
149            /**
150             * return a folder name that match given input
151             * @param name
152             * @param cfid
153             * @param addExtension
154             * @return
155             */
156            public static String getFolderName(String name, String cfid,boolean addExtension) {
157                    if(addExtension) return getFolderName(name, cfid, false)+".scpt";
158                    if(!StringUtil.isEmpty(name))
159                            name=encode(name);//StringUtil.toVariableName(StringUtil.toLowerCase(name));
160                    else 
161                            name="__empty__";
162                    return name+"/"+cfid.substring(0,2)+"/"+cfid.substring(2);
163            }
164            
165            
166            /**
167             * @see railo.runtime.type.scope.storage.StorageScope#getStorageType()
168             */
169            public String getStorageType() {
170                    return STORAGE_TYPE;
171            }
172            
173            
174    }