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    }