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    }