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 }