001 package railo.commons.io.res.type.cache; 002 003 import java.io.IOException; 004 import java.util.Iterator; 005 import java.util.List; 006 import java.util.Map; 007 008 import railo.commons.io.cache.Cache; 009 import railo.commons.io.cache.CacheEntry; 010 import railo.commons.io.res.Resource; 011 import railo.commons.io.res.ResourceProvider; 012 import railo.commons.io.res.Resources; 013 import railo.commons.io.res.util.ResourceLockImpl; 014 import railo.commons.io.res.util.ResourceUtil; 015 import railo.commons.lang.StringUtil; 016 import railo.runtime.cache.ram.RamCache; 017 import railo.runtime.config.Config; 018 import railo.runtime.config.ConfigImpl; 019 import railo.runtime.engine.ThreadLocalPageContext; 020 import railo.runtime.functions.cache.Util; 021 import railo.runtime.op.Caster; 022 import railo.runtime.op.Constants; 023 import railo.runtime.type.Struct; 024 025 026 /** 027 * Resource Provider for ram resource 028 */ 029 public final class CacheResourceProvider implements ResourceProvider { 030 031 private String scheme="ram"; 032 033 boolean caseSensitive=true; 034 private long lockTimeout=1000; 035 private ResourceLockImpl lock=new ResourceLockImpl(lockTimeout,caseSensitive); 036 private Map arguments; 037 038 private final Cache DEFAULT_CACHE=new RamCache(); 039 040 private Config config; 041 042 043 /** 044 * initalize ram resource 045 * @param scheme 046 * @param arguments 047 * @return RamResource 048 */ 049 public ResourceProvider init(String scheme,Map arguments) { 050 if(!StringUtil.isEmpty(scheme))this.scheme=scheme; 051 052 if(arguments!=null) { 053 this.arguments=arguments; 054 Object oCaseSensitive= arguments.get("case-sensitive"); 055 if(oCaseSensitive!=null) { 056 caseSensitive=Caster.toBooleanValue(oCaseSensitive,true); 057 } 058 059 // lock-timeout 060 Object oTimeout = arguments.get("lock-timeout"); 061 if(oTimeout!=null) { 062 lockTimeout=Caster.toLongValue(oTimeout,lockTimeout); 063 } 064 } 065 lock.setLockTimeout(lockTimeout); 066 lock.setCaseSensitive(caseSensitive); 067 068 069 070 return this; 071 } 072 073 074 075 /** 076 * @see res.ResourceProvider#getResource(java.lang.String) 077 */ 078 public Resource getResource(String path) { 079 path=ResourceUtil.removeScheme(scheme,path); 080 if(!StringUtil.startsWith(path,'/'))path="/"+path; 081 return new CacheResource(this,path); 082 } 083 084 /** 085 * returns core for this path if exists, otherwise return null 086 * @param path 087 * @return core or null 088 */ 089 CacheResourceCore getCore(String path,String name) { 090 Object obj = getCache().getValue(toKey(path,name),null); 091 if(obj instanceof CacheResourceCore) return (CacheResourceCore) obj; 092 return null; 093 } 094 095 void touch(String path,String name) { 096 Cache cache = getCache(); 097 CacheEntry ce = cache.getCacheEntry(toKey(path,name),null); 098 if(ce!=null){ 099 cache.put(ce.getKey(), ce.getValue(), ce.idleTimeSpan(), ce.liveTimeSpan()); 100 } 101 } 102 103 104 Struct getMeta(String path,String name) { 105 CacheEntry ce = getCache().getCacheEntry(toKey(path,name),null); 106 if(ce!=null) return ce.getCustomInfo(); 107 return null; 108 } 109 110 String[] getChildNames(String path) { 111 List list = getCache().values(new ChildrenFilter(path)); 112 String[] arr = new String[list.size()]; 113 Iterator it = list.iterator(); 114 int index=0; 115 while(it.hasNext()){ 116 arr[index++]=((CacheResourceCore) it.next()).getName(); 117 } 118 // TODO remove none CacheResourceCore elements 119 return arr; 120 } 121 /*CacheResourceCore[] getChildren(String path) { 122 List list = getCache().values(new ChildrenFilter(path)); 123 CacheResourceCore[] arr = new CacheResourceCore[list.size()]; 124 Iterator it = list.iterator(); 125 int index=0; 126 while(it.hasNext()){ 127 arr[index++]=(CacheResourceCore) it.next(); 128 } 129 // TODO remove none CacheResourceCore elements 130 return arr; 131 }*/ 132 133 134 135 136 /** 137 * create a new core 138 * @param path 139 * @param type 140 * @return created core 141 * @throws IOException 142 */ 143 CacheResourceCore createCore(String path, String name, int type) throws IOException { 144 CacheResourceCore value = new CacheResourceCore(type,path,name); 145 getCache().put(toKey(path,name),value,null,null); 146 return value; 147 } 148 149 150 151 CacheResourceCore createRoot() { 152 CacheResourceCore value = new CacheResourceCore(CacheResourceCore.TYPE_DIRECTORY,null,""); 153 getCache().put(toKey("null",""),value,Constants.LONG_ZERO,Constants.LONG_ZERO); 154 return value; 155 } 156 157 158 159 void removeCore(String path, String name) { 160 getCache().remove(toKey(path,name)); 161 } 162 163 164 /** 165 * @see res.ResourceProvider#getScheme() 166 */ 167 public String getScheme() { 168 return scheme; 169 } 170 /** 171 * @see railo.commons.io.res.ResourceProvider#setResources(railo.commons.io.res.Resources) 172 */ 173 public void setResources(Resources resources) { 174 //this.resources=resources; 175 } 176 177 /** 178 * @throws IOException 179 * @see railo.commons.io.res.ResourceProvider#lock(railo.commons.io.res.Resource) 180 */ 181 public void lock(Resource res) throws IOException { 182 lock.lock(res); 183 } 184 185 /** 186 * @see railo.commons.io.res.ResourceProvider#unlock(railo.commons.io.res.Resource) 187 */ 188 public void unlock(Resource res) { 189 lock.unlock(res); 190 } 191 192 /** 193 * @see railo.commons.io.res.ResourceProvider#read(railo.commons.io.res.Resource) 194 */ 195 public void read(Resource res) throws IOException { 196 lock.read(res); 197 } 198 199 /** 200 * 201 * @see railo.commons.io.res.ResourceProvider#isAttributesSupported() 202 */ 203 public boolean isAttributesSupported() { 204 return true; 205 } 206 207 /** 208 * 209 * @see railo.commons.io.res.ResourceProvider#isCaseSensitive() 210 */ 211 public boolean isCaseSensitive() { 212 return caseSensitive; 213 } 214 215 /** 216 * 217 * @see railo.commons.io.res.ResourceProvider#isModeSupported() 218 */ 219 public boolean isModeSupported() { 220 return true; 221 } 222 223 /** 224 * @see railo.commons.io.res.ResourceProvider#getArguments() 225 */ 226 public Map getArguments() { 227 return arguments; 228 } 229 230 231 private Cache getCache() { 232 if(config==null){ 233 config=ThreadLocalPageContext.getConfig(); 234 createRoot(); 235 236 } 237 Cache c = Util.getDefault(config,ConfigImpl.CACHE_DEFAULT_RESOURCE,DEFAULT_CACHE); 238 return c; 239 } 240 241 private String toKey(String path, String name) { 242 if(caseSensitive) return path+":"+name; 243 return (path+":"+name).toLowerCase(); 244 } 245 246 247 }