001    package railo.runtime.type.scope.storage;
002    
003    import java.io.IOException;
004    
005    import railo.commons.io.cache.Cache;
006    import railo.commons.io.log.Log;
007    import railo.runtime.PageContext;
008    import railo.runtime.cache.CacheConnection;
009    import railo.runtime.config.Config;
010    import railo.runtime.exp.ApplicationException;
011    import railo.runtime.exp.PageException;
012    import railo.runtime.functions.cache.Util;
013    import railo.runtime.op.Caster;
014    import railo.runtime.type.Struct;
015    import railo.runtime.type.dt.DateTime;
016    import railo.runtime.type.dt.DateTimeImpl;
017    import railo.runtime.type.scope.ScopeContext;
018    
019    /**
020     * client scope that store it's data in a datasource
021     */
022    public abstract class StorageScopeCache extends StorageScopeImpl {
023    
024            private static final long serialVersionUID = 6234854552927320080L;
025    
026            public static final long SAVE_EXPIRES_OFFSET = 60*60*1000;
027    
028            //private static ScriptConverter serializer=new ScriptConverter();
029            //boolean structOk;
030            
031            private final String cacheName;
032            private final String appName;
033            private final String cfid;
034    
035    
036            
037            
038            /**
039             * Constructor of the class
040             * @param pc
041             * @param name
042             * @param sct
043             * @param b 
044             */
045            protected StorageScopeCache(PageContext pc,String cacheName, String appName,String strType,int type,Struct sct) { 
046                    // !!! do not store the pagecontext or config object, this object is Serializable !!!
047                    super(
048                                    sct,
049                                    type==SCOPE_CLIENT?doNowIfNull(pc.getConfig(),Caster.toDate(sct.get(TIMECREATED,null),false,pc.getTimeZone(),null)):null,
050                                    doNowIfNull(pc.getConfig(),Caster.toDate(sct.get(LASTVISIT,null),false,pc.getTimeZone(),null)),
051                                    -1, 
052                                    type==SCOPE_CLIENT?Caster.toIntValue(sct.get(HITCOUNT,"1"),1):1
053                                    ,strType,type);
054                    
055                    //this.isNew=isNew;
056                    this.appName=appName;
057                    this.cacheName=cacheName;
058                    this.cfid=pc.getCFID();
059            }
060    
061            /**
062             * Constructor of the class, clone existing
063             * @param other
064             */
065            protected StorageScopeCache(StorageScopeCache other,boolean deepCopy) {
066                    super(other,deepCopy);
067                    
068                    this.appName=other.appName;
069                    this.cacheName=other.cacheName;
070                    this.cfid=other.cfid;
071            }
072            
073            private static DateTime doNowIfNull(Config config,DateTime dt) {
074                    if(dt==null)return new DateTimeImpl(config);
075                    return dt;
076            }
077            
078            /**
079             * @see railo.runtime.type.SharedScope#release(railo.runtime.PageContext)
080             */
081            public void touchAfterRequest(PageContext pc) {
082                    setTimeSpan(pc);
083                    super.touchAfterRequest(pc);
084                    //if(super.hasContent()) 
085                            store(pc.getConfig());
086            }
087    
088            /**
089             * @see railo.runtime.type.scope.storage.StorageScope#getStorageType()
090             */
091            public String getStorageType() {
092                    return "Cache";
093            }
094    
095            /**
096             *
097             * @see railo.runtime.type.scope.ClientSupportOld#initialize(railo.runtime.PageContext)
098             */
099            public void touchBeforeRequest(PageContext pc) {
100                    setTimeSpan(pc);
101                    super.touchBeforeRequest(pc);
102            }
103            
104            protected static Struct _loadData(PageContext pc, String cacheName, String appName, String strType, Log log) throws PageException       {
105                    Cache cache = getCache(pc.getConfig(),cacheName);
106                    String key=getKey(pc.getCFID(),appName,strType);
107                    
108                    Struct s = (Struct) cache.getValue(key,null);
109                    
110                    if(s!=null)
111                            ScopeContext.info(log,"load existing data from  cache ["+cacheName+"] to create "+strType+" scope for "+pc.getApplicationContext().getName()+"/"+pc.getCFID());
112                    else
113                            ScopeContext.info(log,"create new "+strType+" scope for "+pc.getApplicationContext().getName()+"/"+pc.getCFID()+" in cache ["+cacheName+"]");
114                    
115                    return s;
116            }
117    
118            public void store(Config config) {
119                    try {
120                            Cache cache = getCache(config, cacheName);
121                            /*if(cache instanceof CacheEvent) {
122                                    CacheEvent ce=(CacheEvent) cache;
123                                    ce.register(new SessionEndCacheEvent());
124                            }*/
125                            String key=getKey(cfid, appName, getTypeAsString());
126                            cache.put(key, sct,new Long(getTimeSpan()), null);
127                    } 
128                    catch (PageException pe) {}
129            }
130            
131            public void unstore(Config config) {
132                    try {
133                            Cache cache = getCache(config, cacheName);
134                            String key=getKey(cfid, appName, getTypeAsString());
135                            cache.remove(key);
136                    } 
137                    catch (PageException pe) {}
138            }
139            
140    
141            private static Cache getCache(Config config, String cacheName) throws PageException {
142                    try {
143                            CacheConnection cc = Util.getCacheConnection(config,cacheName);
144                            if(!cc.isStorage()) 
145                                    throw new ApplicationException("storage usage for this cache is disabled, you can enable this in the railo administrator.");
146                            return cc.getInstance(config); 
147                    } catch (IOException e) {
148                            throw Caster.toPageException(e);
149                    }
150            }
151            
152    
153            public static String getKey(String cfid, String appName, String type) {
154                    return new StringBuilder("railo-storage:").append(type).append(":").append(cfid).append(":").append(appName).toString();
155            }
156            
157            /*private void setTimeSpan(PageContext pc) {
158                    ApplicationContextPro ac=(ApplicationContextPro) pc.getApplicationContext();
159                    timespan = (getType()==SCOPE_CLIENT?ac.getClientTimeout().getMillis():ac.getSessionTimeout().getMillis())+(expiresControlFromOutside?SAVE_EXPIRES_OFFSET:0L);
160                    
161            }*/
162    }