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