Package railo.runtime.type.scope

Source Code of railo.runtime.type.scope.ScopeContext

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);
  }
 

}
TOP

Related Classes of railo.runtime.type.scope.ScopeContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.