package railo.runtime.type.scope; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import javax.servlet.http.HttpSession; import org.safehaus.uuid.UUIDGenerator; import railo.commons.collection.MapFactory; import railo.commons.io.log.Log; import railo.commons.io.log.LogAndSource; import railo.commons.lang.ExceptionUtil; import railo.commons.lang.SizeOf; import railo.commons.lang.StringUtil; import railo.commons.lang.types.RefBoolean; import railo.commons.lang.types.RefBooleanImpl; import railo.runtime.CFMLFactoryImpl; import railo.runtime.PageContext; import railo.runtime.PageContextImpl; import railo.runtime.cache.CacheConnection; import railo.runtime.config.Config; import railo.runtime.config.ConfigImpl; import railo.runtime.db.DataSource; import railo.runtime.exp.ApplicationException; import railo.runtime.exp.ExceptionHandler; import railo.runtime.exp.ExpressionException; import railo.runtime.exp.PageException; import railo.runtime.exp.PageRuntimeException; import railo.runtime.functions.cache.Util; import railo.runtime.interpreter.VariableInterpreter; import railo.runtime.listener.ApplicationContext; import railo.runtime.listener.ApplicationListener; import railo.runtime.op.Caster; import railo.runtime.type.KeyImpl; import railo.runtime.type.Struct; import railo.runtime.type.StructImpl; import railo.runtime.type.scope.client.ClientCache; import railo.runtime.type.scope.client.ClientCookie; import railo.runtime.type.scope.client.ClientDatasource; import railo.runtime.type.scope.client.ClientFile; import railo.runtime.type.scope.client.ClientMemory; import railo.runtime.type.scope.session.SessionCache; import railo.runtime.type.scope.session.SessionCookie; import railo.runtime.type.scope.session.SessionDatasource; import railo.runtime.type.scope.session.SessionFile; import railo.runtime.type.scope.session.SessionMemory; import railo.runtime.type.scope.storage.MemoryScope; import railo.runtime.type.scope.storage.StorageScope; import railo.runtime.type.scope.storage.StorageScopeCleaner; import railo.runtime.type.scope.storage.StorageScopeEngine; import railo.runtime.type.scope.storage.clean.DatasourceStorageScopeCleaner; import railo.runtime.type.scope.storage.clean.FileStorageScopeCleaner; import railo.runtime.type.wrap.MapAsStruct; import railo.runtime.util.PageContextUtil; /** * Scope Context handle Apllication and Session Scopes */ public final class ScopeContext { private static final int MINUTE = 60*1000; private static final long CLIENT_MEMORY_TIMESPAN = 5*MINUTE; private static final long SESSION_MEMORY_TIMESPAN = 5*MINUTE; private static UUIDGenerator generator = UUIDGenerator.getInstance(); private Map<String,Map<String,Scope>> cfSessionContextes=MapFactory.<String,Map<String,Scope>>getConcurrentMap(); private Map<String,Map<String,Scope>> cfClientContextes=MapFactory.<String,Map<String,Scope>>getConcurrentMap(); private Map<String,Application> applicationContextes=MapFactory.<String,Application>getConcurrentMap(); private int maxSessionTimeout=0; private static Cluster cluster; private static Server server=null; private StorageScopeEngine client; private StorageScopeEngine session; private CFMLFactoryImpl factory; private LogAndSource log; public ScopeContext(CFMLFactoryImpl factory) { this.factory=factory; } /** * @return the log */ private Log getLog() { if(log==null) { this.log=((ConfigImpl)factory.getConfig()).getScopeLogger(); } return log; } public void info(String msg) {info(getLog(), msg);} public void error(String msg) {error(getLog(),msg);} public void error(Throwable t) {error(getLog(), t);} public static void info(Log log,String msg) { if(log!=null)log.info("scope-context", msg); } public static void error(Log log,String msg) { if(log!=null)log.error("scope-context", msg); } public static void error(Log log,Throwable t) { if(log!=null)log.error("scope-context",ExceptionUtil.getStacktrace(t, true)); } /** * return a map matching key from given map * @param parent * @param key key of the map * @return matching map, if no map exist it willbe one created */ private Map<String,Scope> getSubMap(Map<String,Map<String,Scope>> parent, String key) { Map<String,Scope> context=parent.get(key); if(context!=null) return context; context = MapFactory.<String,Scope>getConcurrentMap(); parent.put(key,context); return context; } /** * return the server Scope for this context * @param pc * @return server scope */ public static Server getServerScope(PageContext pc) { if(server==null) { server=new ServerImpl(pc); } return server; } /* * * Returns the current Cluster Scope, if there is no current Cluster Scope, this method returns null. * @param pc * @param create * @return * @throws SecurityException * / public static Cluster getClusterScope() { return cluster; }*/ /** * Returns the current Cluster Scope, if there is no current Cluster Scope and create is true, returns a new Cluster Scope. * If create is false and the request has no valid Cluster Scope, this method returns null. * @param pc * @param create * @return * @throws PageException */ public static Cluster getClusterScope(Config config, boolean create) throws PageException { if(cluster==null && create) { cluster=((ConfigImpl)config).createClusterScope(); } return cluster; } public static void clearClusterScope() { cluster=null; } public Client getClientScope(PageContext pc) throws PageException { Client client=null; ApplicationContext appContext = pc.getApplicationContext(); // get Context Map<String, Scope> context = getSubMap(cfClientContextes,appContext.getName()); // get Client boolean isMemory=false; String storage = appContext.getClientstorage(); if(StringUtil.isEmpty(storage,true)){ storage=ConfigImpl.DEFAULT_STORAGE_CLIENT; } else if("ram".equalsIgnoreCase(storage)) { storage="memory"; isMemory=true; } else if("registry".equalsIgnoreCase(storage)) { storage="file"; } else { storage=storage.toLowerCase(); if("memory".equals(storage))isMemory=true; } final boolean doMemory=isMemory || !appContext.getClientCluster(); client=doMemory?(Client) context.get(pc.getCFID()):null; if(client==null || client.isExpired() || !client.getStorage().equalsIgnoreCase(storage)) { if("file".equals(storage)){ client=ClientFile.getInstance(appContext.getName(),pc,getLog()); } else if("cookie".equals(storage)) client=ClientCookie.getInstance(appContext.getName(),pc,getLog()); else if("memory".equals(storage)){ client=ClientMemory.getInstance(pc,getLog()); } else{ DataSource ds = ((PageContextImpl)pc).getDataSource(storage,null); if(ds!=null)client=ClientDatasource.getInstance(storage,pc,getLog()); else client=ClientCache.getInstance(storage,appContext.getName(),pc,getLog(),null); if(client==null){ // datasource not enabled for storage if(ds!=null) throw new ApplicationException("datasource ["+storage+"] is not enabled to be used as session/client storage, you have to enable it in the railo administrator."); CacheConnection cc = Util.getCacheConnection(pc.getConfig(),storage,null); if(cc!=null) throw new ApplicationException("cache ["+storage+"] is not enabled to be used as a session/client storage, you have to enable it in the railo administrator."); throw new ApplicationException("there is no cache or datasource with name ["+storage+"] defined."); } } client.setStorage(storage); if(doMemory)context.put(pc.getCFID(),client); } else getLog().info("scope-context", "use existing client scope for "+appContext.getName()+"/"+pc.getCFID()+" from storage "+storage); client.touchBeforeRequest(pc); return client; } public Client getClientScopeEL(PageContext pc) { try { return getClientScope(pc); } catch (PageException pe) { throw new PageRuntimeException(pe); } } /*public ClientPlus getClientScopeEL(PageContext pc) { ClientPlus client=null; ApplicationContext appContext = pc.getApplicationContext(); // get Context Map context=getSubMap(cfClientContextes,appContext.getName()); // get Client String storage = appContext.getClientstorage(); if(!StringUtil.isEmpty(storage))storage=storage.toLowerCase(); else storage=""; client=(ClientPlus) context.get(pc.getCFID()); if(client==null || client.isExpired() || !client.getStorageType().equalsIgnoreCase(storage)) { if(StringUtil.isEmpty(storage) || "file".equals(storage) || "registry".equals(storage)){ storage="file"; client=ClientFile.getInstance(appContext.getName(),pc,getLog()); } else if("cookie".equals(storage)) client=ClientCookie.getInstance(appContext.getName(),pc,getLog()); else if("memory".equals(storage) || "ram".equals(storage)){ //storage="ram"; client=ClientMemory.getInstance(pc,getLog()); } else{ DataSource ds = ((ConfigImpl)pc.getConfig()).getDataSource(storage,null); if(ds!=null)client=ClientDatasource.getInstanceEL(storage,pc,getLog()); else client=ClientCache.getInstanceEL(storage,appContext.getName(),pc,getLog()); } client.setStorage(storage); context.put(pc.getCFID(),client); } else getLog().info("scope-context", "use existing client scope for "+appContext.getName()+"/"+pc.getCFID()+" from storage "+storage); client.initialize(pc); return client; }*/ /** * return the session count of all application contextes * @return */ public int getSessionCount(PageContext pc) { if(pc.getSessionType()==Config.SESSION_TYPE_J2EE) return 0; Iterator<Entry<String, Map<String, Scope>>> it = cfSessionContextes.entrySet().iterator(); Entry<String, Map<String, Scope>> entry; int count=0; while(it.hasNext()) { entry = it.next(); count+=getSessionCount(entry.getValue()); } return count; } /** * return the session count of this application context * @return */ public int getAppContextSessionCount(PageContext pc) { ApplicationContext appContext = pc.getApplicationContext(); if(pc.getSessionType()==Config.SESSION_TYPE_J2EE) return 0; Map<String, Scope> context = getSubMap(cfSessionContextes,appContext.getName()); return getSessionCount(context); } private int getSessionCount(Map<String, Scope> context) { Iterator<Entry<String, Scope>> it = context.entrySet().iterator(); Entry<String, Scope> entry; int count=0; Session s; while(it.hasNext()) { entry = it.next(); s=(Session)entry.getValue(); if(!s.isExpired()) count++; } return count; } /** * return all session context of this application context * @param pc * @return */ public Struct getAllSessionScopes(PageContext pc) { return getAllSessionScopes(pc.getApplicationContext().getName()); } public Struct getAllApplicationScopes() { Struct trg=new StructImpl(); StructImpl.copy(MapAsStruct.toStruct(applicationContextes, true), trg, false); return trg; } public Struct getAllCFSessionScopes() { Struct trg=new StructImpl(); StructImpl.copy(MapAsStruct.toStruct(this.cfSessionContextes, true), trg, false); return trg; } /** * return the size in bytes of all session contextes * @return size in bytes * @throws ExpressionException */ public long getScopesSize(int scope) throws ExpressionException { if(scope==Scope.SCOPE_APPLICATION)return SizeOf.size(applicationContextes); if(scope==Scope.SCOPE_CLUSTER)return SizeOf.size(cluster); if(scope==Scope.SCOPE_SERVER)return SizeOf.size(server); if(scope==Scope.SCOPE_SESSION)return SizeOf.size(this.cfSessionContextes); if(scope==Scope.SCOPE_CLIENT)return SizeOf.size(this.cfClientContextes); throw new ExpressionException("can only return information of scope that are not request dependent"); } /** * get all session contexts of given applicaton name * @param pc * @param appName * @return * @deprecated use instead getAllSessionScopes(String appName) */ public Struct getAllSessionScopes(PageContext pc, String appName) { return getAllSessionScopes(appName); } /** * get all session contexts of given applicaton name * @param pc * @param appName * @return */ public Struct getAllSessionScopes(String appName) { //if(pc.getSessionType()==Config.SESSION_TYPE_J2EE)return new StructImpl(); return getAllSessionScopes(getSubMap(cfSessionContextes,appName),appName); } private Struct getAllSessionScopes(Map<String,Scope> context, String appName) { Iterator<Entry<String, Scope>> it = context.entrySet().iterator(); Entry<String, Scope> entry; Struct sct=new StructImpl(); Session s; while(it.hasNext()) { entry = it.next(); s=(Session)entry.getValue(); if(!s.isExpired()) sct.setEL(KeyImpl.init(appName+"_"+entry.getKey()+"_0"), s); } return sct; } /** * return the session Scope for this context (cfid,cftoken,contextname) * @param pc PageContext * @return session matching the context * @throws PageException */ public Session getSessionScope(PageContext pc,RefBoolean isNew) throws PageException { if(pc.getSessionType()==Config.SESSION_TYPE_CFML)return getCFSessionScope(pc,isNew); return getJSessionScope(pc,isNew); } public boolean hasExistingSessionScope(PageContext pc) { if(pc.getSessionType()==Config.SESSION_TYPE_CFML)return hasExistingCFSessionScope(pc); return hasExistingJSessionScope(pc); } private synchronized boolean hasExistingJSessionScope(PageContext pc) { HttpSession httpSession=pc.getSession(); if(httpSession==null) return false; Session session=(Session) httpSession.getAttribute(pc.getApplicationContext().getName()); return session instanceof JSession; } private boolean hasExistingCFSessionScope(PageContext pc) { ApplicationContext appContext = pc.getApplicationContext(); // get Context Map<String, Scope> context = getSubMap(cfSessionContextes,appContext.getName()); // get Session String storage = appContext.getSessionstorage(); if(StringUtil.isEmpty(storage,true))storage="memory"; else if("ram".equalsIgnoreCase(storage)) storage="memory"; else if("registry".equalsIgnoreCase(storage)) storage="file"; else storage=storage.toLowerCase(); Session session=(Session) context.get(pc.getCFID()); if(!(session instanceof StorageScope) || session.isExpired() || !((StorageScope)session).getStorage().equalsIgnoreCase(storage)) { if("memory".equals(storage)) return false; else if("file".equals(storage)) return SessionFile.hasInstance(appContext.getName(),pc); else if("cookie".equals(storage)) return SessionCookie.hasInstance(appContext.getName(),pc); else { DataSource ds = ((ConfigImpl)pc.getConfig()).getDataSource(storage,null); if(ds!=null && ds.isStorage()){ if(SessionDatasource.hasInstance(storage,pc)) return true; } return SessionCache.hasInstance(storage,appContext.getName(),pc); } } return true; } /** * return cf session scope * @param pc PageContext * @param checkExpires * @param listener * @return cf session matching the context * @throws PageException */ private synchronized Session getCFSessionScope(PageContext pc, RefBoolean isNew) throws PageException { ApplicationContext appContext = pc.getApplicationContext(); // get Context Map<String, Scope> context = getSubMap(cfSessionContextes,appContext.getName()); // get Session boolean isMemory=false; String storage = appContext.getSessionstorage(); if(StringUtil.isEmpty(storage,true)){ storage=ConfigImpl.DEFAULT_STORAGE_SESSION; isMemory=true; } else if("ram".equalsIgnoreCase(storage)) { storage="memory"; isMemory=true; } else if("registry".equalsIgnoreCase(storage)) { storage="file"; } else { storage=storage.toLowerCase(); if("memory".equals(storage))isMemory=true; } final boolean doMemory=isMemory || !appContext.getSessionCluster(); Session session=doMemory?appContext.getSessionCluster()?null:(Session) context.get(pc.getCFID()):null; if(!(session instanceof StorageScope) || session.isExpired() || !((StorageScope)session).getStorage().equalsIgnoreCase(storage)) { if(isMemory){ session=SessionMemory.getInstance(pc,isNew,getLog()); } else if("file".equals(storage)){ session=SessionFile.getInstance(appContext.getName(),pc,getLog()); } else if("cookie".equals(storage)) session=SessionCookie.getInstance(appContext.getName(),pc,getLog()); else{ DataSource ds = ((PageContextImpl)pc).getDataSource(storage,null); if(ds!=null && ds.isStorage())session=SessionDatasource.getInstance(storage,pc,getLog(),null); else session=SessionCache.getInstance(storage,appContext.getName(),pc,getLog(),null); if(session==null){ // datasource not enabled for storage if(ds!=null) throw new ApplicationException( "datasource ["+storage+"] is not enabled to be used as session/client storage, " + "you have to enable it in the railo administrator or define key \"storage=true\" for datasources defined in Application.cfc ."); CacheConnection cc = Util.getCacheConnection(pc.getConfig(),storage,null); if(cc!=null) throw new ApplicationException("cache ["+storage+"] is not enabled to be used as a session/client storage, you have to enable it in the railo administrator."); throw new ApplicationException("there is no cache or datasource with name ["+storage+"] defined."); } } ((StorageScope)session).setStorage(storage); if(doMemory)context.put(pc.getCFID(),session); isNew.setValue(true); } else { getLog().info("scope-context", "use existing session scope for "+appContext.getName()+"/"+pc.getCFID()+" from storage "+storage); } session.touchBeforeRequest(pc); return session; } public synchronized void removeSessionScope(PageContext pc) throws PageException { //CFSession Session sess = getCFSessionScope(pc, new RefBooleanImpl()); ApplicationContext appContext = pc.getApplicationContext(); Map<String, Scope> context = getSubMap(cfSessionContextes,appContext.getName()); if(context!=null) { context.remove(pc.getCFID()); if(sess instanceof StorageScope)((StorageScope)sess).unstore(pc.getConfig()); } // JSession HttpSession httpSession=pc.getSession(); if(httpSession!=null) { httpSession.removeAttribute(appContext.getName()); } } public synchronized void removeClientScope(PageContext pc) throws PageException { Client cli = getClientScope(pc); ApplicationContext appContext = pc.getApplicationContext(); Map<String, Scope> context = getSubMap(cfClientContextes,appContext.getName()); if(context!=null) { context.remove(pc.getCFID()); if(cli!=null)cli.unstore(pc.getConfig()); } } public boolean remove(int type, String appName, String cfid) { Map<String, Map<String, Scope>> contextes = type==Scope.SCOPE_CLIENT?cfClientContextes:cfSessionContextes; Map<String, Scope> context = getSubMap(contextes,appName); Object res = context.remove(cfid); getLog().info("scope-context", "remove "+VariableInterpreter.scopeInt2String(type)+" scope "+appName+"/"+cfid+" from memory"); return res!=null; } /** * return j session scope * @param pc PageContext * @param listener * @return j session matching the context * @throws PageException */ private synchronized Session getJSessionScope(PageContext pc, RefBoolean isNew) throws PageException { HttpSession httpSession=pc.getSession(); ApplicationContext appContext = pc.getApplicationContext(); Object session=null;// this is from type object, because it is possible that httpSession return object from prior restart int s=(int) appContext.getSessionTimeout().getSeconds(); if(maxSessionTimeout<s)maxSessionTimeout=s; if(httpSession!=null) { httpSession.setMaxInactiveInterval(maxSessionTimeout); session= httpSession.getAttribute(appContext.getName()); } else { Map<String, Scope> context = getSubMap(cfSessionContextes,appContext.getName()); session=context.get(pc.getCFID()); } JSession jSession=null; if(session instanceof JSession) { jSession=(JSession) session; try { if(jSession.isExpired()) { jSession.touch(); } info(getLog(), "use existing JSession for "+appContext.getName()+"/"+pc.getCFID()); } catch(ClassCastException cce) { error(getLog(), cce); // if there is no HTTPSession if(httpSession==null) return getCFSessionScope(pc, isNew); jSession=new JSession(); httpSession.setAttribute(appContext.getName(),jSession); isNew.setValue(true); } } else { // if there is no HTTPSession if(httpSession==null) return getCFSessionScope(pc, isNew); info(getLog(), "create new JSession for "+appContext.getName()+"/"+pc.getCFID()); jSession=new JSession(); httpSession.setAttribute(appContext.getName(),jSession); isNew.setValue(true); Map<String, Scope> context = getSubMap(cfSessionContextes,appContext.getName()); context.put(pc.getCFID(),jSession); } jSession.touchBeforeRequest(pc); return jSession; } /** * return the application Scope for this context (cfid,cftoken,contextname) * @param pc PageContext * @param listener * @param isNew * @return session matching the context * @throws PageException */ public synchronized Application getApplicationScope(PageContext pc, RefBoolean isNew) { ApplicationContext appContext = pc.getApplicationContext(); // getApplication Scope from Context ApplicationImpl application; Object objApp=applicationContextes.get(appContext.getName()); if(objApp!=null) { application=(ApplicationImpl)objApp; if(application.isExpired()) { application.release(); isNew.setValue(true); } } else { application=new ApplicationImpl(); applicationContextes.put(appContext.getName(),application); isNew.setValue(true); } application.touchBeforeRequest(pc); //if(newApplication)listener.onApplicationStart(pc); return application; } public void removeApplicationScope(PageContext pc) { applicationContextes.remove(pc.getApplicationContext().getName()); } /** * remove all unused scope objects */ public void clearUnused() { Log log=getLog(); try{ // create cleaner engine for session/client scope if(session==null)session=new StorageScopeEngine(factory,log,new StorageScopeCleaner[]{ new FileStorageScopeCleaner(Scope.SCOPE_SESSION, null)//new SessionEndListener()) ,new DatasourceStorageScopeCleaner(Scope.SCOPE_SESSION, null)//new SessionEndListener()) //,new CacheStorageScopeCleaner(Scope.SCOPE_SESSION, new SessionEndListener()) }); if(client==null)client=new StorageScopeEngine(factory,log,new StorageScopeCleaner[]{ new FileStorageScopeCleaner(Scope.SCOPE_CLIENT, null) ,new DatasourceStorageScopeCleaner(Scope.SCOPE_CLIENT, null) //,new CacheStorageScopeCleaner(Scope.SCOPE_CLIENT, null) //Cache storage need no control, if there is no listener }); // store session/client scope and remove from memory storeUnusedStorageScope(factory, Scope.SCOPE_CLIENT); storeUnusedStorageScope(factory, Scope.SCOPE_SESSION); // remove unused memory based client/session scope (invoke onSessonEnd) clearUnusedMemoryScope(factory, Scope.SCOPE_CLIENT); clearUnusedMemoryScope(factory, Scope.SCOPE_SESSION); // session must be executed first, because session creates a reference from client scope session.clean(); client.clean(); // clean all unused application scopes clearUnusedApplications(factory); } catch(Throwable t){ error(t); } } /** * remove all scope objects */ public void clear() { try{ Scope scope; //Map.Entry entry,e; //Map context; // release all session scopes Iterator<Entry<String, Map<String, Scope>>> sit = cfSessionContextes.entrySet().iterator(); Entry<String, Map<String, Scope>> sentry; Map<String, Scope> context; Iterator<Entry<String, Scope>> itt; Entry<String, Scope> e; while(sit.hasNext()){ sentry=sit.next(); context = sentry.getValue(); itt = context.entrySet().iterator(); while(itt.hasNext()){ e = itt.next(); scope=e.getValue(); scope.release(); } } cfSessionContextes.clear(); // release all application scopes Iterator<Entry<String, Application>> ait = applicationContextes.entrySet().iterator(); Entry<String, Application> aentry; while(ait.hasNext()){ aentry = ait.next(); scope=aentry.getValue(); scope.release(); } applicationContextes.clear(); // release server scope if(server!=null){ server.release(); server=null; } } catch(Throwable t){t.printStackTrace();} } private void storeUnusedStorageScope(CFMLFactoryImpl cfmlFactory, int type) { Map<String, Map<String, Scope>> contextes = type==Scope.SCOPE_CLIENT?cfClientContextes:cfSessionContextes; long timespan = type==Scope.SCOPE_CLIENT?CLIENT_MEMORY_TIMESPAN:SESSION_MEMORY_TIMESPAN; String strType=VariableInterpreter.scopeInt2String(type); if(contextes.size()==0)return; long now = System.currentTimeMillis(); Object[] arrContextes= contextes.keySet().toArray(); Object applicationName,cfid,o; Map<String, Scope> fhm; for(int i=0;i<arrContextes.length;i++) { applicationName=arrContextes[i]; fhm = contextes.get(applicationName); if(fhm.size()>0){ Object[] arrClients= fhm.keySet().toArray(); int count=arrClients.length; for(int y=0;y<arrClients.length;y++) { cfid=arrClients[y]; o=fhm.get(cfid); if(!(o instanceof StorageScope)) continue; StorageScope scope=(StorageScope)o; if(scope.lastVisit()+timespan<now && !(scope instanceof MemoryScope)) { getLog().info("scope-context", "remove from memory "+strType+" scope for "+applicationName+"/"+cfid+" from storage "+scope.getStorage()); //if(scope instanceof StorageScope)((StorageScope)scope).store(cfmlFactory.getConfig()); fhm.remove(arrClients[y]); count--; } } if(count==0)contextes.remove(arrContextes[i]); } } } /** * @param cfmlFactory * */ private void clearUnusedMemoryScope(CFMLFactoryImpl cfmlFactory, int type) { Map<String, Map<String, Scope>> contextes = type==Scope.SCOPE_CLIENT?cfClientContextes:cfSessionContextes; if(contextes.size()==0)return; Object[] arrContextes= contextes.keySet().toArray(); ApplicationListener listener = cfmlFactory.getConfig().getApplicationListener(); Object applicationName,cfid,o; Map<String, Scope> fhm; for(int i=0;i<arrContextes.length;i++) { applicationName=arrContextes[i]; fhm = contextes.get(applicationName); if(fhm.size()>0){ Object[] cfids= fhm.keySet().toArray(); int count=cfids.length; for(int y=0;y<cfids.length;y++) { cfid=cfids[y]; o=fhm.get(cfid); if(!(o instanceof MemoryScope)) continue; MemoryScope scope=(MemoryScope) o; // close if(scope.isExpired()) { // TODO macht das sinn? ist das nicht kopierleiche? ApplicationImpl application=(ApplicationImpl) applicationContextes.get(applicationName); long appLastAccess=0; if(application!=null){ appLastAccess=application.getLastAccess(); application.touch(); } scope.touch(); try { if(type==Scope.SCOPE_SESSION)listener.onSessionEnd(cfmlFactory,(String)applicationName,(String)cfid); } catch (Throwable t) {t.printStackTrace(); ExceptionHandler.log(cfmlFactory.getConfig(),Caster.toPageException(t)); } finally { if(application!=null)application.setLastAccess(appLastAccess); fhm.remove(cfids[y]); scope.release(); getLog().info("scope-context", "remove memory based "+VariableInterpreter.scopeInt2String(type)+" scope for "+applicationName+"/"+cfid); count--; } } } if(count==0)contextes.remove(arrContextes[i]); } } } private void clearUnusedApplications(CFMLFactoryImpl jspFactory) { if(applicationContextes.size()==0)return; long now=System.currentTimeMillis(); Object[] arrContextes= applicationContextes.keySet().toArray(); ApplicationListener listener = jspFactory.getConfig().getApplicationListener(); for(int i=0;i<arrContextes.length;i++) { Application application=applicationContextes.get(arrContextes[i]); if(application.getLastAccess()+application.getTimeSpan()<now) { //SystemOut .printDate(jspFactory.getConfigWebImpl().getOut(),"Clear application scope:"+arrContextes[i]+"-"+this); application.touch(); try { listener.onApplicationEnd(jspFactory,(String)arrContextes[i]); } catch (Throwable t) { ExceptionHandler.log(jspFactory.getConfig(),Caster.toPageException(t)); } finally { applicationContextes.remove(arrContextes[i]); application.release(); } } } } public void clearApplication(PageContext pc) throws PageException { if(applicationContextes.size()==0) throw new ApplicationException("there is no application context defined"); String name = pc.getApplicationContext().getName(); CFMLFactoryImpl jspFactory = (CFMLFactoryImpl)pc.getCFMLFactory(); Application application=applicationContextes.get(name); if(application==null) throw new ApplicationException("there is no application context defined with name ["+name+"]"); ApplicationListener listener = PageContextUtil.getApplicationListener(pc); application.touch(); try { listener.onApplicationEnd(jspFactory,name); } finally { applicationContextes.remove(name); application.release(); } } /** * @return returns a new CFIs */ public static String getNewCFId() { return generator.generateRandomBasedUUID().toString(); } /** * @return returns a new CFToken */ public static String getNewCFToken() { return "0"; } public synchronized void invalidateUserScope(PageContextImpl pc,boolean migrateSessionData,boolean migrateClientData) throws PageException { ApplicationContext appContext = pc.getApplicationContext(); // get in memory scopes Map<String, Scope> clientContext = getSubMap(cfClientContextes,appContext.getName()); UserScope clientScope = (UserScope) clientContext.get(pc.getCFID()); Map<String, Scope> sessionContext = getSubMap(cfSessionContextes,appContext.getName()); UserScope sessionScope = (UserScope) sessionContext.get(pc.getCFID()); // remove Scopes completly removeSessionScope(pc); removeClientScope(pc); pc.resetIdAndToken(); _migrate(pc,clientContext,clientScope,migrateClientData); _migrate(pc,sessionContext,sessionScope,migrateSessionData); } private static void _migrate(PageContextImpl pc, Map<String, Scope> context, UserScope scope, boolean migrate) { if(scope==null) return; if(!migrate) scope.clear(); scope.resetEnv(pc); context.put(pc.getCFID(), scope); } }