001    package railo.runtime.type.scope.storage;
002    
003    import java.sql.SQLException;
004    
005    import railo.commons.io.log.Log;
006    import railo.runtime.PageContext;
007    import railo.runtime.PageContextImpl;
008    import railo.runtime.config.Config;
009    import railo.runtime.config.ConfigImpl;
010    import railo.runtime.db.DataSource;
011    import railo.runtime.db.DatasourceConnection;
012    import railo.runtime.db.DatasourceConnectionPool;
013    import railo.runtime.debug.DebuggerImpl;
014    import railo.runtime.debug.DebuggerPro;
015    import railo.runtime.engine.ThreadLocalPageContext;
016    import railo.runtime.exp.ApplicationException;
017    import railo.runtime.exp.PageException;
018    import railo.runtime.op.Caster;
019    import railo.runtime.type.Query;
020    import railo.runtime.type.Struct;
021    import railo.runtime.type.dt.DateTime;
022    import railo.runtime.type.dt.DateTimeImpl;
023    import railo.runtime.type.scope.ScopeContext;
024    import railo.runtime.type.scope.storage.db.SQLExecutionFactory;
025    import railo.runtime.type.scope.storage.db.SQLExecutor;
026    import railo.runtime.type.util.KeyConstants;
027    
028    /**
029     * client scope that store it's data in a datasource
030     */
031    public abstract class StorageScopeDatasource extends StorageScopeImpl {
032    
033            private static final long serialVersionUID = 239179599401918216L;
034    
035            public static final String PREFIX = "cf";
036            
037            private String datasourceName;
038    
039            private String appName;
040    
041            private String cfid;
042            
043            
044            /**
045             * Constructor of the class
046             * @param pc
047             * @param name
048             * @param sct
049             * @param b 
050             */
051            protected StorageScopeDatasource(PageContext pc,String datasourceName, String strType,int type,Struct sct) { 
052                    super(
053                                    sct,
054                                    doNowIfNull(pc,Caster.toDate(sct.get(TIMECREATED,null),false,pc.getTimeZone(),null)),
055                                    doNowIfNull(pc,Caster.toDate(sct.get(LASTVISIT,null),false,pc.getTimeZone(),null)),
056                                    -1, 
057                                    type==SCOPE_CLIENT?Caster.toIntValue(sct.get(HITCOUNT,"1"),1):0,
058                                    strType,type);
059    
060                    this.datasourceName=datasourceName; 
061                    appName=pc.getApplicationContext().getName();
062                    cfid=pc.getCFID();
063            }
064    
065            /**
066             * Constructor of the class, clone existing
067             * @param other
068             */
069            protected StorageScopeDatasource(StorageScopeDatasource other,boolean deepCopy) {
070                    super(other,deepCopy);
071                    this.datasourceName=other.datasourceName;
072            }
073            
074            private static DateTime doNowIfNull(PageContext pc,DateTime dt) {
075                    if(dt==null)return new DateTimeImpl(pc.getConfig());
076                    return dt;
077            }
078            
079            
080            
081            
082            protected static Struct _loadData(PageContext pc, String datasourceName,String strType,int type, Log log, boolean mxStyle) throws PageException {
083                    ConfigImpl config = (ConfigImpl)pc.getConfig();
084                    DatasourceConnectionPool pool = config.getDatasourceConnectionPool();
085                    DatasourceConnection dc=pool.getDatasourceConnection(pc,((PageContextImpl)pc).getDataSource(datasourceName),null,null);
086                    SQLExecutor executor=SQLExecutionFactory.getInstance(dc);
087                    
088                    
089                    Query query;
090                    
091                    try {
092                            if(!dc.getDatasource().isStorage()) 
093                                    throw new ApplicationException("storage usage for this datasource is disabled, you can enable this in the railo administrator.");
094                            query = executor.select(pc.getConfig(),pc.getCFID(),pc.getApplicationContext().getName(), dc, type,log, true);
095                    } 
096                    catch (SQLException se) {
097                            throw Caster.toPageException(se);
098                    }
099                finally {
100                    if(dc!=null) pool.releaseDatasourceConnection(dc);
101                }
102                boolean debugUsage=DebuggerImpl.debugQueryUsage(pc,query);
103                
104                if(query!=null)
105                    ((DebuggerPro)pc.getDebugger()).addQuery(debugUsage?query:null,datasourceName,"",query.getSql(),query.getRecordcount(),pc.getCurrentPageSource(),query.getExecutionTime());
106                boolean _isNew = query.getRecordcount()==0;
107                
108                if(_isNew) {
109                    ScopeContext.info(log,"create new "+strType+" scope for "+pc.getApplicationContext().getName()+"/"+pc.getCFID()+" in datasource ["+datasourceName+"]");
110                            return null;
111                }
112                String str=Caster.toString(query.get(KeyConstants._data));
113                if(mxStyle) return null;
114                Struct s = (Struct)pc.evaluate(str);
115                ScopeContext.info(log,"load existing data from ["+datasourceName+"."+PREFIX+"_"+strType+"_data] to create "+strType+" scope for "+pc.getApplicationContext().getName()+"/"+pc.getCFID());
116                    
117                return s;
118            }
119    
120            @Override
121            public void touchAfterRequest(PageContext pc) {
122                    setTimeSpan(pc);
123                    super.touchAfterRequest(pc); 
124                    
125                    store(pc.getConfig());
126            }
127            
128            public void store(Config config) {
129                    //if(!super.hasContent()) return;
130                    
131                    DatasourceConnection dc = null;
132                    ConfigImpl ci = (ConfigImpl)config;
133                    DatasourceConnectionPool pool = ci.getDatasourceConnectionPool();
134                    Log log=((ConfigImpl)config).getScopeLogger();
135                    try {
136                            PageContext pc = ThreadLocalPageContext.get();// FUTURE change method interface
137                            DataSource ds;
138                            if(pc!=null) ds=((PageContextImpl)pc).getDataSource(datasourceName);
139                            else ds=config.getDataSource(datasourceName);
140                            dc=pool.getDatasourceConnection(null,ds,null,null);
141                            SQLExecutor executor=SQLExecutionFactory.getInstance(dc);
142                            executor.update(config, cfid,appName, dc, getType(), sct,getTimeSpan(),log);
143                    } 
144                    catch (Throwable t) {
145                            ScopeContext.error(log, t);
146                    }
147                    finally {
148                            if(dc!=null) pool.releaseDatasourceConnection(dc);
149                    }
150            }
151            
152            public void unstore(Config config) {
153                    ConfigImpl ci=(ConfigImpl) config;
154                    DatasourceConnection dc = null;
155                    
156                    
157                    DatasourceConnectionPool pool = ci.getDatasourceConnectionPool();
158                    Log log=((ConfigImpl)config).getScopeLogger();
159                    try {
160                            PageContext pc = ThreadLocalPageContext.get();// FUTURE change method interface
161                            DataSource ds;
162                            if(pc!=null) ds=((PageContextImpl)pc).getDataSource(datasourceName);
163                            else ds=config.getDataSource(datasourceName);
164                            dc=pool.getDatasourceConnection(null,ds,null,null);
165                            SQLExecutor executor=SQLExecutionFactory.getInstance(dc);
166                            executor.delete(config, cfid,appName, dc, getType(),log);
167                    } 
168                    catch (Throwable t) {
169                            ScopeContext.error(log, t);
170                    }
171                    finally {
172                            if(dc!=null) pool.releaseDatasourceConnection(dc);
173                    }
174            }
175            
176            
177    
178            
179            
180            
181            
182            
183            
184    
185            @Override
186            public void touchBeforeRequest(PageContext pc) {
187                    setTimeSpan(pc);
188                    super.touchBeforeRequest(pc);
189            }
190            
191            @Override
192            public String getStorageType() {
193                    return "Datasource";
194            }
195    
196            /**
197             * @return the datasourceName
198             */
199            public String getDatasourceName() {
200                    return datasourceName;
201            }
202    }