Package org.infoglue.deliver.util

Source Code of org.infoglue.deliver.util.CacheController

/* ===============================================================================
*
* Part of the InfoGlue Content Management Platform (www.infoglue.org)
*
* ===============================================================================
*
*  Copyright (C)
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2, as published by the
* Free Software Foundation. See the file LICENSE.html for more information.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
* Place, Suite 330 / Boston, MA 02111-1307 / USA.
*
* ===============================================================================
*/

package org.infoglue.deliver.util;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.pluto.portalImpl.services.ServiceManager;
import org.apache.pluto.portalImpl.services.portletentityregistry.PortletEntityRegistry;
import org.exolab.castor.jdo.CacheManager;
import org.exolab.castor.jdo.Database;
import org.exolab.castor.jdo.ObjectNotFoundException;
import org.infoglue.cms.applications.common.VisualFormatter;
import org.infoglue.cms.controllers.kernel.impl.simple.AccessRightController;
import org.infoglue.cms.controllers.kernel.impl.simple.CastorDatabaseService;
import org.infoglue.cms.controllers.kernel.impl.simple.ComponentController;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentCategoryController;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentController;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentTypeDefinitionController;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentVersionController;
import org.infoglue.cms.controllers.kernel.impl.simple.DigitalAssetController;
import org.infoglue.cms.controllers.kernel.impl.simple.GroupPropertiesController;
import org.infoglue.cms.controllers.kernel.impl.simple.InterceptionPointController;
import org.infoglue.cms.controllers.kernel.impl.simple.PropertiesCategoryController;
import org.infoglue.cms.controllers.kernel.impl.simple.SiteNodeController;
import org.infoglue.cms.controllers.kernel.impl.simple.SiteNodeVersionController;
import org.infoglue.cms.entities.content.ContentCategoryVO;
import org.infoglue.cms.entities.content.ContentVO;
import org.infoglue.cms.entities.content.ContentVersionVO;
import org.infoglue.cms.entities.content.SmallestContentVersionVO;
import org.infoglue.cms.entities.content.impl.simple.ContentCategoryImpl;
import org.infoglue.cms.entities.content.impl.simple.ContentImpl;
import org.infoglue.cms.entities.content.impl.simple.ContentRelationImpl;
import org.infoglue.cms.entities.content.impl.simple.ContentVersionImpl;
import org.infoglue.cms.entities.content.impl.simple.DigitalAssetImpl;
import org.infoglue.cms.entities.content.impl.simple.MediumContentImpl;
import org.infoglue.cms.entities.content.impl.simple.MediumDigitalAssetImpl;
import org.infoglue.cms.entities.content.impl.simple.SmallContentImpl;
import org.infoglue.cms.entities.content.impl.simple.SmallContentVersionImpl;
import org.infoglue.cms.entities.content.impl.simple.SmallDigitalAssetImpl;
import org.infoglue.cms.entities.content.impl.simple.SmallestContentVersionImpl;
import org.infoglue.cms.entities.content.impl.simple.SmallishContentImpl;
import org.infoglue.cms.entities.management.AccessRightVO;
import org.infoglue.cms.entities.management.ContentTypeDefinitionVO;
import org.infoglue.cms.entities.management.InterceptionPointVO;
import org.infoglue.cms.entities.management.impl.simple.AccessRightGroupImpl;
import org.infoglue.cms.entities.management.impl.simple.AccessRightImpl;
import org.infoglue.cms.entities.management.impl.simple.AccessRightRoleImpl;
import org.infoglue.cms.entities.management.impl.simple.AccessRightUserImpl;
import org.infoglue.cms.entities.management.impl.simple.AvailableServiceBindingImpl;
import org.infoglue.cms.entities.management.impl.simple.CategoryImpl;
import org.infoglue.cms.entities.management.impl.simple.ContentTypeDefinitionImpl;
import org.infoglue.cms.entities.management.impl.simple.FormEntryImpl;
import org.infoglue.cms.entities.management.impl.simple.FormEntryValueImpl;
import org.infoglue.cms.entities.management.impl.simple.GroupContentTypeDefinitionImpl;
import org.infoglue.cms.entities.management.impl.simple.GroupImpl;
import org.infoglue.cms.entities.management.impl.simple.GroupPropertiesImpl;
import org.infoglue.cms.entities.management.impl.simple.InterceptionPointImpl;
import org.infoglue.cms.entities.management.impl.simple.InterceptorImpl;
import org.infoglue.cms.entities.management.impl.simple.LanguageImpl;
import org.infoglue.cms.entities.management.impl.simple.PropertiesCategoryImpl;
import org.infoglue.cms.entities.management.impl.simple.RedirectImpl;
import org.infoglue.cms.entities.management.impl.simple.RegistryImpl;
import org.infoglue.cms.entities.management.impl.simple.RepositoryImpl;
import org.infoglue.cms.entities.management.impl.simple.RepositoryLanguageImpl;
import org.infoglue.cms.entities.management.impl.simple.RoleContentTypeDefinitionImpl;
import org.infoglue.cms.entities.management.impl.simple.RoleImpl;
import org.infoglue.cms.entities.management.impl.simple.RolePropertiesImpl;
import org.infoglue.cms.entities.management.impl.simple.ServerNodeImpl;
import org.infoglue.cms.entities.management.impl.simple.ServiceDefinitionImpl;
import org.infoglue.cms.entities.management.impl.simple.SiteNodeTypeDefinitionImpl;
import org.infoglue.cms.entities.management.impl.simple.SmallAvailableServiceBindingImpl;
import org.infoglue.cms.entities.management.impl.simple.SmallGroupImpl;
import org.infoglue.cms.entities.management.impl.simple.SmallRoleImpl;
import org.infoglue.cms.entities.management.impl.simple.SmallSystemUserImpl;
import org.infoglue.cms.entities.management.impl.simple.SubscriptionImpl;
import org.infoglue.cms.entities.management.impl.simple.SystemUserGroupImpl;
import org.infoglue.cms.entities.management.impl.simple.SystemUserImpl;
import org.infoglue.cms.entities.management.impl.simple.SystemUserRoleImpl;
import org.infoglue.cms.entities.management.impl.simple.UserContentTypeDefinitionImpl;
import org.infoglue.cms.entities.management.impl.simple.UserPropertiesImpl;
import org.infoglue.cms.entities.publishing.impl.simple.PublicationImpl;
import org.infoglue.cms.entities.structure.SiteNodeVO;
import org.infoglue.cms.entities.structure.SiteNodeVersionVO;
import org.infoglue.cms.entities.structure.impl.simple.QualifyerImpl;
import org.infoglue.cms.entities.structure.impl.simple.ServiceBindingImpl;
import org.infoglue.cms.entities.structure.impl.simple.SiteNodeImpl;
import org.infoglue.cms.entities.structure.impl.simple.SiteNodeVersionImpl;
import org.infoglue.cms.entities.structure.impl.simple.SmallSiteNodeImpl;
import org.infoglue.cms.entities.structure.impl.simple.SmallSiteNodeVersionImpl;
import org.infoglue.cms.entities.workflow.impl.simple.ActionDefinitionImpl;
import org.infoglue.cms.entities.workflow.impl.simple.ActionImpl;
import org.infoglue.cms.entities.workflow.impl.simple.ActorImpl;
import org.infoglue.cms.entities.workflow.impl.simple.ConsequenceDefinitionImpl;
import org.infoglue.cms.entities.workflow.impl.simple.ConsequenceImpl;
import org.infoglue.cms.entities.workflow.impl.simple.EventImpl;
import org.infoglue.cms.entities.workflow.impl.simple.WorkflowDefinitionImpl;
import org.infoglue.cms.entities.workflow.impl.simple.WorkflowImpl;
import org.infoglue.cms.exception.Bug;
import org.infoglue.cms.exception.SystemException;
import org.infoglue.cms.io.FileHelper;
import org.infoglue.cms.security.InfoGlueAuthenticationFilter;
import org.infoglue.cms.util.CmsPropertyHandler;
import org.infoglue.cms.util.sorters.CacheComparator;
import org.infoglue.cms.util.workflow.InfoGlueJDBCPropertySet;
import org.infoglue.deliver.applications.actions.InfoGlueComponent;
import org.infoglue.deliver.applications.databeans.CacheEvictionBean;
import org.infoglue.deliver.applications.databeans.DatabaseWrapper;
import org.infoglue.deliver.cache.PageCacheHelper;
import org.infoglue.deliver.invokers.PageInvoker;
import org.infoglue.deliver.portal.ServletConfigContainer;
import org.xmlpull.v1.builder.XmlDocument;
import org.xmlpull.v1.builder.XmlElement;
import org.xmlpull.v1.builder.XmlInfosetBuilder;
import org.xmlpull.v1.builder.xpath.Xb1XPath;

import com.opensymphony.oscache.base.AbstractCacheAdministrator;
import com.opensymphony.oscache.base.CacheEntry;
import com.opensymphony.oscache.base.NeedsRefreshException;
import com.opensymphony.oscache.base.algorithm.ImprovedLRUCache;
import com.opensymphony.oscache.base.events.CacheEntryEventListener;
import com.opensymphony.oscache.base.events.CacheMapAccessEventListener;
import com.opensymphony.oscache.extra.CacheEntryEventListenerImpl;
import com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl;
import com.opensymphony.oscache.general.GeneralCacheAdministrator;


public class CacheController extends Thread
{
  private static long readLockTimeout = 5;
  private static long writeLockTimeout = 50;
    public final static Logger logger = Logger.getLogger(CacheController.class.getName());
  private static VisualFormatter formatter = new VisualFormatter();

  public static final String SETTINGSPROPERTIESCACHENAME = "serverNodePropertiesCache";
  public static final String SETTINGSPROPERTIESDOCUMENTCACHENAME = "serverNodePropertiesDocumentCache";

    public static List notifications = Collections.synchronizedList(new ArrayList());
   
    private static Map eventListeners = new HashMap();
  //private static Map caches = new HashMap();
  private static ConcurrentMap caches = new ConcurrentHashMap();
 
  //private static Map caches = Collections.synchronizedMap(new HashMap());
  private boolean expireCacheAutomatically = false;
  private int cacheExpireInterval = 1800000;
  private boolean continueRunning = true;
  public static Pattern pattern = null;
   
    public static Date expireDateTime = null;
    public static Date publishDateTime = null;
    
    private static Map<Integer, Integer> assetContentIdMapping = new HashMap<Integer, Integer>();

    private static CompressionHelper compressionHelper = new CompressionHelper();
  
  private static AtomicInteger numberOfPageCacheFiles = new AtomicInteger(0);
 
  //Force mode only happens when a cache eviction has to wait to long. Then we switch to force mode
    private static class ThreadLocalCacheEvictionMode extends ThreadLocal
    {
      public Object initialValue()
        {
          return false;
        }
    }

    //boolean forcedCacheEvictionMode = false;
    private static ThreadLocalCacheEvictionMode cem = new ThreadLocalCacheEvictionMode();

    public static Boolean getForcedCacheEvictionMode()
    {
        return (Boolean) cem.get();
    }
    public static void setForcedCacheEvictionMode(Boolean cemValue)
    {
      if(logger.isInfoEnabled())
        logger.info("Forcing quick cache eviction...");
        cem.set(cemValue);
    }
   
  //Force defeatCaches-mode
    private static class ThreadLocalDefeatCacheMode extends ThreadLocal<DefeatCacheParameters>
    {
      public DefeatCacheParameters initialValue()
        {
          return new DefeatCacheParameters();
        }
    }

    private static ThreadLocalDefeatCacheMode defeatCaches = new ThreadLocalDefeatCacheMode();

    public static DefeatCacheParameters getDefeatCaches()
    {
        return (DefeatCacheParameters) defeatCaches.get();
    }
   
    public static void setDefeatCaches(boolean defeatCache, Map<Class, List<Object>> entities)
    {
      DefeatCacheParameters defeatCachesValue = new DefeatCacheParameters();
      defeatCachesValue.setDefeatCache(defeatCache);
      if(entities != null)
        defeatCachesValue.getEntities().putAll(entities);
     
      if(logger.isInfoEnabled())
        logger.info("Forcing defeatCaches...");

      defeatCaches.set(defeatCachesValue);

      boolean skipClearCastor = false;
      if(defeatCaches.get().getEntities() == null || defeatCaches.get().getEntities().size() == 0)
        skipClearCastor = true;

      if(defeatCache && defeatCaches.get() != null && !skipClearCastor)
      {
        try
        {
        clearCastorCaches(defeatCaches.get());
      }
        catch (Exception e)
        {
          logger.error("Error setting defeatCaches:" + e.getMessage(), e);
      }
      }
      else if(defeatCache && skipClearCastor)
      {
        logger.info("Skipping clearCastorCaches as entities was null");
      }
    }

  //Store extra info
    private static class ThreadLocalNotificationExtraInformation extends ThreadLocal<Map<String,Map<String,String>>>
    {
      public Map<String,Map<String,String>> initialValue()
        {
          return new HashMap<String,Map<String,String>>();
        }
    }

    private static ThreadLocalNotificationExtraInformation extraInfo = new ThreadLocalNotificationExtraInformation();

    public static Map<String, String> getExtraInfo(String entityClassName, String entityId)
    {
      Map<String, Map<String,String>> allExtra = (Map<String, Map<String,String>>) extraInfo.get();
      //System.out.println("Returning allExtra for: " + entityClassName + "_" + entityId + ":" + allExtra.get(entityClassName + "_" + entityId));
        return allExtra.get(entityClassName + "_" + entityId);
    }
   
    public static void setExtraInfo(String entityClassName, String entityId, Map<String,String> extraInfoMap)
    {
      //System.out.println("Adding extraInfoMap:" + extraInfoMap + " TO " + entityClassName + "_" + entityId);
      Map<String, Map<String,String>> allExtra = (Map<String, Map<String,String>>) extraInfo.get();
      //System.out.println("Adding allExtra for: " + entityClassName + "_" + entityId + ":" + allExtra);
      Map existingMap = getExtraInfo(entityClassName, entityId);
      if(existingMap == null)
        allExtra.put(entityClassName + "_" + entityId, extraInfoMap);
      else
        existingMap.putAll(extraInfoMap);
    }

  private static StringPool stringPool = new StringPool();
  public static String getPooledString(Integer type, Object id)
  {
    if(type == null || id == null)
    {
      logger.info("Broken was returned from pool:" + type + ":" + id);
      return "broken";
    }
   
    return stringPool.getCanonicalVersion(type, id.toString());
  }
  public static String getPooledString(int hashCode)
  {
    return stringPool.getCanonicalVersion(hashCode);
  }

  public static Integer getPooledStringSize()
  {
    return stringPool.getPoolSize();
  }
  public static Integer getPooledStringHits()
  {
    return stringPool.getHits();
  }
  public static void clearPooledString()
  {
    stringPool.clearPool();
  }
 
  public CacheController()
  {
    super();
  }

  public static void preCacheCMSEntities() throws Exception
  {
    Timer t = new Timer();
    ContentTypeDefinitionController.getController().getContentTypeDefinitionVOList();
    logger.warn("pre cache content types took:" + t.getElapsedTime());

    ComponentController.getController().preCacheComponents(-1);
    logger.warn("preCacheComponents took:" + t.getElapsedTime());
   
    List<SiteNodeVO> snVOList = SiteNodeController.getController().getSiteNodeVOList(false, 0, 30000);
    logger.warn("snVOList:" + snVOList.size() + " fetched and precached in " + t.getElapsedTime() + " ms");

    List<ContentVO> cList = ContentController.getContentController().getContentVOList(10000);
    logger.warn("cList:" + snVOList.size() + " fetched and precached in " + t.getElapsedTime() + " ms");
   
    /*
    List<SiteNodeVO> snVOList = SiteNodeController.getController().getSiteNodeVOList(false, 0, 10000);
    logger.info("snVOList:" + snVOList.size() + " fetched and precached");

    List<SiteNodeVersionVO> snvVOList = SiteNodeController.getController().getSiteNodeVersionVOList(false, 0, 10000);
    logger.info("snvVOList:" + snvVOList.size() + " fetched and precached");

    List<ContentVO> cList = ContentController.getContentController().getContentVOList(false, 10000);
    logger.info("cList:" + cList.size() + " fetched and precached");
   
    List<ContentVersionVO> cvList = ContentVersionController.getContentVersionController().getContentVersionVOList(null, false, 0);
    logger.info("cvList:" + cvList.size() + " fetched and precached");
    */
  }

  public static void preCacheDeliverEntities() throws Exception
  {
    Timer t = new Timer();
   
    class PreCacheGroupPropertiesTask implements Runnable
    {
      PreCacheGroupPropertiesTask() { }
         
          public void run()
          {
        try
        {
          Timer t = new Timer();
          Database db = CastorDatabaseService.getDatabase();
          try
          {
            beginTransaction(db);

            GroupPropertiesController.getController().preCacheAllGroupProperties(db);
            logger.warn("preCacheAllGroupProperties took: " + t.getElapsedTime());
            commitTransaction(db);
          }
          catch (Exception e)
          {
            logger.error("Error precaching all group properties: " + e.getMessage(), e);
            rollbackTransaction(db);
          }
        }
        catch (Exception e)
        {
          logger.error("Could not start PreCacheTask:" + e.getMessage(), e);
        }
        finally
        {
          GroupPropertiesController.inCacheProgress.set(false);
        }
          }
      }
    if(GroupPropertiesController.inCacheProgress.compareAndSet(false, true))
    {
      Thread thread = new Thread(new PreCacheGroupPropertiesTask());
        thread.start();
    }
   
    if(CacheController.getCacheSize("propertiesCategoryCache") == 0 && GroupPropertiesController.preCacheInProgress.compareAndSet(false, true))
    {
      try
      {
        PropertiesCategoryController.getController().preCacheAllPropertiesCategoryVOList();
      }
      finally
      {
        GroupPropertiesController.preCacheInProgress.set(false);
      }
      logger.warn("preCacheAllPropertiesCategoryVOList took: " + t.getElapsedTime());
    }
   
    ContentTypeDefinitionController.getController().getContentTypeDefinitionVOList();
    logger.warn("pre cache content types took:" + t.getElapsedTime());
   
    ComponentController.getController().preCacheComponents(-1);
    logger.warn("preCacheComponents took:" + t.getElapsedTime());
   
    List<SiteNodeVO> snVOList = SiteNodeController.getController().getSiteNodeVOList(false, new Integer(CmsPropertyHandler.getOperatingMode()), 30000);
    logger.warn("snVOList:" + snVOList.size() + " fetched and precached in " + t.getElapsedTime() + " ms");

    List<ContentVO> cList = ContentController.getContentController().getContentVOList(10000);
    logger.warn("cList:" + snVOList.size() + " fetched and precached in " + t.getElapsedTime() + " ms");

    /*
    FileInputStream fis = new FileInputStream(CmsPropertyHandler.getDigitalAssetPath() + File.separator + "startupCache.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Map<Integer,Integer> mostUsedContentId = (Map<Integer,Integer>) ois.readObject();
        ois.close();
        */
   
    /*
    List<SiteNodeVO> snVOList = SiteNodeController.getController().getSiteNodeVOList(false, 0, 100000);
    logger.info("snVOList:" + snVOList.size() + " fetched and precached");

    List<SiteNodeVersionVO> snvVOList = SiteNodeController.getController().getSiteNodeVersionVOList(false, 0, 100000);
    logger.info("snvVOList:" + snvVOList.size() + " fetched and precached");

    List<ContentVO> cList = ContentController.getContentController().getContentVOList(false, 100000);
    logger.info("cList:" + cList.size() + " fetched and precached");
   

    List<ContentVersionVO> cvList = ContentVersionController.getContentVersionController().getContentVersionVOList(null, false, 0, 100000);
    logger.info("cvList:" + cvList.size() + " fetched and precached");
    */
  }

 
 

  public void setCacheExpireInterval(int cacheExpireInterval)
  {
    this.cacheExpireInterval = cacheExpireInterval;
  }

  public static void renameCache(String cacheName, String newCacheName)
  {
    //synchronized(caches)
    //{
        Object cacheInstance = caches.get(cacheName);
       
        if(cacheInstance != null)
        {
            synchronized(cacheInstance)
            {
                caches.put(newCacheName, cacheInstance);
                //locksCache.put(newCacheName, new ReentrantReadWriteLock());
                caches.remove(cacheName);
            }
        }
    //}
 
 
  public static void clearServerNodeProperty(boolean reCache)
  {
    if(reCache)
      InfoGlueJDBCPropertySet.reCache();
       else
         InfoGlueJDBCPropertySet.clearCaches();
    clearCache("serverNodePropertiesCache");
    clearCache("encodedStringsCache");
    clearCache("principalToolPropertiesCache");
    CmsPropertyHandler.resetHardCachedSettings();
     }
 
  public static void cacheObject(String cacheName, Object key, Object value)
  {
    if(cacheName == null || key == null || value == null)
      return;
     
    //synchronized(caches)
    //{
      if(caches.get(cacheName) == null)
          caches.put(cacheName, new HashMap());
    //}
     
    //synchronized(caches)
    //{
      Map cacheInstance = (Map)caches.get(cacheName);
      if(cacheInstance != null && key != null && value != null)
        {
        if(CmsPropertyHandler.getUseSynchronizationOnCaches())
        {
          synchronized(cacheInstance)
          {
              if(CmsPropertyHandler.getUseHashCodeInCaches())
                cacheInstance.put("" + key.hashCode(), value);
              else
                cacheInstance.put(key, value);
            }
        }
        else
        {
             if(CmsPropertyHandler.getUseHashCodeInCaches())
              cacheInstance.put("" + key.hashCode(), value);
            else
              cacheInstance.put(key, value);
         }
        }
    //}
 
 
  public static Object getCachedObject(String cacheName, Object key)
  {
    if(cacheName == null || key == null)
      return null;
   
    if(getDefeatCaches() != null && getDefeatCaches().getDefeatCache("" + cacheName + "_" + key))
    {
      if(!cacheName.equals("serverNodePropertiesCache") &&
         !cacheName.equals("contentTypeDefinitionCache")
      )
      {
        if (logger.isInfoEnabled())
        {
          logger.info("Missed cache: " + cacheName + " because of defeat caches. Cache.key: " + key);
        }
        return null;
      }
    }
   
    //synchronized(caches)
    //{
      Map cacheInstance = (Map)caches.get(cacheName);
      if(cacheInstance != null)
        {
        //TODO
        if(CmsPropertyHandler.getUseSynchronizationOnCaches())
        {
          synchronized(cacheInstance)
          {
            if(CmsPropertyHandler.getUseHashCodeInCaches())
              return cacheInstance.get("" + key.hashCode());
            else
              return cacheInstance.get(key);
          }
        }
        else
        {
          if(CmsPropertyHandler.getUseHashCodeInCaches())
            return cacheInstance.get("" + key.hashCode());
          else
            return cacheInstance.get(key);
        }
        }
    //}
   
        return null;
    }

  public static void cacheObjectInAdvancedCacheWithGroupsAsSet(String cacheName, Object key, Object value, Set<String> groupsAsList, boolean useGroups)
  {
    String[] groups = groupsAsList.toArray(new String[0]);
   
    cacheObjectInAdvancedCache(cacheName, key, value, groups, useGroups);
  }

  public static void cacheObjectInAdvancedCache(String cacheName, Object key, Object value)
  {
    cacheObjectInAdvancedCache(cacheName, key, value, null, false);
  }

  public static void cacheObjectInAdvancedCache(String cacheName, Object key, Object value, boolean useFileCacheFallback, String fileCacheCharEncoding)
  {
    cacheObjectInAdvancedCache(cacheName, key, value, null, false, useFileCacheFallback, true, fileCacheCharEncoding);
  }

  public static void cacheObjectInAdvancedCache(String cacheName, Object key, Object value, String[] groups, boolean useGroups)
  {
    cacheObjectInAdvancedCache(cacheName, key, value, groups, useGroups, false, true, null);
  }
 
  public static void cacheObjectInAdvancedCache(String cacheName, Object key, Object value, String[] groups, boolean useGroups, boolean useFileCacheFallback, boolean useMemoryCache, String fileCacheCharEncoding)
  {
    if(cacheName == null || key == null || value == null || key.toString().length() == 0)
      return;
   
    if(defeatCaches.get().getDefeatCache())
      defeatCaches.get().setDefeatedKey("" + cacheName + "_" + key.toString());

    /*
    if(cacheName.equalsIgnoreCase("pageCacheExtra"))
      System.out.println("key pageCacheExtra: " + key);
    if(cacheName.equalsIgnoreCase("pageCache"))
      System.out.println("key pageCache: " + key);
    */
   
    if(logger.isInfoEnabled() && cacheName.equalsIgnoreCase("pageCacheExtra"))
    {     
      logger.info("cacheName: " + cacheName);
      logger.info("key: " + key);
      logger.info("useGroups: " + useGroups);
      logger.info("useFileCacheFallback: " + useFileCacheFallback);
      logger.info("useMemoryCache: "+ useMemoryCache);
      logger.info("groups: " + (groups == null ? "null" : groups.length));
      if(groups != null)
      {
        for(String group : groups)
          logger.info(group + ",");
      }
    }

    if(useMemoryCache)
    {
        if(!caches.containsKey(cacheName))
        {
          GeneralCacheAdministrator cacheAdministrator = null;
          Map cacheSettings = (Map)getCachedObject("serverNodePropertiesCacheSettings", "cacheSettings");
          if(cacheSettings == null)
          {
            cacheSettings = CmsPropertyHandler.getCacheSettings();
            cacheObject("serverNodePropertiesCacheSettings", "cacheSettings", cacheSettings);
          }
         
          String cacheCapacity = (String)cacheSettings.get("CACHE_CAPACITY_" + cacheName);
          if(cacheCapacity == null || !cacheCapacity.equals(""))
            cacheCapacity = "15000";
                   
          if(cacheName != null && cacheName.startsWith("contentAttributeCache"))
            cacheCapacity = "50000";
          if(cacheName != null && cacheName.startsWith("metaInfoContentAttributeCache"))
            cacheCapacity = "40000";
          //else if(cacheName != null && cacheName.startsWith("contentAttributeCache"))
          //  cacheCapacity = "1000";
          String pageCacheSize = "100";
          String pageCacheExtraSize = "300";
          if(CmsPropertyHandler.getOperatingMode().equals("3"))
          {
            pageCacheSize = "10000";
            pageCacheExtraSize = "30000";
          }
         
          if(cacheName != null && cacheName.startsWith("pageCache"))
            cacheCapacity = pageCacheSize;
          if(cacheName != null && cacheName.startsWith("pageCacheExtra"))
            cacheCapacity = pageCacheExtraSize;
        if(cacheName != null && cacheName.equalsIgnoreCase("encodedStringsCache"))
          cacheCapacity = "2000";
        if(cacheName != null && cacheName.equalsIgnoreCase("assetUrlCacheWithGroups"))
          cacheCapacity = "10000";
        if(cacheName != null && cacheName.equalsIgnoreCase("importTagResultCache"))
          cacheCapacity = "500";
        if(cacheName != null && cacheName.equalsIgnoreCase("componentPropertyCache"))
          cacheCapacity = "10000";
        if(cacheName != null && cacheName.equalsIgnoreCase("componentPropertyVersionIdCache"))
          cacheCapacity = "10000";
        if(cacheName != null && cacheName.equalsIgnoreCase("componentPropertyCacheRepoGroups"))
          cacheCapacity = "5000";
        if(cacheName != null && cacheName.equalsIgnoreCase("componentPropertyVersionIdCacheRepoGroups"))
          cacheCapacity = "5000";
        if(cacheName != null && cacheName.equalsIgnoreCase("componentEditorCache"))
            cacheCapacity = "3000";
        if(cacheName != null && cacheName.equalsIgnoreCase("componentEditorVersionIdCache"))
            cacheCapacity = "3000";
        if(cacheName != null && cacheName.equalsIgnoreCase("contentVersionIdCache"))
            cacheCapacity = "30000";
        if(cacheName != null && cacheName.equalsIgnoreCase("contentVersionCache"))
            cacheCapacity = "30000";
        if(cacheName != null && cacheName.equalsIgnoreCase("pageComponentsCache"))
            cacheCapacity = "10000";
        if(cacheName != null && cacheName.equalsIgnoreCase("boundContentCache"))
            cacheCapacity = "5000";
        if(cacheName != null && cacheName.equalsIgnoreCase("childSiteNodesCache"))
            cacheCapacity = "20000";
        if(cacheName != null && cacheName.equalsIgnoreCase("childPagesCache"))
            cacheCapacity = "20000";
        if(cacheName != null && cacheName.equalsIgnoreCase("siteNodeCache"))
            cacheCapacity = "20000";
        if(cacheName != null && cacheName.equalsIgnoreCase("contentCache"))
            cacheCapacity = "20000";
        if(cacheName != null && cacheName.equalsIgnoreCase("latestSiteNodeVersionCache"))
            cacheCapacity = "20000";
        if(cacheName != null && cacheName.equalsIgnoreCase("pageDeliveryMetaDataCache"))
            cacheCapacity = "50000";
       
        /*
        if(cacheCapacity.length() > 4)
          cacheCapacity = "10000";
        */
        /*
        if(cacheName != null && (cacheName.equalsIgnoreCase("contentAttributeCache_Title") ||
                     cacheName.equalsIgnoreCase("contentAttributeCache_NavigationTitle") ||
                     cacheName.equalsIgnoreCase("contentAttributeCache_hideInNavigation") ||
                     cacheName.equalsIgnoreCase("contentAttributeCache_SortOrder")))
        {
          cacheCapacity = "100000";
        }
        */
       
        if(cacheCapacity != null && !cacheCapacity.equals(""))
          {
          Properties p = new Properties();
          String cacheAlgorithm = (String)cacheSettings.get("CACHE_ALGORITHM_" + cacheName);
          if(cacheAlgorithm == null || cacheAlgorithm.equals(""))
            p.setProperty(AbstractCacheAdministrator.CACHE_ALGORITHM_KEY, "com.opensymphony.oscache.base.algorithm.ImprovedLRUCache");
          else
            p.setProperty(AbstractCacheAdministrator.CACHE_ALGORITHM_KEY, cacheAlgorithm);
         
          //p.setProperty(AbstractCacheAdministrator.CACHE_ALGORITHM_KEY, "com.opensymphony.oscache.base.algorithm.LRUCache");
          p.setProperty(AbstractCacheAdministrator.CACHE_CAPACITY_KEY, cacheCapacity);
          cacheAdministrator = new GeneralCacheAdministrator(p);
        }
        else
        {
          cacheAdministrator = new GeneralCacheAdministrator();
        }
           
            CacheEntryEventListenerImpl cacheEntryEventListener = new ExtendedCacheEntryEventListenerImpl();
        CacheMapAccessEventListenerImpl cacheMapAccessEventListener = new CacheMapAccessEventListenerImpl();
           
        cacheAdministrator.getCache().addCacheEventListener(cacheEntryEventListener, CacheEntryEventListener.class);
        cacheAdministrator.getCache().addCacheEventListener(cacheMapAccessEventListener, CacheMapAccessEventListener.class);
        caches.put(cacheName, cacheAdministrator);
        //locksCache.put(cacheName, new ReentrantReadWriteLock());
        }
       
      GeneralCacheAdministrator cacheAdministrator = (GeneralCacheAdministrator)caches.get(cacheName);
     
      //if(cacheName.startsWith("contentAttribute")/* || cacheName.startsWith("contentVersionIdCache")*/)
      //  useGroups = false;

      //boolean containsSelectiveCacheUpdateNonApplicable = false;
      if(groups != null)
      {
        List<String> groupCandidateListStandard = new ArrayList<String>();
        List<String> groupCandidateListSpecial = new ArrayList<String>();
        for(int i=0; i<groups.length; i++)
        {
          if(groups[i].startsWith("content") || groups[i].startsWith("siteNode"))
            groupCandidateListStandard.add(groups[i]);
          else
            groupCandidateListSpecial.add(groups[i]);
        }
       
        if(!groupCandidateListSpecial.contains("selectiveCacheUpdateNonApplicable"))
        {
          groupCandidateListSpecial.addAll(groupCandidateListStandard);
        }
        String[] newGroups = new String[groupCandidateListSpecial.size()];
        groups = groupCandidateListSpecial.toArray(newGroups);
      }
     
      if(logger.isInfoEnabled() && cacheName.equalsIgnoreCase("pageCacheExtra"))
      {
        logger.info("real groups: " + (groups == null ? "null" : groups.length));
        if(groups != null)
        {
          for(String group : groups)
            logger.info(group + ",");
        }
      }
     
      //Kanske tillbaka om minnet sticker
      if(cacheName.equals("componentPropertyCache") || cacheName.equals("componentPropertyVersionIdCache"))
      {       
        //logger.error("Skipping useGroups on " + cacheName + ". Groups was:" + groups.length + " for " + key);
        useGroups = false;
      }
      /*
      if(cacheName.equals("componentPropertyCache") || cacheName.equals("componentPropertyVersionIdCache"))
      {       
        //logger.error("Skipping useGroups on " + cacheName + ". Groups was:" + groups.length + " for " + key);
        useGroups = false;
      }
      */
           
      /*
      if(cacheName.startsWith("pageCache"))
      {
        //logger.error("Skipping useGroups on pageCache. Groups was:" + groups.length + " for " + key);
        useGroups = false;       
      }
      */
           
      //TODO
      if(CmsPropertyHandler.getUseSynchronizationOnCaches())
      {
        synchronized(cacheAdministrator) //Back
          {
          try
          {
            if(useGroups)
            {
              if(CmsPropertyHandler.getUseHashCodeInCaches())
                cacheAdministrator.putInCache("" + key.toString().hashCode(), value, groups);
              else
                cacheAdministrator.putInCache(key.toString(), value, groups);
            }
            else
            {
              if(CmsPropertyHandler.getUseHashCodeInCaches())
                cacheAdministrator.putInCache("" + key.toString().hashCode(), value);
              else
                  cacheAdministrator.putInCache(key.toString(), value);
            }
          }
          catch (Exception e)
          {
            logger.warn("Error putting in cache:" + e.getMessage());
          }
                //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Putting object in " + cacheName, t.getElapsedTime());
        }
      }
      else
      {
        try
        {
          if(useGroups)
          {
            if(CmsPropertyHandler.getUseHashCodeInCaches())
              cacheAdministrator.putInCache("" + key.toString().hashCode(), value, groups);
            else
              cacheAdministrator.putInCache(key.toString(), value, groups);
          }
          else
          {
            if(CmsPropertyHandler.getUseHashCodeInCaches())
              cacheAdministrator.putInCache("" + key.toString().hashCode(), value);
            else
                cacheAdministrator.putInCache(key.toString(), value);
          }
        }
        catch (Exception e)
        {
          logger.warn("Error putting in cache:" + e.getMessage(), e);
        }
      }
    }
     
    //  logger.info("numberOfPageCacheFiles:" + numberOfPageCacheFiles.get());
    if(cacheName.equals("pageCache") && numberOfPageCacheFiles.get() > 30000)
    {
      if(logger.isInfoEnabled())
        logger.info("Skipping file cache as to many files were allready there");
      useFileCacheFallback = false;
    }

    //if(cacheName.equals("pageCache"))
    //  logger.info("useFileCacheFallback:" + useFileCacheFallback + " - useGroups:" + useGroups);
      if(useFileCacheFallback && !useGroups)
      {
        if(logger.isInfoEnabled())
          logger.info("Caching value to disk also");
       
        String compressPageCache = CmsPropertyHandler.getCompressPageCache();
       
        //System.out.println("Caching in file...:" + value.toString());
        if(cacheName.equals("pageCache") && compressPageCache != null && compressPageCache.equals("true"))
          putCachedCompressedContentInFile(cacheName, key.toString(), (byte[])value);             
        else
          putCachedContentInFile(cacheName, key.toString(), value.toString(), fileCacheCharEncoding);             
      }

   
    //logger.info("Done cacheObjectInAdvancedCache");
  }
  /*
  public static void printLockDebug(ReentrantReadWriteLock rwl) {
    System.out.println("CurrentThread hasLock: " + rwl.writeLock().isHeldByCurrentThread());
    System.out.println("CurrentThread getWriteHoldCount: " + rwl.getWriteHoldCount());
    System.out.println("CurrentThread getWriteHoldCount: " + rwl.getReadLockCount());
    System.out.println("CurrentThread getQueueLength: " + rwl.getQueueLength());
    System.out.println("CurrentThread hasQueuedThreads: " + rwl.hasQueuedThreads());
    System.out.println("CurrentThread isWriteLocked: " + rwl.isWriteLocked());
  } 
  */

  public static void cacheObjectInAdvancedCache(String cacheName, Object key, Object value, boolean useFileCacheFallback, boolean useMemoryCache, String fileCacheCharEncoding, Integer memoryCacheSize, boolean unlimitedDiskCache)
  {
    cacheObjectInAdvancedCache(cacheName, key, value, null, false, useFileCacheFallback, useMemoryCache, fileCacheCharEncoding, memoryCacheSize, unlimitedDiskCache, false);
  }
 
  public static void cacheObjectInAdvancedCache(String cacheName, Object key, Object value, String[] groups, boolean useGroups, boolean useFileCacheFallback, boolean useMemoryCache, String fileCacheCharEncoding, Integer memoryCacheSize, boolean unlimitedDiskCache, boolean persistentCachesBetweenRestarts)
  {
    if(cacheName == null || key == null || value == null || key.toString().length() == 0)
      return;
   
    if(defeatCaches.get().getDefeatCache())
      defeatCaches.get().setDefeatedKey("" + cacheName + "_" + key.toString());

    if(logger.isInfoEnabled())
    {     
      logger.info("cacheName: " + cacheName);
      logger.info("key: " + key);
      logger.info("useFileCacheFallback: " + useFileCacheFallback);
      logger.info("useMemoryCache: "+ useMemoryCache);
      logger.info("fileCacheCharEncoding: "+ fileCacheCharEncoding);
      logger.info("memoryCacheSize: "+ memoryCacheSize);
      logger.info("unlimitedDiskCache: "+ unlimitedDiskCache);
      logger.info("persistentCachesBetweenRestarts: "+ persistentCachesBetweenRestarts);
    }

      if(!caches.containsKey(cacheName))
      {
        GeneralCacheAdministrator cacheAdministrator = null;
     
      Properties p = new Properties();
     
      p.setProperty(AbstractCacheAdministrator.CACHE_MEMORY_KEY, Boolean.toString(useMemoryCache));
      p.setProperty(AbstractCacheAdministrator.CACHE_DISK_UNLIMITED_KEY, Boolean.toString(unlimitedDiskCache));
      p.setProperty(AbstractCacheAdministrator.CACHE_CAPACITY_KEY, "" + memoryCacheSize);
      p.setProperty(AbstractCacheAdministrator.CACHE_PERSISTENCE_OVERFLOW_KEY, Boolean.toString(useFileCacheFallback));
     
      p.setProperty(AbstractCacheAdministrator.CACHE_ALGORITHM_KEY, "com.opensymphony.oscache.base.algorithm.ImprovedLRUCache");
      p.setProperty("cache.persistence.class", "com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener");
      p.setProperty("cache.path", CmsPropertyHandler.getDigitalAssetPath() + File.separator + (persistentCachesBetweenRestarts ? "persistentCaches" : "caches") + File.separator + cacheName);
     
      cacheAdministrator = new GeneralCacheAdministrator(p);
     
      //Adding one entry just to get the disk cache active
      if(useFileCacheFallback && memoryCacheSize == 1)
         cacheAdministrator.putInCache("dummy", "value");
     
          //CacheEntryEventListenerImpl cacheEntryEventListener = new ExtendedCacheEntryEventListenerImpl();
      //CacheMapAccessEventListenerImpl cacheMapAccessEventListener = new CacheMapAccessEventListenerImpl();
         
      //cacheAdministrator.getCache().addCacheEventListener(cacheEntryEventListener, CacheEntryEventListener.class);
      //cacheAdministrator.getCache().addCacheEventListener(cacheMapAccessEventListener, CacheMapAccessEventListener.class);
          caches.put(cacheName, cacheAdministrator);
          //locksCache.put(cacheName, new ReentrantReadWriteLock());
          //eventListeners.put(cacheName + "_cacheEntryEventListener", cacheEntryEventListener);
          //eventListeners.put(cacheName + "_cacheMapAccessEventListener", cacheMapAccessEventListener);
      }
     
    GeneralCacheAdministrator cacheAdministrator = (GeneralCacheAdministrator)caches.get(cacheName);
     
    if(groups != null)
    {
      List<String> groupCandidateListStandard = new ArrayList<String>();
      List<String> groupCandidateListSpecial = new ArrayList<String>();
      for(int i=0; i<groups.length; i++)
      {
        if(groups[i].startsWith("content") || groups[i].startsWith("siteNode"))
          groupCandidateListStandard.add(groups[i]);
        else
          groupCandidateListSpecial.add(groups[i]);
      }
     
      if(!groupCandidateListSpecial.contains("selectiveCacheUpdateNonApplicable"))
      {
        groupCandidateListSpecial.addAll(groupCandidateListStandard);
      }
      String[] newGroups = new String[groupCandidateListSpecial.size()];
      groups = groupCandidateListSpecial.toArray(newGroups);
    }
   
    if(CmsPropertyHandler.getUseSynchronizationOnCaches())
    {
        synchronized(cacheAdministrator) //Back
        {
        try
        {
          if(useGroups)
          {
            if(CmsPropertyHandler.getUseHashCodeInCaches())
              cacheAdministrator.putInCache("" + key.toString().hashCode(), value, groups);
            else
              cacheAdministrator.putInCache(key.toString(), value, groups);
          }
          else
          {
            if(CmsPropertyHandler.getUseHashCodeInCaches())
              cacheAdministrator.putInCache("" + key.toString().hashCode(), value);
            else
                cacheAdministrator.putInCache(key.toString(), value);
          }
        }
        catch (Exception e)
        {
          logger.warn("Error putting in cache:" + e.getMessage());
        }
      }
    }
    else
    {
      try
      {
        if(useGroups)
        {
          if(CmsPropertyHandler.getUseHashCodeInCaches())
            cacheAdministrator.putInCache("" + key.toString().hashCode(), value, groups);
          else
            cacheAdministrator.putInCache(key.toString(), value, groups);
        }
        else
        {
          if(CmsPropertyHandler.getUseHashCodeInCaches())
            cacheAdministrator.putInCache("" + key.toString().hashCode(), value);
          else
              cacheAdministrator.putInCache(key.toString(), value);
        }
      }
      catch (Exception e)
      {
        logger.warn("Error putting in cache:" + e.getMessage(), e);
      }
    }
         
    //logger.info("Done cacheObjectInAdvancedCache");
 
 

  public static Object getCachedObjectFromAdvancedCache(String cacheName, String key)
  {
    return getCachedObjectFromAdvancedCache(cacheName, key, false, "UTF-8", false);
  }

  public static Object getCachedObjectFromAdvancedCache(String cacheName, String key, boolean useFileCacheFallback, String fileCacheCharEncoding, boolean cacheFileResultInMemory)
  {
    if(cacheName == null || key == null || key.length() == 0)
      return null;
   
    if(getDefeatCaches().getDefeatCache("" + cacheName + "_" + key))
      return null;
   
      Object value = null;
      boolean stopUseFileCacheFallback = false;
     
      //synchronized(caches)
      //{
        GeneralCacheAdministrator cacheAdministrator = (GeneralCacheAdministrator)caches.get(cacheName);
        if(cacheAdministrator != null)
        {
          //TODO
          if(CmsPropertyHandler.getUseSynchronizationOnCaches())
        {
            synchronized(cacheAdministrator) //Back
            {
                try
              {
                if(CmsPropertyHandler.getUseHashCodeInCaches())
                value = (cacheAdministrator == null) ? null : cacheAdministrator.getFromCache("" + key.hashCode(), CacheEntry.INDEFINITE_EXPIRY);
              else
                value = (cacheAdministrator == null) ? null : cacheAdministrator.getFromCache(key, CacheEntry.INDEFINITE_EXPIRY);

                //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Getting from cache on " + cacheName, t.getElapsedTime());
              }
              catch (NeedsRefreshException nre)
              {
                if(useFileCacheFallback && nre.getCacheContent() != null)
                {
                  stopUseFileCacheFallback = true;
                }
               
                try
                {
                if(CmsPropertyHandler.getUseHashCodeInCaches())
                  cacheAdministrator.cancelUpdate("" + key.hashCode());
                else
                  cacheAdministrator.cancelUpdate(key);
                }
                catch (Exception e)
                {
                  logger.error("Error:" + e.getMessage());
              }

                //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Getting object 3 part 2 from " + cacheName, t.getElapsedTime());
            }
            }
        }
          else
          {
            try
            {
            if(CmsPropertyHandler.getUseHashCodeInCaches())
              value = (cacheAdministrator == null) ? null : cacheAdministrator.getFromCache("" + key.hashCode(), CacheEntry.INDEFINITE_EXPIRY);
            else
              value = (cacheAdministrator == null) ? null : cacheAdministrator.getFromCache(key, CacheEntry.INDEFINITE_EXPIRY);
            }
            catch (NeedsRefreshException nre)
            {
              if(useFileCacheFallback && nre.getCacheContent() != null)
              {
                stopUseFileCacheFallback = true;
              }
             
              try
              {
              if(CmsPropertyHandler.getUseHashCodeInCaches())
                cacheAdministrator.cancelUpdate("" + key.hashCode());
              else
                cacheAdministrator.cancelUpdate(key);
              }
              catch (Exception e)
              {
                logger.error("Error:" + e.getMessage());
            }
          }
          }
        }

        if(value == null && useFileCacheFallback && !stopUseFileCacheFallback)
        {        
          Timer t = new Timer();
          if(logger.isInfoEnabled())
            logger.info("Getting cache content from file..");
          value = getCachedContentFromFile(cacheName, key, fileCacheCharEncoding);
          if(value != null && cacheFileResultInMemory)
          {
            if(logger.isInfoEnabled())
                logger.info("Got cached content from file as it did not exist in memory...:" + value.toString().length());
          if(CmsPropertyHandler.getUseHashCodeInCaches())
            cacheObjectInAdvancedCache(cacheName, "" + key.hashCode(), value);
          else
            cacheObjectInAdvancedCache(cacheName, key, value);
          }
          RequestAnalyser.getRequestAnalyser().registerComponentStatistics("File cache", t.getElapsedTime());
        }
    //}
     
    return value;
  }

  public static Object getCachedObjectFromAdvancedCache(String cacheName, String key, boolean useFileCacheFallback, String fileCacheCharEncoding, boolean cacheFileResultInMemory, Object o, Method m, Object[] args, PageInvoker pageInvoker) throws Exception
  {
    if(cacheName == null || key == null || key.length() == 0)
      return null;
   
      Object value = null;
     
      String pageKey = key;
      //if(CmsPropertyHandler.getUseHashCodeInCaches())
      //  pageKey = "" + key.hashCode();

      GeneralCacheAdministrator cacheAdministrator = (GeneralCacheAdministrator)caches.get(cacheName);
      if(cacheAdministrator == null)
      {
        Map cacheSettings = (Map)getCachedObject("serverNodePropertiesCacheSettings", "cacheSettings");
        if(cacheSettings == null)
        {
          cacheSettings = CmsPropertyHandler.getCacheSettings();
          cacheObject("serverNodePropertiesCacheSettings", "cacheSettings", cacheSettings);
        }
       
        String cacheCapacity = "20000";
        String cacheCapacityProperty = (String)cacheSettings.get("CACHE_CAPACITY_" + cacheName);
        if(cacheCapacityProperty != null && !cacheCapacityProperty.equals(""))
          cacheCapacity = cacheCapacityProperty;
         
      if(cacheCapacity != null && !cacheCapacity.equals(""))
        {
        Properties p = new Properties();
         
        logger.info("Creating cache " + cacheName + " with:" + cacheCapacity);
        p.setProperty(AbstractCacheAdministrator.CACHE_ALGORITHM_KEY, "com.opensymphony.oscache.base.algorithm.ImprovedLRUCache");
        p.setProperty(AbstractCacheAdministrator.CACHE_CAPACITY_KEY, cacheCapacity);
        cacheAdministrator = new GeneralCacheAdministrator(p);
      }
      else
      {
        cacheAdministrator = new GeneralCacheAdministrator();
        logger.info("Creating cache without limit" + cacheName);
      }
     
      if(cacheAdministrator.getCache().cacheMap instanceof ImprovedLRUCache)
        ((ImprovedLRUCache)cacheAdministrator.getCache().cacheMap).setIsPageCache(true);
     
      CacheEntryEventListenerImpl cacheEntryEventListener = new ExtendedCacheEntryEventListenerImpl();
      CacheMapAccessEventListenerImpl cacheMapAccessEventListener = new CacheMapAccessEventListenerImpl();
         
          cacheAdministrator.getCache().addCacheEventListener(cacheEntryEventListener, CacheEntryEventListener.class);
      cacheAdministrator.getCache().addCacheEventListener(cacheMapAccessEventListener, CacheMapAccessEventListener.class);
      caches.put(cacheName, cacheAdministrator);
      //locksCache.put(cacheName, new ReentrantReadWriteLock());
      }
     
     
      if(logger.isInfoEnabled())
        logger.info("Getting from file: " + pageKey);
      Object pageCacheFileName = getCachedObjectFromAdvancedCache(cacheName, pageKey, CacheEntry.INDEFINITE_EXPIRY);
      if(logger.isInfoEnabled())
        logger.info("pageCacheFileName:" + pageCacheFileName + " from " + cacheName + " and key: " + pageKey);
      if(pageCacheFileName != null && !pageCacheFileName.equals(""))
        value = PageCacheHelper.getInstance().getCachedPageString(pageKey, new File(pageCacheFileName.toString()));
      else
        logger.info("No page file name in memory cache:" + pageKey);
      //System.out.println("value:" + value);
      //value = getCachedObjectFromAdvancedCache(cacheName, pageKey, CacheEntry.INDEFINITE_EXPIRY);
    if(value == null)
    {
      logger.info("Invoking:" + cacheName);
        String result = (String)m.invoke(o, args);
        logger.info("result:" + (result == null ? "null" : result.length()));
      value = result;
      if(result != null)
      {
           cacheNewResult(pageInvoker, cacheAdministrator, pageKey, result);
      }
        value = result;
    }
   
      if(value != null && value instanceof byte[])
        value = compressionHelper.decompress((byte[])value);
     
     
    return value;
  }

  public static Map<String,Object> getCachedObjectsFromAdvancedCacheFilteredOnKeyEnd(String cacheName, String keyNameFilter)
  {
    if(cacheName == null)
      return null;
   
    if(getDefeatCaches().getDefeatCache())
      return null;
   
    Map<String,Object> cachedValues = new HashMap<String,Object>();
   
    GeneralCacheAdministrator cacheAdministrator = (GeneralCacheAdministrator)caches.get(cacheName);
    if(cacheAdministrator != null)
    {
        synchronized(cacheAdministrator) //Back
        {
          try
          {
            if(cacheAdministrator != null)
            {
              for(String key : (Set<String>)cacheAdministrator.getCache().cacheMap.keySet())
              {
                if(key.toString().endsWith(keyNameFilter))
                {
                  try
                    {
                    cachedValues.put(key, cacheAdministrator.getCache().getFromCache(key));
                    }
                  catch (NeedsRefreshException nre)
                  {
                    logger.info("Stale cache entry");
                      cacheAdministrator.cancelUpdate(key);
                }
                }
              }
            }
          }
          catch (Exception e)
          {
            logger.error("Problem getting all cache keys and values:" + e.getMessage(), e);
        }
        }
    }
     
    return cachedValues;
  }
 
  private static boolean cacheNewResult(PageInvoker pageInvoker, GeneralCacheAdministrator cacheAdministrator, String pageKey, String value)
  {
    /*
    int argumentCount = StringUtils.countMatches(pageKey, "&");
    if(argumentCount > 4)
    {
      logger.error("Skipping caching as we don't cache url:s with more than 3 params:" + pageKey);
      return false;
    }
    argumentCount = StringUtils.countMatches(pageKey, "/");
    if(argumentCount > 7)
    {
      logger.error("Skipping caching as we don't cache url:s with more than 7 slashes:" + pageKey);
      return false;
    }
    */

    boolean isCached = false;
   
    String pageCacheExtraName = "pageCacheExtra";
    if(!pageInvoker.getTemplateController().getIsPageCacheDisabled() && !pageInvoker.getDeliveryContext().getDisablePageCache()) //Caching page if not disabled
    {
      Integer newPageCacheTimeout = pageInvoker.getDeliveryContext().getPageCacheTimeout();
      if(newPageCacheTimeout == null)
        newPageCacheTimeout = pageInvoker.getTemplateController().getPageCacheTimeout();
     
      //String[] allUsedEntitiesCopy = pageInvoker.getDeliveryContext().getAllUsedEntities().clone();
      List<String> allUsedEntitiesSet = pageInvoker.getDeliveryContext().getAllUsedEntitiesAsSet();
      //String[] allUsedEntitiesCopy = allUsedEntitiesSet.toArray(new String[0]);
      //System.out.println("allUsedEntitiesSet:" + allUsedEntitiesSet.size());
     
      String pageCacheExclusionsRegexp = null;
      Integer pageCacheMaxGroups = 500;
      try
      {
        Map cacheSettings = CmsPropertyHandler.getCacheSettings();
        //System.out.println("cacheSettings:" + cacheSettings);
          if(cacheSettings != null)
          {
            pageCacheExclusionsRegexp = (String)cacheSettings.get("PAGE_CACHE_EXCLUSIONS");
            String pageCacheMaxGroupsString = (String)cacheSettings.get("PAGE_CACHE_MAX_GROUPS");
            if(pageCacheMaxGroupsString != null)
              pageCacheMaxGroups = new Integer(pageCacheMaxGroupsString);
           
            if(pageCacheExclusionsRegexp != null && !pageCacheExclusionsRegexp.equals(""))
            pattern = Pattern.compile(pageCacheExclusionsRegexp);
          }
      }
      catch (Exception e)
      {
        logger.warn("cacheSettings was null:" + e.getMessage(), e);
      }
      if(logger.isInfoEnabled())
      {
        logger.info("pageCacheExclusionsRegexp:" + pageCacheExclusionsRegexp);
        logger.info("pageCacheMaxGroups:" + pageCacheMaxGroups);
      }
     
      boolean detailedRelations = true;
      if(allUsedEntitiesSet.size() > pageCacheMaxGroups)
        detailedRelations = false;

      //System.out.println("detailedRelations:" + detailedRelations);
      //System.out.println("allUsedEntitiesSet:" + allUsedEntitiesSet.size());

      Object extraData = pageInvoker.getDeliveryContext().getExtraData();
      List<String> allUsedEntitiesFilteredCopy = new ArrayList<String>();
      for(String s : allUsedEntitiesSet)
      {
        if(detailedRelations)
        {
          if(s.startsWith("content_") && s.indexOf("_", 8) > -1)
          {
            //allUsedEntitiesFilteredCopy.add(getPooledString(s.hashCode()));
            allUsedEntitiesFilteredCopy.add(s); //(getPooledString(s.hashCode()));
            //System.out.println("Added: " + s);
          }
          else if(s.startsWith("siteNode_"))
            allUsedEntitiesFilteredCopy.add(s);
          else if(s.startsWith("selectiveCacheUpdateNonApplicable"))
            allUsedEntitiesFilteredCopy.add(s);
        }
        else
        {
          if(s.startsWith("content_") && s.indexOf("_", 8) == -1)
          {
            allUsedEntitiesFilteredCopy.add(s);
            //allUsedEntitiesFilteredCopy.add(s); //getPooledString(s.hashCode()));
            //System.out.println("Added: " + s);
          }
          else if(s.startsWith("siteNode_"))
            allUsedEntitiesFilteredCopy.add(s);
          else if(s.startsWith("selectiveCacheUpdateNonApplicable"))
            allUsedEntitiesFilteredCopy.add(s);
        }
      }
      //System.out.println("allUsedEntitiesFilteredCopy:" + allUsedEntitiesFilteredCopy.size());

      try
      {
          logger.info("pageCacheExclusionsRegexp:" + pageCacheExclusionsRegexp);
          logger.info("pageCacheMaxGroups:" + pageCacheMaxGroups);
     
        if(pattern != null)
        {
              Matcher matcher = pattern.matcher(pageKey);
              if(matcher.find())
            {
              logger.info("Skipping caching key 1:" + pageKey);
              return false;
            }
            if(pageCacheMaxGroups != null && !pageCacheMaxGroups.equals("") && allUsedEntitiesFilteredCopy.size() > pageCacheMaxGroups)
            {
              logger.info("Skipping caching key 2:" + pageKey);
              return false;
            }
            matcher.reset();
        }
      }
      catch (Exception e)
      {
        logger.warn("cacheSettings was null:" + e.getMessage(), e);
      }

      String[] allUsedEntitiesCopy = allUsedEntitiesFilteredCopy.toArray(new String[0]);
      //System.out.println("allUsedEntitiesCopy:" + allUsedEntitiesCopy.length);
      logger.info("allUsedEntitiesCopy:" + allUsedEntitiesCopy.length);
      logger.info("Caching:" + pageKey);

      synchronized (cacheAdministrator)
      {
        byte[] compressedData = compressionHelper.compress(value);   
          //logger.info("Compressing page for pageCache took " + (System.currentTimeMillis() - startCompression) + " with a compressionFactor of " + (this.pageString.length() / compressedData.length));
        if(pageInvoker.getTemplateController().getOperatingMode().intValue() == 3 && !CmsPropertyHandler.getLivePublicationThreadClass().equalsIgnoreCase("org.infoglue.deliver.util.SelectiveLivePublicationThread"))
        {
          PageCacheHelper.getInstance().cachePageString(pageKey, compressedData);
          //cacheAdministrator.putInCache(pageKey, compressedData, allUsedEntitiesCopy);
          isCached = true;
          //CacheController.cacheObjectInAdvancedCache(pageCacheExtraName, pageKey, extraData, allUsedEntitiesCopy, false);
          //CacheController.cacheObjectInAdvancedCache(pageCacheExtraName, pageKey + "_pageCacheTimeout", newPageCacheTimeout, allUsedEntitiesCopy, false);   
        }
        else
        {
          //FIX THE part above as well
          //System.out.println("Caching in pageCache");
          PageCacheHelper.getInstance().cachePageString(pageKey, compressedData);
          //cacheAdministrator.putInCache(pageKey, compressedData, allUsedEntitiesCopy);
          isCached = true;

          /*
          if(pageInvoker.getTemplateController().getHttpServletRequest().getParameter("listMostUsed") != null)
          {
            System.out.println("These contents were used before:" + ContentDeliveryController.mostUsedContentIds.size());
            Map<Integer,Integer> contentIds = ContentDeliveryController.mostUsedContentIds;
            for(Integer contentId : contentIds.keySet())
            {
              if(contentIds.get(contentId) > 3)
                System.out.println("" + contentId + ":" + contentIds.get(contentId));
            }
          }
          */
          if(pageInvoker.getTemplateController().getHttpServletRequest().getParameter("listEntities") != null)
          {
            List<String> debug = Arrays.asList(allUsedEntitiesCopy);
            Collections.sort(debug);
            for(String s : debug)
            {
              System.out.println("s:" + s);
            }
          }
         
          CacheController.cacheObjectInAdvancedCache(pageCacheExtraName, pageKey, extraData, null, false);
          CacheController.cacheObjectInAdvancedCache(pageCacheExtraName, pageKey + "_pageCacheTimeout", newPageCacheTimeout, null, false);   
          //CacheController.cacheObjectInAdvancedCache(pageCacheExtraName, pageKey + "_entities", allUsedEntitiesCopy, null, false);
          String allUsedEntitiesCopyAsString = StringUtils.join(allUsedEntitiesCopy, "|");
          if(logger.isInfoEnabled())
          {
            logger.info("pageKey:" + pageKey);
            logger.info("allUsedEntitiesCopyAsString:" + allUsedEntitiesCopyAsString);
          }
         
          if(CmsPropertyHandler.getOperatingMode().equals("0"))
          {
            CacheController.cacheObjectInAdvancedCache(pageCacheExtraName, pageKey + "_entitiesAsByte", allUsedEntitiesCopyAsString);
          }
          else
          {
            byte[] compressedAllUsedEntitiesCopyAsString = compressionHelper.compress(allUsedEntitiesCopyAsString);
            CacheController.cacheObjectInAdvancedCache(pageCacheExtraName, pageKey + "_entitiesAsByte", compressedAllUsedEntitiesCopyAsString);           
          }
        }
      }
    }
    else
    {
      if(logger.isInfoEnabled())
        logger.info("Page caching was disabled for the page " + pageInvoker.getDeliveryContext().getSiteNodeId() + " with pageKey " + pageInvoker.getDeliveryContext().getPageKey() + " - modifying the logic to enable page caching would boast performance.");
    }
    return isCached;
  }
 
  public static Object getCachedObjectFromAdvancedCache(String cacheName, String key, int updateInterval)
  {
    return getCachedObjectFromAdvancedCache(cacheName, key, updateInterval, false, "UTF-8", false);
  }
 
  public static Object getCachedObjectFromAdvancedCache(String cacheName, String key, int updateInterval, boolean useFileCacheFallback, String fileCacheCharEncoding, boolean cacheFileResultInMemory)
  {
    if(cacheName == null || key == null)
      return null;
   
    if(getDefeatCaches().getDefeatCache("" + cacheName + "_" + key))
      return null;

      //logger.info("getCachedObjectFromAdvancedCache start:" + cacheName + ":" + key + ":" + updateInterval);

      //return getCachedObject(cacheName, key);
      Object value = null;
      boolean stopUseFileCacheFallback = false;

      //synchronized(caches)
      //{
        GeneralCacheAdministrator cacheAdministrator = (GeneralCacheAdministrator)caches.get(cacheName);
        if(cacheAdministrator != null)
        {
          //TODO
          if(CmsPropertyHandler.getUseSynchronizationOnCaches())
          {
              try
            {
                if(CmsPropertyHandler.getUseHashCodeInCaches())
                  value = (cacheAdministrator == null) ? null : cacheAdministrator.getFromCache("" + key.hashCode(), updateInterval);
                else
                  value = (cacheAdministrator == null) ? null : cacheAdministrator.getFromCache(key, updateInterval);
            }
            catch (NeedsRefreshException nre)
            {
              if(useFileCacheFallback && nre.getCacheContent() != null)
              {
                stopUseFileCacheFallback = true;
              }
             
                if(CmsPropertyHandler.getUseHashCodeInCaches())
                  cacheAdministrator.cancelUpdate("" + key.hashCode());
                else
                  cacheAdministrator.cancelUpdate(key);
          }
          }
          else
          {
            try
            {
                if(CmsPropertyHandler.getUseHashCodeInCaches())
                  value = (cacheAdministrator == null) ? null : cacheAdministrator.getFromCache("" + key.hashCode(), updateInterval);
                else
                  value = (cacheAdministrator == null) ? null : cacheAdministrator.getFromCache(key, updateInterval);
            }
            catch (NeedsRefreshException nre)
            {
              if(useFileCacheFallback && nre.getCacheContent() != null)
              {
                stopUseFileCacheFallback = true;
              }
             
                if(CmsPropertyHandler.getUseHashCodeInCaches())
                  cacheAdministrator.cancelUpdate("" + key.hashCode());
                else
                  cacheAdministrator.cancelUpdate(key);
          }
          }
         
        if(useFileCacheFallback && !stopUseFileCacheFallback)
          {               
            if(logger.isInfoEnabled())
              logger.info("Getting cache content from file..");
            value = getCachedContentFromFile(cacheName, key, updateInterval, fileCacheCharEncoding);
            if(value != null && cacheFileResultInMemory)
            {
              if(logger.isInfoEnabled())
                  logger.info("Got cached content from file as it did not exist in memory...:" + value.toString().length());
                if(CmsPropertyHandler.getUseHashCodeInCaches())
                  cacheObjectInAdvancedCache(cacheName, "" + key.hashCode(), value);
                else
                  cacheObjectInAdvancedCache(cacheName, key, value);
            }
          }
        }
    //}
     
    return value;
  }

  /**
   * This method let's you get a list of caches and entries in which the given entity is located.
   * @param entityName
   * @param entityId
   * @throws Exception
   */
  public static String debugCache(String entityName, String entityId, String cacheNamesToDebug, String forceClear) throws Exception
  {
    StringBuffer debug = new StringBuffer();
   
    if(entityName.equalsIgnoreCase("content"))
      entityName = "content";
    if(entityName.equalsIgnoreCase("sitenode"))
      entityName = "siteNode";
    logger.error("Debugging " + entityName + "=" + entityId + " (" + cacheNamesToDebug + ")" + " - forceClear:" + forceClear);
   
    /*
    Boolean isEntityPublicationProcessed = false;
    try
    {
      isEntityPublicationProcessed = PublicationController.getController().getIsEntityPublicationProcessed(entityName, entityId);
      System.out.println("isEntityPublicationProcessed: " + isEntityPublicationProcessed);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    */
    if(cacheNamesToDebug == null || cacheNamesToDebug.equals(""))
      cacheNamesToDebug = "contentVersionCache,contentVersionIdCache,contentCache,matchingContentsCache,pageCache,pageCacheExtra";
    logger.info("cacheNamesToDebug:" + cacheNamesToDebug);
   
    Set<String> pageCacheNotifications = new HashSet<String>();
    List<String[]> entriesToClear = new ArrayList<String[]>();
   
    String[] cacheNamesToDebugArray = cacheNamesToDebug.split(",");
    List<String> cacheNamesToDebugList = Arrays.asList(cacheNamesToDebugArray);
    synchronized(caches)
    {
      for (Iterator i = caches.entrySet().iterator(); i.hasNext(); )
      {
        Map.Entry e = (Map.Entry) i.next();
        String cachName = (String)e.getKey();
        //System.out.println("Cache: " + cachName);
        if(cacheNamesToDebugList.contains(cachName))
        {
          //debug.append("Checked: " + cachName + ",");
          Object object = e.getValue();
          if(object instanceof Map)
          {
            Map cacheInstance = (Map)e.getValue();
            synchronized(cacheInstance)
            {
              Set<Map.Entry<String,Object>> entrySet = cacheInstance.entrySet();
              logger.info("entrySet:" + entrySet.size());
              Iterator<Map.Entry<String,Object>> entrySetIterator = entrySet.iterator();
              while(entrySetIterator.hasNext())
              {
                Map.Entry<String,Object> entry = entrySetIterator.next();
                if(entry.getKey().toLowerCase().contains(entityName.toLowerCase()) || entry.getKey().contains("selectiveCacheUpdateNonApplicable"))
                {
                  debug.append("" + cachName + "=" + entry.getKey() + ",");
                  entriesToClear.add(new String[]{cachName, entry.getKey()});
                }
              }
            }
          }
          else
          {
              GeneralCacheAdministrator cacheInstance = (GeneralCacheAdministrator)e.getValue();
            synchronized(cacheInstance)
            {
              pageCacheNotifications.add(entityName + "_" + entityId);

              Set<String> entries = cacheInstance.getCache().getGroup(entityName + "_" + entityId);
              logger.info("entries:" + entries.size());
              for(String entry : entries)
              {
                //debug.append("" + cachName + "=" + entry + ",");
                entriesToClear.add(new String[]{cachName, entry});
              }
             
              try
              {
                pageCacheNotifications.add("selectiveCacheUpdateNonApplicable");

                if(entityName.toLowerCase().equals("content"))
                {
                  List<ContentTypeDefinitionVO> contentTypeDefinitionVOList = ContentTypeDefinitionController.getController().getContentTypeDefinitionVOList();
                  for(ContentTypeDefinitionVO ctdVO : contentTypeDefinitionVOList)
                  {
                    //System.out.println("Group:" + "selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + ctdVO.getId());
                    Set<String> selectiveCacheUpdateNonApplicableEntries = cacheInstance.getCache().getGroup("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + ctdVO.getId());
                    for(String entry : selectiveCacheUpdateNonApplicableEntries)
                    {
                      //debug.append("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + ctdVO.getId() + "/" + cachName + "=" + entry + ",");
                      //debug.append("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + ctdVO.getId() + ",");
                      entriesToClear.add(new String[]{cachName, entry});
                      pageCacheNotifications.add("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + ctdVO.getId());
                    }
                  }
                }
                Set<String> selectiveCacheUpdateNonApplicableEntries = cacheInstance.getCache().getGroup("selectiveCacheUpdateNonApplicable");
                for(String entry : selectiveCacheUpdateNonApplicableEntries)
                {
                  //debug.append("selectiveCacheUpdateNonApplicable: " + cachName + "=" + entry + ",");
                  entriesToClear.add(new String[]{cachName, entry});
                  pageCacheNotifications.add("selectiveCacheUpdateNonApplicable");
                }
              }
              catch (Exception e2)
              {
                e2.printStackTrace();
              }
            }
          }
        }
        else
          logger.info("Skipping cache:" + cachName);
      }
    }
       
    if(forceClear != null && forceClear.equalsIgnoreCase("true"))
    {
      logger.info("********** Clearing caches *********");
      String entityNameFull = ContentImpl.class.getName();
      if(entityName.toLowerCase().contains("sitenode"))
        entityNameFull = SiteNodeImpl.class.getName();
      CacheController.clearCaches(entityNameFull, entityId, null);
    }
   
    for(String[] clearEntries : entriesToClear)
    {
      debug.append("" + clearEntries[0] + "=" + clearEntries[1] + ",");
      if(forceClear != null && forceClear.equalsIgnoreCase("true"))
      {
        clearCacheHard(clearEntries[0], clearEntries[1]);
      }
    }
    for(String pageCacheNotification : pageCacheNotifications)
    {
      logger.info("Asking page cache to clear on: " + pageCacheNotification);
      debug.append("PageCache: " + pageCacheNotification + ",");
      if(forceClear != null && forceClear.equalsIgnoreCase("true"))
        PageCacheHelper.getInstance().notify(pageCacheNotification);
    }
    if(forceClear != null && forceClear.equalsIgnoreCase("true"))
      System.out.println("************************************");
       
    if(entityName.contains("siteNode"))
    {
      SiteNodeVO siteNodeVO = SiteNodeController.getController().getSiteNodeVOWithId(new Integer(entityId));
      if(siteNodeVO != null && siteNodeVO.getMetaInfoContentId() != null)
      {
        debug.append(debugCache("Content", siteNodeVO.getMetaInfoContentId().toString(), cacheNamesToDebug, forceClear));
      }
    }
   
    return debug.toString();
  }
 
  public static void clearCachesStartingWith(String cacheNamePrefix)
  {
    Set keySet = new HashSet();
    keySet.addAll(caches.keySet());
   
    Iterator cachesIterator = keySet.iterator();
    while(cachesIterator.hasNext())
    {
      String cacheName = (String)cachesIterator.next();
      if(cacheName.startsWith(cacheNamePrefix))
        clearCache(cacheName);
    }
  }
 
  public static void clearUserAccessCache(String accessRightKey)
  {
    if(caches.containsKey("userAccessCache"))
    {
        Object object = caches.get("userAccessCache");
       
      Map cacheInstance = (Map)object;
      synchronized(cacheInstance)
      {
        for(Object personalCache : cacheInstance.values())
        {
          //System.out.println("personalCache:" + personalCache);
          if(personalCache instanceof Map)
          {
            //System.out.println("personalCache contains:" + ((Map)personalCache).containsKey(accessRightKey));
            //((Map) personalCache).remove(accessRightKey);
            ((Map) personalCache).put(accessRightKey, -1)
            //System.out.println("personalCache contains after:" + ((Map)personalCache).containsKey(accessRightKey));
          }
        }
      }

        logger.info("clearCache stop...");
    }
  }
 
  public static int getCacheSize(String cacheName)
  {
    int cacheSize = 0;
    synchronized(caches)
    {
      if(caches.containsKey(cacheName))
      {
          Object object = caches.get(cacheName);
          if(object instanceof Map)
        {
          Map cacheInstance = (Map)object;
          synchronized(cacheInstance)
          {
            cacheSize = cacheInstance.size();
          }
        }
        else
        {
            GeneralCacheAdministrator cacheInstance = (GeneralCacheAdministrator)object;
            synchronized(cacheInstance) //Back
            {
            /*
            Timer t = new Timer();
            ReentrantReadWriteLock rwl = locksCache.get(cacheName);
            boolean lockSuccess = false;
            try {
              System.out.println("YAAAAAAAAAAAAA 2");
            lockSuccess = rwl.readLock().tryLock(readLockTimeout, TimeUnit.SECONDS);
          } catch (InterruptedException e1) {
            RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Error getting lock in getCacheSize on " + cacheName, t.getElapsedTime());
            printLockDebug(rwl);
            return 0;
          }
            //rwl.readLock().lock();
                try
                {
                  if(!lockSuccess)
                  {
              RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Timeout getting lock in getCacheSize on " + cacheName, t.getElapsedTime());
                    return 0;
                  }
            */ 
            cacheSize = cacheInstance.getCache().getSize();
           
              //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Getting getCacheSize on " + cacheName, t.getElapsedTime());
          }
            /*
                finally
                {
                  if(lockSuccess)
                    rwl.readLock().unlock();
                }
                */
        }
      }
    }
    return cacheSize;
  }
 

  public static void clearCache(String cacheName)
  {
    logger.info("Clearing the cache called " + cacheName);
   
    synchronized(caches)
    {
      if(caches.containsKey(cacheName))
      {
          Object object = caches.get(cacheName);
          if(object instanceof Map)
        {
          Map cacheInstance = (Map)object;
          synchronized(cacheInstance)
          {
            cacheInstance.clear();
          }
        }
        else
        {
            GeneralCacheAdministrator cacheInstance = (GeneralCacheAdministrator)object;
            synchronized(cacheInstance) //Back
            {
            /* 
            Timer t = new Timer();
            ReentrantReadWriteLock rwl = locksCache.get(cacheName);
            boolean lockSuccess = false;
            try {
            lockSuccess = rwl.writeLock().tryLock(writeLockTimeout, TimeUnit.SECONDS);
            printLockDebug(rwl);
          } catch (InterruptedException e1) {
            return;
          }
            //rwl.writeLock().lock();
                try
                {
                  if(!lockSuccess)
                  {
              printLockDebug(rwl);
                    return;
                  }
             
              RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Getting lock for flushing " + cacheName, t.getElapsedTime());
                  */
            cacheInstance.flushAll();
              cacheInstance.destroy();

              //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Flushing " + cacheName, t.getElapsedTime());
          }
            /*
                finally
                {
                  if(lockSuccess)
                    rwl.writeLock().unlock();
                }
                */
        }
          caches.remove(cacheName);
 
          logger.info("clearCache stop...");
      }
    }
  }

  public static void flushCache(String cacheName)
  {
    logger.info("Flushing the cache called " + cacheName);
    synchronized(caches)
    {
      if(caches.containsKey(cacheName))
      {
          Object object = caches.get(cacheName);
          if(object instanceof Map)
        {
          Map cacheInstance = (Map)object;
          synchronized(cacheInstance)
          {
            cacheInstance.clear();
          }
        }
        else
        {
            GeneralCacheAdministrator cacheInstance = (GeneralCacheAdministrator)object;
            synchronized(cacheInstance) //Back
            {
            /*
            Timer t = new Timer();
            ReentrantReadWriteLock rwl = locksCache.get(cacheName);
            boolean lockSuccess = false;
            try {
              System.out.println("ddddddddddddddddddd");
              lockSuccess = rwl.writeLock().tryLock(writeLockTimeout, TimeUnit.SECONDS);
          } catch (InterruptedException e1) {
            printLockDebug(rwl);
            return;
          }
            //rwl.writeLock().lock();
                try
                {
                  if(!lockSuccess)
                  {
              printLockDebug(rwl);
                    return;
                  }

              RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Getting lock for flushing " + cacheName, t.getElapsedTime());
            */
            cacheInstance.flushAll();
           
              //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Flushing " + cacheName, t.getElapsedTime());
          }
            /*
                finally
                {
                  if(lockSuccess)
                    rwl.writeLock().unlock();
                }
                */
        }
          //caches.remove(cacheName);
          //eventListeners.remove(cacheName + "_cacheEntryEventListener");
          //eventListeners.remove(cacheName + "_cacheMapAccessEventListener");
 
          logger.info("clearCache stop...");
      }
    }
  }

  public static void clearCache(String cacheName, String key)
  {
    //synchronized(caches)
    //{
      if(caches.containsKey(cacheName))
      {
          Object object = caches.get(cacheName);
          if(object instanceof Map)
        {
          Map cacheInstance = (Map)object;
          synchronized(cacheInstance)
          {
            cacheInstance.remove(key);
          }
        }
        else
        {
            GeneralCacheAdministrator cacheInstance = (GeneralCacheAdministrator)object;
            synchronized(cacheInstance) //Back
            {
            cacheInstance.flushEntry(key);
          }
        }
      }
    //}
  }

  public static void clearCacheHard(String cacheName, String key)
  {
    if(caches.containsKey(cacheName))
    {
        Object object = caches.get(cacheName);
        if(object instanceof Map)
      {
        Map cacheInstance = (Map)object;
        synchronized(cacheInstance)
        {
          cacheInstance.remove(key);
        }
      }
      else
      {
          GeneralCacheAdministrator cacheInstance = (GeneralCacheAdministrator)object;
          synchronized(cacheInstance) //Back
          {
          //cacheInstance.flushEntry(key);
          cacheInstance.removeEntry(key);
          }
      }
    }
  }
 
  /**
   * This method clears part of a cache.
   * @param cacheName
   * @param groups
   */
  public static void clearCacheForGroup(String cacheName, String group)
  {
    /*
    if(cacheName.indexOf("pageCache") > -1)
      Thread.dumpStack();
    */
    synchronized(caches)
    {
      if(caches.containsKey(cacheName))
      {
          Object object = caches.get(cacheName);
          if(object instanceof Map)
        {
          Map cacheInstance = (Map)object;
          synchronized(cacheInstance)
          {
            cacheInstance.clear();
            logger.info("Clearing full cache:" + cacheName + " - the call wanted partly clear for [" + group + "] but the cache was a Map.");
          }
        }
        else
        {
            GeneralCacheAdministrator cacheInstance = (GeneralCacheAdministrator)object;
            synchronized(cacheInstance) //Back
            {
            /* 
            Timer t = new Timer();
            ReentrantReadWriteLock rwl = locksCache.get(cacheName);
            boolean lockSuccess = false;
            try {
              System.out.println("YEEEEEEEEEEEEEEEEEAAAAAAH");
            lockSuccess = rwl.writeLock().tryLock(writeLockTimeout, TimeUnit.SECONDS);
            printLockDebug(rwl);
          } catch (InterruptedException e1) {
            return;
          }
            //rwl.writeLock().lock();
                try
                {
                  if(!lockSuccess)
                  {
                    return;
                  }

              RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Getting lock for flushGroup in " + cacheName, t.getElapsedTime());
          */
              cacheInstance.flushGroup(group);

            //  RequestAnalyser.getRequestAnalyser().registerComponentStatistics("FlushGroup on " + cacheName, t.getElapsedTime());
          }
            /*
                finally
                {
                  if(lockSuccess)
                    rwl.writeLock().unlock();
                }
                */
        }
      }
    }
  }

  /**
   * This method clears part of a cache.
   * @param cacheName
   * @param groups
   */
  /*
  public static void clearFileCacheForGroup(GeneralCacheAdministrator cacheInstance, String groupName) throws Exception
  {
        Set groupEntries = cacheInstance.getCache().cacheMap.getGroup(groupName);
       
        if(logger.isInfoEnabled())
        {
          if(groupEntries != null)
            logger.info("groupEntries for " + groupName + ":" + groupEntries.size() + " in cacheInstance:" + cacheInstance);
          else
            logger.info("no groupEntries for " + groupName + " in cacheInstance:" + cacheInstance);
        }
       
        if (groupEntries != null)
        {
            Iterator groupEntriesIterator = groupEntries.iterator();
            while (groupEntriesIterator.hasNext())
            {
              String key = (String) groupEntriesIterator.next();
              CacheEntry entry = (CacheEntry) cacheInstance.getCache().cacheMap.get(key);
              if(logger.isInfoEnabled())
                logger.info("Removing file with key:" + key);
              removeCachedContentInFile("pageCache", key);
              numberOfPageCacheFiles.decrementAndGet();
            }
        }
  }
  */
 
  public static void clearCaches(String entity, String entityId, String[] cachesToSkip) throws Exception
 
    clearCaches(entity, entityId, null, cachesToSkip, false);
  }

  public static void clearCaches(String entity, String entityId, Map<String,String> extraInformation, String[] cachesToSkip) throws Exception
 
    clearCaches(entity, entityId, extraInformation, cachesToSkip, false);
  }
 
  public static void clearCaches(String entity, String entityId, Map<String,String> extraInformation, String[] cachesToSkip, boolean forceClear) throws Exception
 
    Timer t = new Timer();
    //t.setActive(false);
   
    if(CmsPropertyHandler.getOperatingMode().equals("3"))
    {
      long wait = 0;
      //while(true && !getForcedCacheEvictionMode())
      while(!forceClear && !getForcedCacheEvictionMode() && RequestAnalyser.getRequestAnalyser().getNumberOfActiveRequests() > 0)
      {
            logger.warn("Number of requests: " + RequestAnalyser.getRequestAnalyser().getNumberOfCurrentRequests() + " was more than 0 - lets wait a bit.");
            if(wait > 1000)
        {
          logger.warn("The clearCache method waited over " + ((wait * 10) / 1000) + " seconds but there seems to be " + RequestAnalyser.getRequestAnalyser().getNumberOfCurrentRequests() + " requests blocking all the time. Continuing anyway.");
          //printThreads();
          break;
        }
 
            if(wait > 100)
          setForcedCacheEvictionMode(true);
 
        Thread.sleep(10);
        wait++;
        }
    }
   
      logger.info("clearCaches start in " + CmsPropertyHandler.getContextRootPath());
    if(entity == null)
    { 
      logger.info("Clearing the caches");
      //synchronized(caches)
      //{
        for (Iterator i = caches.entrySet().iterator(); i.hasNext(); )
        {
          Map.Entry e = (Map.Entry) i.next();
          logger.info("e:" + e.getKey());
          boolean skip = false;
          if(cachesToSkip != null)
          {
            for(int index=0; index<cachesToSkip.length; index++)
            {
                if(e.getKey().equals(cachesToSkip[index]))
                {
                    skip = true;
                    break;
                }
            }
          }
         
          if(!skip)
          {
            Object object = e.getValue();
            if(object instanceof Map)
            {
              Map cacheInstance = (Map)e.getValue();
              synchronized(cacheInstance)
              {
                cacheInstance.clear();
              }
            }
            else
            {
                GeneralCacheAdministrator cacheInstance = (GeneralCacheAdministrator)e.getValue();
              synchronized(cacheInstance)
              {
                  cacheInstance.flushAll();
              }
            }
            logger.info("Cleared cache:" + e.getKey());
           
              i.remove();
          }
        }
      //}
    }
      else if(entity.equalsIgnoreCase("CacheNames"))
      {
        String[] cacheNames = entityId.split(",");
        for(int i=0; i<cacheNames.length; i++)
        {
          String cacheName = cacheNames[i];
          CacheController.clearCache(cacheName);
        }
      }
    else
    {
      logger.info("Clearing some caches");
      logger.info("entity:" + entity);

        String useSelectivePageCacheUpdateString = CmsPropertyHandler.getUseSelectivePageCacheUpdate();
        boolean useSelectivePageCacheUpdate = false;
        if(useSelectivePageCacheUpdateString != null && useSelectivePageCacheUpdateString.equalsIgnoreCase("true"))
            useSelectivePageCacheUpdate = true;
           
        String operatingMode = CmsPropertyHandler.getOperatingMode();

        TreeMap<String, Object> orderedCaches = new TreeMap<String,Object>(new CacheComparator());
        orderedCaches.putAll(caches);
       
        /*
        for (String key : orderedCaches.keySet())
      {
        System.out.println("key:" + key);
      }
      */
        //t.printElapsedTime("Start cache eviction");
        RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Start cache eviction", t.getElapsedTime());
        //t.printElapsedTime("START cachesLoop:" + entity + ":" + entityId);

      //synchronized(caches)
        //{
          //for (Iterator i = caches.entrySet().iterator(); i.hasNext(); )
          cachesLoop:for (Iterator i = orderedCaches.entrySet().iterator(); i.hasNext(); )
        {
          RequestAnalyser.getRequestAnalyser().registerComponentStatistics("cache iteration top", t.getElapsedTime());

          Map.Entry e = (Map.Entry) i.next();
          logger.info("e:" + e.getKey());

          boolean clear = false;
          boolean selectiveCacheUpdate = false;
          String cacheName = e.getKey().toString();

          if(cachesToSkip != null)
          {
            for(int index=0; index<cachesToSkip.length; index++)
            {
                if(cacheName.equals(cachesToSkip[index]))
                {
                    continue cachesLoop;
                }
            }
          }
         
          //t.printElapsedTime("clearCaches 3");

          if(cacheName.equalsIgnoreCase("serviceDefinitionCache") && entity.indexOf("ServiceBinding") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("qualifyerListCache") && (entity.indexOf("Qualifyer") > 0 || entity.indexOf("ServiceBinding") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("availableServiceBindingCache") && entity.indexOf("AvailableServiceBinding") > 0)
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("categoriesCache") && entity.indexOf("Category") > 0)
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("repositoryCache") && entity.indexOf("Repository") > 0)
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("languageCache") && entity.indexOf("Language") > 0)
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("localeCache") && entity.indexOf("Language") > 0)
          { 
            clear = true;
          }
          if((cacheName.equalsIgnoreCase("latestSiteNodeVersionCache") || cacheName.equalsIgnoreCase("pageCacheLatestSiteNodeVersions") || cacheName.equalsIgnoreCase("pageCacheSiteNodeTypeDefinition")) && entity.indexOf("SiteNode") > 0)
          { 
            clear = true;
            selectiveCacheUpdate = true;
          }
          if((cacheName.equalsIgnoreCase("parentSiteNodeCache") || cacheName.equalsIgnoreCase("pageCacheParentSiteNodeCache")) && entity.indexOf("SiteNode") > 0)
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("NavigationCache") && (entity.indexOf("SiteNode") > 0 || entity.indexOf("Content") > 0))
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("pagePathCache") && (entity.indexOf("SiteNode") > 0 || entity.indexOf("Content") > 0))
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("componentEditorCache") && (entity.indexOf("SiteNode") > 0 || entity.indexOf("Content") > 0))
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("componentEditorVersionIdCache") && (entity.indexOf("SiteNode") > 0 || entity.indexOf("Content") > 0))
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("masterLanguageCache") && (entity.indexOf("Repository") > 0 || entity.indexOf("Language") > 0))
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("parentRepository") && entity.indexOf("Repository") > 0)
          { 
            clear = true;
          }
          if(cacheName.startsWith("contentAttributeCache") && (entity.indexOf("Content") > -1 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          { 
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.startsWith("metaInfoContentAttributeCache") && entity.indexOf("Content") > -1)
          { 
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("contentVersionCache") && (entity.indexOf("Content") > -1 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          { 
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.startsWith("contentVersionIdCache") && (entity.indexOf("Content") > -1 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          { 
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("referencingPagesCache") && (entity.indexOf("ContentVersion") > -1 || entity.indexOf("Qualifyer") > 0))
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("boundSiteNodeCache") && (entity.indexOf("ServiceBinding") > 0 || entity.indexOf("Qualifyer") > 0 || entity.indexOf("SiteNodeVersion") > 0 || entity.indexOf("SiteNodeVersion") > 0 || entity.indexOf("SiteNode") > 0 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("boundContentCache") && (entity.indexOf("ServiceBinding") > 0 || entity.indexOf("Qualifyer") > 0 || entity.indexOf("SiteNodeVersion") > 0 || entity.indexOf("ContentVersion") > 0 || entity.indexOf("Content") > 0 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          {
            clear = true;
          }
          if(cacheName.startsWith("pageCache") && entity.indexOf("Registry") == -1)
          { 
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.startsWith("pageCacheExtra") && entity.indexOf("Registry") == -1)
          { 
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("componentCache") && entity.indexOf("Registry") == -1)
          { 
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("componentPropertyCache") && (entity.indexOf("SiteNode") > -1 || entity.indexOf("ContentVersion") > -1 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          { 
            clear = true;
            //selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("componentPropertyVersionIdCache") && (entity.indexOf("SiteNode") > -1 || entity.indexOf("ContentVersion") > -1 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          { 
            clear = true;
            //selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("componentPropertyCacheRepoGroups") && (entity.indexOf("SiteNode") > -1 || entity.indexOf("ContentVersion") > -1 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          { 
            clear = true;
            if(entity.indexOf("SiteNode") > -1 || entity.indexOf("ContentVersion") > -1)
              selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("componentPropertyVersionIdCacheRepoGroups") && (entity.indexOf("SiteNode") > -1 || entity.indexOf("ContentVersion") > -1 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          { 
            clear = true;
            if(entity.indexOf("SiteNode") > -1 || entity.indexOf("ContentVersion") > -1)
              selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("pageComponentsCache") && (entity.indexOf("ContentVersion") > -1 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          { 
            clear = true;
            //selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("includeCache"))
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("authorizationCache") && (entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0 || entity.indexOf("Intercept") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("personalAuthorizationCache") && (entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0 || entity.indexOf("Intercept") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("componentPaletteDivCache") && (entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          { 
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("userCache") && (entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("principalCache") && (entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          {
            clear = true;
          }
          if((cacheName.equalsIgnoreCase("assetUrlCache") || cacheName.equalsIgnoreCase("assetUrlCacheWithGroups") || cacheName.equalsIgnoreCase("assetThumbnailUrlCache")) && (entity.indexOf("DigitalAsset") > 0 || entity.indexOf("ContentVersion") > 0 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          {
            clear = true;
            if(cacheName.equalsIgnoreCase("assetUrlCacheWithGroups") && (entity.indexOf("ContentVersion") > -1 || entity.indexOf("DigitalAsset") > -1))
              selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("digitalAssetCache") && (entity.indexOf("DigitalAsset") > 0 || entity.indexOf("ContentVersion") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("sortedChildContentsCache") && (entity.indexOf("Content") > 0 || entity.indexOf("ContentVersion") > 0 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("childContentCache") && (entity.indexOf("Content") > 0 || entity.indexOf("ContentVersion") > 0 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          {
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("matchingContentsCache") && (entity.indexOf("Content") > 0 || entity.indexOf("ContentVersion") > 0 || entity.indexOf("AccessRight") > 0 || entity.indexOf("SystemUser") > 0 || entity.indexOf("Role") > || entity.indexOf("Group") > 0))
          {
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("workflowCache") && entity.indexOf("WorkflowDefinition") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("rootSiteNodeCache") && entity.indexOf("SiteNode") > 0)
          {
            if(CmsPropertyHandler.getOperatingMode().equals("0"))
              clear = true;
          }
          if((cacheName.equalsIgnoreCase("siteNodeCache") || cacheName.equalsIgnoreCase("siteNodeVOCache")) && entity.indexOf("SiteNode") > 0)
          {
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("contentCache") && entity.indexOf("Content") > 0)
          {
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("rootContentCache") && entity.indexOf("Content") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("componentContentsCache") && entity.indexOf("Content") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("childSiteNodesCache") && (entity.indexOf("SiteNode") > 0 || entity.indexOf("ContentVersion") > 0))
          {
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("childPagesCache") && (entity.indexOf("SiteNode") > 0 || entity.indexOf("Content") > 0))
          {
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("siteNodeCacheWithLatestVersion") && entity.indexOf("SiteNode") > 0)
          {
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("propertySetCache") && entity.indexOf("SiteNode") > 0)
          {
              clear = true;
          }
          if(cacheName.equalsIgnoreCase("groupVOListCache") && entity.indexOf("Group") > 0)
          {               
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("roleListCache") && entity.indexOf("Role") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("groupPropertiesCache") && (entity.indexOf("Group") > 0 || entity.indexOf("PropertiesCategory") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("propertiesCategoryCache") && (entity.indexOf("Group") > 0 || entity.indexOf("Role") > 0 || entity.indexOf("User") > 0 || entity.indexOf("PropertiesCategory") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("rolePropertiesCache") && entity.indexOf("Role") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("principalPropertyValueCache") && (entity.indexOf("Group") > 0 || entity.indexOf("Role") > 0 || entity.indexOf("User") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("relatedCategoriesCache") && (entity.indexOf("Group") > 0 || entity.indexOf("Role") > 0 || entity.indexOf("User") > 0 || entity.indexOf("PropertiesCategory") > 0))
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("categoryCache") && entity.indexOf("Category") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("contentCategoryCache") && entity.indexOf("ContentVersion") > 0)
          {
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("redirectCache") && entity.indexOf("Redirect") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("interceptorsCache") && entity.indexOf("Intercept") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("interceptionPointCache") && entity.indexOf("Intercept") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("siteNodeLanguageCache") && (entity.indexOf("Repository") > 0 || entity.indexOf("Language") > 0 || entity.indexOf("SiteNode") > 0))
          {
            clear = true;
            selectiveCacheUpdate = true;
          }
          if(cacheName.equalsIgnoreCase("contentTypeDefinitionCache") && entity.indexOf("ContentTypeDefinition") > 0)
          {
            clear = true;
          }
          if(cacheName.equalsIgnoreCase("ServerNodeProperties"))
          {
            clear = true;
          }
         
          if(!cacheName.equalsIgnoreCase("serverNodePropertiesCache") && entity.equalsIgnoreCase("ServerNodeProperties"))
          {
            clear = true;           
          }
          if(!cacheName.equalsIgnoreCase("encodedStringsCache") && entity.equalsIgnoreCase("ServerNodeProperties"))
          {
            clear = true;           
          }

          if(logger.isInfoEnabled())
            logger.info("clear:" + clear);

          if(clear)
          { 
            if(logger.isInfoEnabled())
                logger.info("clearing:" + e.getKey());

            Object object = e.getValue();
           
            String sentContentId = null;
            String sentParentContentId = null;
            String sentSiteNodeId = null;
            String sentParentSiteNodeId = null;
            String sentRepositoryId = null;
            String sentContentTypeDefinitionId = null;
            String sentContentIsProtected = null;
            if (extraInformation != null)
            {
              sentContentId = extraInformation.get("contentId");
              sentParentContentId = extraInformation.get("parentContentId");
              sentSiteNodeId = extraInformation.get("siteNodeId");
              sentParentSiteNodeId = extraInformation.get("parentSiteNodeId");
              sentRepositoryId = extraInformation.get("repositoryId");
              sentContentTypeDefinitionId = extraInformation.get("contentTypeDefinitionId");
              sentContentIsProtected = extraInformation.get("contentIsProtected");
            }
           
            //System.out.println("sentContentId:" + sentContentId);
            //System.out.println("sentParentContentId:" + sentParentContentId);
            //System.out.println("sentSiteNodeId:" + sentSiteNodeId);
            //System.out.println("sentParentSiteNodeId:" + sentParentSiteNodeId);
            //System.out.println("sentRepositoryId:" + sentRepositoryId);

            if(object instanceof Map)
            {
              Map cacheInstance = (Map)e.getValue();
                synchronized(cacheInstance)
              {
                  if(cacheName.equals("componentContentsCache"))
                  {
                    try
                    {
                      if(entity.indexOf("ContentVersion") > 0)
                      {
                        String contentId = sentContentId;
                        String contentTypeDefinitionId = sentContentTypeDefinitionId;
                        if(contentId == null || contentId.equals(""))
                        {
                          try
                          {
                            contentId = ""+ContentVersionController.getContentVersionController().getContentIdForContentVersion(new Integer(entityId));
                          }
                          catch (Exception e2)
                          {
                            logger.info("Error loading content with id " + entityId + ":" + e2.getMessage());
                        }
                        }
                       
                       
                        if(contentId != null)
                        {                             
                          //ContentVO contentVO = ContentController.getContentController().getContentVOWithId(contentId);
                          if(contentTypeDefinitionId != null && !contentTypeDefinitionId.equals(""))
                          {
                            ContentTypeDefinitionVO ctdVO = ContentTypeDefinitionController.getController().getContentTypeDefinitionVOWithId(new Integer(contentTypeDefinitionId));
                            if(ctdVO.getName().equals("HTMLTemplate") || ctdVO.getName().equals("PagePartTemplate"))
                            {
                            ComponentController.getController().reIndexComponentContentsDelayed(new Integer(contentId));
                            }
                          }
                          else
                            logger.info("No content type for " + contentId);
                        }
                      }
                      else
                        logger.info("skipping clearing components as it seems stupid");
                    }
                    catch (Exception e2)
                    {
                      logger.warn("Error clearing componentContentsCache:" + e2.getMessage(), e2);
                  }
                  }
                  else if(!(cacheName.equals("userAccessCache") && cacheInstance.size() < 100))
                  {
                    logger.info("clearing ordinary map:" + e.getKey() + " (" + cacheInstance.size() + ")");
                    cacheInstance.clear();
                  }
                  else
                    logger.info("skipping clearing this as it seems stupid");
                }
            }
            else
            {
                GeneralCacheAdministrator cacheInstance = (GeneralCacheAdministrator)e.getValue();
                synchronized(cacheInstance) //Back
                {
                  //t.printElapsedTime("START:" + entity + ":" + entityId);
                  //ADD logic to flush correct on sitenode and sitenodeversion
                  /*
                  if(selectiveCacheUpdate && entity.indexOf("SiteNode") > 0)
                  {
                    cacheInstance.flushAll();
                    eventListeners.remove(cacheName + "_cacheEntryEventListener");
                    eventListeners.remove(cacheName + "_cacheMapAccessEventListener");
                    logger.info("clearing:" + e.getKey());
                  }
                  */
                  //System.out.println("entity:" + entity);
                if(entity.indexOf("pageCache") == 0)
                  {
                  if(entity.indexOf("pageCache:") == 0)
                  {
                    String groupQualifyer = entity.substring("pageCache:".length());
                    logger.info("CacheController: This is a application pageCache-clear request... specific:" + groupQualifyer);
                    logger.info("clearing " + e.getKey() + " : " + groupQualifyer);

                    PageCacheHelper.getInstance().notify("" + groupQualifyer);
                      /*
                    if(cacheName.equals("pageCacheExtra"))
                      {
                        clearFileCacheForGroup(cacheInstance, "" + groupQualifyer);
                      }
                      else if(cacheName.equals("pageCache"))
                      {
                        cacheInstance.flushGroup("" + groupQualifyer);                     
                      }
                      */
                  }
                  else
                    {
                    PageCacheHelper.getInstance().notify("selectiveCacheUpdateNonApplicable");
                    /*
                      logger.error("clearing " + e.getKey() + " selectiveCacheUpdateNonApplicable");
                      if(cacheName.equals("pageCacheExtra"))
                      {
                        clearFileCacheForGroup(cacheInstance, "selectiveCacheUpdateNonApplicable");
                      }
                      else if(cacheName.equals("pageCache"))
                      {
                        cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");                     
                      }
                      */
                    }
                  }

                if(selectiveCacheUpdate && entity.indexOf("Repository") > 0 && useSelectivePageCacheUpdate)
                  {
                    if(cacheName.equals("pageCacheExtra"))
                    {
                      PageCacheHelper.getInstance().notify("repository_" + entityId);
                      PageCacheHelper.getInstance().notify("selectiveCacheUpdateNonApplicable");
                    }
                    else
                    {
                      cacheInstance.flushGroup("repository_" + entityId);
                      cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");                     
                    }
                   
                    /*
                    logger.info("clearing " + e.getKey() + " with group " + "repository_" + entityId);
                    if(cacheName.equals("pageCacheExtra"))
                    {
                      clearFileCacheForGroup(cacheInstance, "repository_" + entityId);
                      clearFileCacheForGroup(cacheInstance, "selectiveCacheUpdateNonApplicable");
                    }
                    else
                    {
                      cacheInstance.flushGroup("repository_" + entityId);
                      cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");                     
                    }
                    */
                  }
                  else if(selectiveCacheUpdate && entity.indexOf("SiteNodeVersion") > 0)
                  {
                    //Thread.dumpStack();
                    //How to solve this good
                    if(CmsPropertyHandler.getOperatingMode().equalsIgnoreCase("0"))
                    {
                      if(cacheName.equals("pageCacheExtra"))
                      {
                        PageCacheHelper.getInstance().notify("siteNodeVersion_" + entityId);
                        PageCacheHelper.getInstance().notify("selectiveCacheUpdateNonApplicable");

                        //clearFileCacheForGroup(cacheInstance, "siteNodeVersion_" + entityId);
                        //clearFileCacheForGroup(cacheInstance, "selectiveCacheUpdateNonApplicable");
                      }
                      else
                      {
                        cacheInstance.flushGroup("siteNodeVersion_" + entityId);
                        cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");
                      }
                      logger.info("clearing " + e.getKey() + " with group " + "siteNodeVersion_" + entityId);
                     
                      try
                      {
                        logger.info("BeforesiteNodeVersionVO...");
                       
                        String siteNodeId = sentSiteNodeId;
                        String repositoryId = sentRepositoryId;
                        String parentSiteNodeId = sentParentSiteNodeId;
                        //System.out.println("siteNodeId:" + siteNodeId);
                        //System.out.println("repositoryId:" + repositoryId);
                        //System.out.println("parentSiteNodeId:" + parentSiteNodeId);
                        if(siteNodeId == null || siteNodeId.equals(""))
                        {
                          try
                          {
                            SiteNodeVersionVO snvVO = SiteNodeVersionController.getController().getSiteNodeVersionVOWithId(new Integer(entityId));
                            siteNodeId = ""+snvVO.getSiteNodeId();
                            if(repositoryId == null)
                            {
                              SiteNodeVO snVO = SiteNodeController.getController().getSiteNodeVOWithId(snvVO.getSiteNodeId());
                              repositoryId = ""+snVO.getRepositoryId();
                              parentSiteNodeId = ""+snVO.getParentSiteNodeId();
                            }
                          }
                          catch (Exception e2)
                          {
                            logger.info("Error getting siteNodeVersion " + entityId);
                          }
                        }
                                               
                        if(siteNodeId != null)
                        {
                          logger.info("Before flushGroup2...");
                          if(cacheName.equals("pageCacheExtra"))
                          {
                            PageCacheHelper.getInstance().notify("siteNode_" + siteNodeId);
                            //clearFileCacheForGroup(cacheInstance, "siteNode_" + siteNodeId);
                          }
                          else
                          {
                            cacheInstance.flushGroup("siteNode_" + siteNodeId);
                            cacheInstance.flushGroup("" + siteNodeId);
                          }
                         
                          if(siteNodeId != null && (cacheName.equals("childSiteNodesCache") || cacheName.equals("childPagesCache") || cacheName.equals("siteNodeCache") || cacheName.equals("componentPropertyCacheRepoGroups") || cacheName.equals("componentPropertyVersionIdCacheRepoGroups")))
                          {
                            if(cacheName.equals("componentPropertyCacheRepoGroups") || cacheName.equals("componentPropertyVersionIdCacheRepoGroups"))
                            {
                              cacheInstance.flushGroup("" + repositoryId);
                              logger.info("Clearing componentPropertyCacheRepoGroups for repo:" + repositoryId);
                            }
                            if(parentSiteNodeId != null)
                            {
                              cacheInstance.flushGroup("siteNode_" + parentSiteNodeId);
                              cacheInstance.flushGroup("" + parentSiteNodeId);
                              cacheInstance.flushEntry("" + parentSiteNodeId);
                              logger.info("Clearing for:" + parentSiteNodeId);
                            }
                          }
                         
                          logger.info("After flushGroup2...");
                        }
                      }
                      catch(Exception se)
                      {
                        logger.warn("Missing siteNode version: " + se.getMessage(), se);
                      }
                    }
                    else
                    {
                      try
                      {
                        if((cacheName.equals("childSiteNodesCache") || cacheName.equals("childPagesCache") || cacheName.equals("siteNodeCache") || cacheName.equals("componentPropertyCacheRepoGroups") || cacheName.equals("componentPropertyVersionIdCacheRepoGroups")))
                        {
                          SiteNodeVersionVO snvVO = SiteNodeVersionController.getController().getSiteNodeVersionVOWithId(new Integer(entityId));
                          SiteNodeVO snVO = SiteNodeController.getController().getSiteNodeVOWithId(snvVO.getSiteNodeId());
                         
                          Integer repositoryId = snVO.getRepositoryId();
                          Integer parentSiteNodeId = snVO.getParentSiteNodeId();
 
                          if(cacheName.equals("componentPropertyCacheRepoGroups") || cacheName.equals("componentPropertyVersionIdCacheRepoGroups"))
                          {
                            cacheInstance.flushGroup("" + repositoryId);
                            logger.info("Clearing componentPropertyCacheRepoGroups for repo:" + repositoryId);
                          }
                          if(parentSiteNodeId != null)
                          {
                            cacheInstance.flushGroup("siteNode_" + parentSiteNodeId);
                            cacheInstance.flushGroup("" + parentSiteNodeId);
                            cacheInstance.flushEntry("" + parentSiteNodeId);
                            logger.info("Clearing for:" + parentSiteNodeId);
                          }
                        }
                      }
                      catch (Exception e2)
                      {
                        logger.error("Problem clearing cache for site node version:" + e2.getMessage(), e2);
                    }
                    }
                  }
                  else if(selectiveCacheUpdate && (entity.indexOf("SiteNode") > 0 && entity.indexOf("SiteNodeTypeDefinition") == -1) && useSelectivePageCacheUpdate)
                  {
                    //System.out.println("Entity: " + entity);
                    logger.info("Flushing " + "" + entityId);
                    logger.info("Flushing " + "siteNode_" + entityId);
                    logger.info("Flushing " + "selectiveCacheUpdateNonApplicable");

                    if(cacheName.equals("pageCacheExtra"))
                    {
                      PageCacheHelper.getInstance().notify("siteNode_" + entityId);
                      PageCacheHelper.getInstance().notify("selectiveCacheUpdateNonApplicable");

                      //clearFileCacheForGroup(cacheInstance, "siteNode_" + entityId);
                      //clearFileCacheForGroup(cacheInstance, "selectiveCacheUpdateNonApplicable");
                    }
                    else
                    {
                      cacheInstance.flushEntry("" + entityId);
                      cacheInstance.flushGroup("" + entityId);
                      cacheInstance.flushGroup("siteNode_" + entityId);
                      cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");
                   
                      if(cacheName.equals("childSiteNodesCache") || cacheName.equals("childPagesCache") || cacheName.equals("siteNodeCache") || cacheName.equals("componentPropertyCacheRepoGroups") || cacheName.equals("componentPropertyVersionIdCacheRepoGroups"))
                      {
                        logger.info("Flushing parent also");
                       
                        String repositoryId = sentRepositoryId;
                        String parentSiteNodeId = sentParentSiteNodeId;
                        try
                        {
                          if(repositoryId == null)
                          {
                            SiteNodeVO snVO = SiteNodeController.getController().getSiteNodeVOWithId(new Integer(entityId));
                            if(snVO != null)
                            {
                              repositoryId = "" + snVO.getRepositoryId();
                              parentSiteNodeId = "" + snVO.getParentSiteNodeId();
                            }
                          }
                          if(cacheName.equals("componentPropertyCacheRepoGroups") || cacheName.equals("componentPropertyVersionIdCacheRepoGroups"))
                          {
                            cacheInstance.flushGroup("" + repositoryId);
                            logger.info("Clearing componentPropertyCacheRepoGroups for repo:" + repositoryId);
                          }

                          if(parentSiteNodeId != null && !parentSiteNodeId.equals(""))
                          {
                            logger.info("Flushing " + "" + entityId);
                            logger.info("Flushing " + "siteNode_" + entityId);

                            cacheInstance.flushGroup("siteNode_" + parentSiteNodeId);
                            cacheInstance.flushGroup("" + parentSiteNodeId);
                            cacheInstance.flushEntry("" + parentSiteNodeId);
                            logger.info("Clearing for:" + parentSiteNodeId);
                          }
                        }
                        catch(SystemException se)
                        {
                          logger.warn("Missing siteNode: " + se.getMessage(), se);
                        }
                      }
                    }

                    logger.info("clearing " + e.getKey() + " with group " + "siteNode_" + entityId);
                }
                  else if(selectiveCacheUpdate && entity.indexOf("ContentVersion") > 0 && useSelectivePageCacheUpdate)
                  {
                    //t.printElapsedTime("CV start....");
                  logger.info("ContentVersion entity was sent: " + entity + ":" + entityId + " and cacheName:" + cacheName);

                    logger.info("Getting eventListeners...");
                      //Object cacheEntryEventListener = eventListeners.get(e.getKey() + "_cacheEntryEventListener");
                    //Object cacheMapAccessEventListener = eventListeners.get(e.getKey() + "_cacheMapAccessEventListener");

                    //System.out.println("entity:" + entity);
                   
                    //System.out.println("Before flushGroup:" +cacheName);
                    logger.info("Before flushGroup...");
                    if(cacheName.equals("pageCacheExtra"))
                    {
                      //clearFileCacheForGroup(cacheInstance, "contentVersion_" + entityId);
                      //clearFileCacheForGroup(cacheInstance, "selectiveCacheUpdateNonApplicable");
                    }
                    else if(cacheName.equals("pageCache"))
                    {
                      logger.info("Skipping clearing pageCache for version");
                      //cacheInstance.flushGroup("contentVersion_" + entityId);
                      //cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");
                    }
                    else if(cacheName.equals("componentPropertyCacheRepoGroups") || cacheName.equals("componentPropertyVersionIdCacheRepoGroups"))
                    {
                      Timer t2 = new Timer();
                      try
                      {
                        String repositoryId = sentRepositoryId;
                        if(repositoryId == null)
                        {
                          String contentId = sentContentId;
                          if(contentId == null)
                            contentId = "" + ContentVersionController.getContentVersionController().getContentIdForContentVersion(new Integer(entityId));
                          ContentVO contentVO = ContentController.getContentController().getContentVOWithId(new Integer(contentId));
                          repositoryId = "" + contentVO.getRepositoryId();
                        }
                       
                        cacheInstance.flushGroup("" + repositoryId);
                        //t2.printElapsedTime("3");
                        if(cacheName.equals("componentPropertyVersionIdCacheRepoGroups"))
                          cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");
                        //t2.printElapsedTime("4");
                        logger.info("Clearing componentPropertyCacheRepoGroups for repo:" +repositoryId);
                      }
                      catch (Exception e2)
                      {
                        logger.info("Error loading content with id " + entityId + ":" + e2.getMessage());
                    }
                      //t.printElapsedTime("componentPropertyCacheRepoGroups");
                    }
                    else if(cacheName.equals("assetUrlCacheWithGroups"))
                    {
                      try
                      {
                        String contentId = sentContentId;
                        if(contentId == null || contentId.equals(""))
                          contentId = ""+ContentVersionController.getContentVersionController().getContentIdForContentVersion(new Integer(entityId));
                      cacheInstance.flushGroup("content_" + contentId);
                        logger.info("Clearing assetUrlCacheWithGroups for content:" + "content_" + contentId);
                      }
                      catch (Exception e2)
                      {
                        logger.warn("Flushing assetUrlCacheWithGroups as it was a missing entity - was probably a delete");
                        cacheInstance.flushAll();
                    }
                      //t.printElapsedTime("assetUrlCacheWithGroups");
                    }
                    else if(cacheName.equals("childPagesCache") || cacheName.equals("childSiteNodesCache"))
                    {
                      //System.out.println("childPagesCache:" + entity + "=" + entityId);
                      //t.printElapsedTime("childPagesCache start");
                      try
                      {
                        String contentId = sentContentId;
                        //System.out.println("sentContentId:" + sentContentId);
                        if(contentId == null || contentId.equals(""))
                          contentId = ""+ContentVersionController.getContentVersionController().getContentIdForContentVersion(new Integer(entityId));
                        //System.out.println("contentId:" + contentId);
                        //t.printElapsedTime("childPagesCache A");
                       
                        ContentTypeDefinitionVO metaInfoContentTypeDefinitionVO = ContentTypeDefinitionController.getController().getContentTypeDefinitionVOWithName("Meta info");
                        //t.printElapsedTime("childPagesCache B");
                        ContentVO contentVO = ContentController.getContentController().getContentVOWithId(new Integer(contentId));
                        //t.printElapsedTime("childPagesCache C");
                       
                        if(metaInfoContentTypeDefinitionVO.getId().equals(contentVO.getContentTypeDefinitionId()))
                        {
                          try
                          {
                            SiteNodeVO siteNodeVO = SiteNodeController.getController().getSiteNodeVOWithMetaInfoContentId(new Integer(contentId));
                            //t.printElapsedTime("childPagesCache getSiteNodeVOWithMetaInfoContentId");
                            if(siteNodeVO != null)
                            {
                              cacheInstance.flushGroup("siteNode_" + siteNodeVO.getId());
                              cacheInstance.flushGroup("siteNode_" + siteNodeVO.getParentSiteNodeId());
                            }
                          }
                          catch (Exception e2)
                          {
                            logger.error("Did not find a sitenode with this meta info:" + contentId);
                        }
                          cacheInstance.flushGroup("content_" + contentId);
                          cacheInstance.flushGroup("contentVersion_" + entityId);
                          cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");
                          //t.printElapsedTime("childPagesCache flush done...");
                          logger.info("Clearing childPagesCache for content:" + "content_" + contentId);
                        }
                      }
                      catch (Exception e2)
                      {
                        logger.warn("Flushing childPagesCache as it was a missing entity - was probably a delete");
                        cacheInstance.flushAll();
                    }
                      //t.printElapsedTime("childPagesCache");
                    }
                    else if(cacheName.equals("matchingContentsCache"))
                    {
                      try
                      {
                        String contentId = sentContentId;
                        if(contentId == null || contentId.equals(""))
                          contentId = ""+ContentVersionController.getContentVersionController().getContentIdForContentVersion(new Integer(entityId));

                        try
                        {
                          ContentVO contentVO = ContentController.getContentController().getContentVOWithId(new Integer(contentId));
                          String contentTypeDefinitionId = "" + contentVO.getContentTypeDefinitionId();
                          cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentTypeDefinitionId);
                          cacheInstance.putInCache("recacheMark_" + contentTypeDefinitionId, "" + System.currentTimeMillis());
                          cacheInstance.putInCache("recacheMark", "" + System.currentTimeMillis());
                        }
                        catch (Exception e2)
                        {
                          logger.warn("Flushing all as it was a missing entity - was probably a delete:" + e2.getMessage());
                          cacheInstance.flushAll();
                      }
                       
                        cacheInstance.flushGroup("content_" + contentId);
                        logger.info("Clearing assetUrlCacheWithGroups for content:" + "content_" + contentId);
                      }
                      catch (Exception e2)
                      {
                        logger.warn("Flushing all as it was a missing entity - was probably a delete:" + e2.getMessage());
                        cacheInstance.flushAll();
                    }
                      //t.printElapsedTime("matchingContentsCache");
                    }
                    else
                    {
                      //t.printElapsedTime("Before");
                      cacheInstance.flushGroup("contentVersion_" + entityId);
                      //if(!cacheName.equals("contentCache") && !cacheName.equals("contentVersionCache") && !cacheName.equals("contentAttributeCache") && !cacheName.equals("contentVersionIdCache") && !cacheName.equals("contentCategoryCache") && !cacheName.equals("metaInfoContentAttributeCache"))
                        cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");
                      logger.info("clearing " + e.getKey() + " with selectiveCacheUpdateNonApplicable");
                      //t.printElapsedTime("clearing " + e.getKey() + " with selectiveCacheUpdateNonApplicable");
                    }
                    logger.info("clearing " + e.getKey() + " with group " + "contentVersion_" + entityId);
                 
                    //String[] changedAttributes = new String[]{"Title","NavigationTitle"};
                   
                    try
                    {
                      //t.printElapsedTime("Cache 3.4");
                      logger.info("Before contentVersionVO...");
                      //System.out.println("cacheName:" + cacheName);
                      //System.out.println("entity:" + entity);
                      //System.out.println("entityId:" + entityId);
                     
                      String contentIdString = sentContentId;
                      String contentTypeDefinitionId = sentContentTypeDefinitionId;
                      String contentIsProtected = sentContentIsProtected;
                      if(contentIdString == null || contentIdString.equals(""))
                      {
                        try
                        {
                          contentIdString = "" + ContentVersionController.getContentVersionController().getContentIdForContentVersion(new Integer(entityId));
                        }
                        catch (Exception e2)
                        {
                          logger.info("Error loading content with id " + entityId + ":" + e2.getMessage());
                      }
                      }

                      Integer contentId = null;
                      if(contentIdString != null)
                        contentId = new Integer(contentIdString);
                     
                      if(contentTypeDefinitionId == null && contentIsProtected == null && contentId != null)
                      {
                        ContentVO contentVO = ContentController.getContentController().getContentVOWithId(new Integer(contentId));
                        contentTypeDefinitionId = ""+contentVO.getContentTypeDefinitionId();
                        contentIsProtected = ""+contentVO.getIsProtected().intValue();
                      }
                     
                      //t.printElapsedTime("Cache 3.5");
                      //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Cache 3.5", t.getElapsedTime());

                    if(contentId != null)
                      {
                        List<String> changes = Collections.EMPTY_LIST;
                        //System.out.println("extraInformation:" + extraInformation);
                        String changedAttributes = extraInformation == null ? null : extraInformation.get("changedAttributeNames");
                        if(changedAttributes != null && changedAttributes.length() > 0)
                          changes = new ArrayList<String>(Arrays.asList(StringUtils.split(changedAttributes, ",")));


                        //ContentVO contentVO = ContentController.getContentController().getContentVOWithId(new Integer(contentId));

                        logger.info("Before flushGroup2...");
                        if(cacheName.equals("pageCacheExtra"))
                        {
                          if(contentIsProtected.equals(""+ContentVO.YES.intValue()))
                          {
                            List<InterceptionPointVO> interceptionPointVOList = InterceptionPointController.getController().getInterceptionPointVOList("Content");
                            for(InterceptionPointVO interceptionPointVO : interceptionPointVOList)
                            {
                              if(interceptionPointVO.getName().endsWith(".Read"))
                              {
                                String acKey = "" + interceptionPointVO.getId() + "_" + entityId;
                                CacheController.clearUserAccessCache(acKey);                     
                              }
                            }
                          }
                         
                          PageCacheHelper.getInstance().notify("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentTypeDefinitionId);
                          PageCacheHelper.getInstance().notify("content_" + contentId);
                          //clearFileCacheForGroup(cacheInstance, "selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentVO.getContentTypeDefinitionId());
                         
                          if((changes == null || changes.size() == 0) && CmsPropertyHandler.getOperatingMode().equals("3"))
                          {
                            ContentVersionVO oldContentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(new Integer(entityId));
                            ContentVersionVO newContentVersionVO = ContentVersionController.getContentVersionController().getLatestActiveContentVersionVO(contentId, oldContentVersionVO.getLanguageId(), new Integer(CmsPropertyHandler.getOperatingMode()));
                            if(newContentVersionVO != null && oldContentVersionVO != null && newContentVersionVO.getId().equals(oldContentVersionVO.getId()))
                            {
                              oldContentVersionVO = null;
                              //System.out.println("SHIT - same version allready - must find other");
                              List<SmallestContentVersionVO> contentVersionVOList = ContentVersionController.getContentVersionController().getSmallestContentVersionVOList(new Integer(contentId));
                              for(SmallestContentVersionVO cvVO : contentVersionVOList)
                              {
                                if(!cvVO.getId().equals(newContentVersionVO.getId()) && cvVO.getStateId().equals(new Integer(CmsPropertyHandler.getOperatingMode())) && cvVO.getLanguageId().equals(newContentVersionVO.getLanguageId()) && cvVO.getIsActive() && (oldContentVersionVO == null || oldContentVersionVO.getId() < cvVO.getId()))
                                {
                                  oldContentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(cvVO.getId());
                                }
                              }
                            }
                           
                            //System.out.println("Now we should have current and previous version:" + newContentVersionVO + " / " + oldContentVersionVO);
                            if(newContentVersionVO != null && oldContentVersionVO != null)
                              changes = ContentVersionController.getContentVersionController().getChangedAttributeNames(newContentVersionVO, oldContentVersionVO);
                          }

                          //System.out.println("changes:" + changes);
                          for(String changedAttributeName : changes)
                          {
                            if(changedAttributeName.indexOf("ComponentStructure") > -1)
                            {
                              //Map allreadyFlushedEntries....
                              Set<String> groupEntries = (Set<String>)cacheInstance.getCache().cacheMap.getGroup("content_" + contentId + "_ComponentStructureDependency");
                              //System.out.println("groupEntries:" + groupEntries);
                              if(groupEntries != null)
                              {
                                System.out.println("groupEntries:" + groupEntries.size());
                                outer:for(String key : groupEntries)
                                {
                                  //System.out.println("key 1:" + key);
                                  try
                                  {
                                    //String[] usedEntities = (String[])cacheInstance.getFromCache(key + "_entities");
                                    byte[] usedEntitiesByteArray = (byte[])cacheInstance.getFromCache(key + "_entitiesAsByte");
                                    String usedEntitiesString = compressionHelper.decompress(usedEntitiesByteArray);
                                    //t.printElapsedTime("Decompress to " + usedEntitiesString.length() + " took");
                                    String[] usedEntities = StringUtils.split(usedEntitiesString, "|");
                                    //t.printElapsedTime("Split to usedEntities " + usedEntities.length + " took");
                                   
                                    ContentVersionVO newContentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(new Integer(entityId));
                                    String newComponentStructure = ContentVersionController.getContentVersionController().getAttributeValue(newContentVersionVO, "ComponentStructure", false);
   
                                    for(String usedEntity : usedEntities)
                                    {
                                      //System.out.println("usedEntity:" + usedEntity);
                                      if(usedEntity.startsWith("content_" + contentId + "_ComponentStructure("))
                                      {
                                        //System.out.println("Match - now lets parse: " + usedEntity);
                                        String arguments = usedEntity.substring(usedEntity.indexOf("(") + 1, usedEntity.indexOf(")"));
                                        Integer oldComponentPropertyHash = new Integer(usedEntity.substring(usedEntity.indexOf("=") + 1));
                                        String[] args = arguments.split(",");
                                        Integer componentId = new Integer(args[0]);
                                        String propertyName = args[1];
                                        Integer siteNodeId = new Integer(args[2]);
                                        Integer languageId = new Integer(args[3]);
                                        //System.out.println("componentId:" + componentId);
                                        //System.out.println("propertyName:" + propertyName);
                                        //System.out.println("siteNodeId:" + siteNodeId);
                                        //System.out.println("languageId:" + languageId);
                                     
                                        int newComponentPropertyHash = getPropertyAsStringHashCode(newComponentStructure, componentId, propertyName, siteNodeId, languageId);
                                        //System.out.println("oldComponentPropertyHash:" + oldComponentPropertyHash);
                                        //System.out.println("newComponentPropertyHash:" + newComponentPropertyHash);
                                        if(oldComponentPropertyHash.intValue() != newComponentPropertyHash)
                                        {
                                          //System.out.println("Yes - clearing - must have changed something important:" + usedEntity);
                                          PageCacheHelper.getInstance().notify(usedEntity);
                                          //clearFileCacheForGroup(cacheInstance, usedEntity);
                                        }
                                        else
                                        {
                                          //System.out.println("Flushing content_" + currentPageMetaInfoContentId + "_ComponentStructure just to catch page itself");
                                          //cacheInstance.flushGroup("content_" + currentPageMetaInfoContentId + "_ComponentStructure");
                                          //System.out.println("Flushing content_" + contentId + "_ComponentStructure just to catch page itself");
                                          //cacheInstance.flushGroup("content_" + contentId + "_ComponentStructure");
                                        }
                                       
                                      }
                                      else if(usedEntity.startsWith("content_" + contentId + "_ComponentStructure:"))
                                      {
                                        //System.out.println("Match - now lets parse component order etc: " + usedEntity);
                                        String xPath = usedEntity.substring(usedEntity.indexOf(":") + 1, usedEntity.lastIndexOf("="));
                                        Integer oldComponentPropertyHash = new Integer(usedEntity.substring(usedEntity.lastIndexOf("=") + 1));
                                        //System.out.println("xPath:" + xPath);
                                       
                                        int newComponentPropertyHash = getComponentsAsStringHashCode(newComponentStructure, xPath);
                                        //System.out.println("oldComponentPropertyHash:" + oldComponentPropertyHash);
                                        //System.out.println("newComponentPropertyHash:" + newComponentPropertyHash);
                                        if(oldComponentPropertyHash.intValue() != newComponentPropertyHash)
                                        {
                                          //System.out.println("Yes - clearing - must have changed order or added/subtracted components:" + usedEntity);
                                          PageCacheHelper.getInstance().notify(usedEntity);
                                          //clearFileCacheForGroup(cacheInstance, usedEntity);
                                        }
                                      }
                                    }
                                  }
                                  catch (Exception ex)
                                  {
                                  //logger.error("Got error trying to update cache:" + ex.getMessage());
                                    logger.warn("Got error trying to update cache:" + ex.getMessage(), ex);

                                    //clearFileCacheForGroup(cacheInstance, "content_" + contentId + "_" + changedAttributeName);
                                    //cacheInstance.flushGroup("content_" + contentId + "_" + changedAttributeName);
                                    //logger.warn("Cleared pageCache for " + "content_" + contentId + "_" + changedAttributeName);

                                    break outer;
                                  }
                                }
                              }
                            }
                            else
                            {
                              PageCacheHelper.getInstance().notify("content_" + contentId + "_" + changedAttributeName);
                              //clearFileCacheForGroup(cacheInstance, "content_" + contentId + "_" + changedAttributeName);
                              //System.out.println("Cleared for " + "content_" + contentId + "_" + changedAttributeName);
                            }
                          } 

                          //t.printElapsedTime("Handled page cache extra");
                          RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Handled page cache extra", t.getElapsedTime())
                          //clearFileCacheForGroup(cacheInstance, "content_" + contentId);
                        }
                        else if(cacheName.equals("pageCache"))
                        {
                          //t.printElapsedTime("Page cache start");
                          RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Page cache start", t.getElapsedTime());
                          logger.info("Flushing pageCache for content type def");

                          String contentTypeDefKey = "selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentTypeDefinitionId;
                          cacheInstance.flushGroup(contentTypeDefKey);
                          //cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentVO.getContentTypeDefinitionId());
                          //cacheInstance.flushGroup("content_" + contentVO.getId());
                          //System.out.println("Flushing:" + getPooledString(1, contentVO.getId()));
                          cacheInstance.flushGroup(getPooledString(1, new Integer(contentId)));
                          PageCacheHelper.getInstance().notify("content_" + contentId);

                          ContentVersionVO oldContentVersionVO = null;
                          ContentVersionVO newContentVersionVO = null;
                         
                          String debug = "";
                          if((changes == null || changes.size() == 0) && CmsPropertyHandler.getOperatingMode().equals("3"))
                          {
                            debug += "entityId:" + entityId + "\n";
                            debug += "contentId:" + contentId + "\n";
                            oldContentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(new Integer(entityId));
                            debug += "oldContentVersionVO:" + oldContentVersionVO.getId() + ":" + oldContentVersionVO.getLanguageId() + "\n";
                            debug += "oldContentVersionVO:" + CmsPropertyHandler.getOperatingMode() + "\n";
                            newContentVersionVO = ContentVersionController.getContentVersionController().getLatestActiveContentVersionVO(contentId, oldContentVersionVO.getLanguageId(), new Integer(CmsPropertyHandler.getOperatingMode()));
                            debug += "newContentVersionVO:" + newContentVersionVO + "\n";
                            if(newContentVersionVO != null && oldContentVersionVO != null && newContentVersionVO.getId().equals(oldContentVersionVO.getId()))
                            {
                              debug += "newContentVersionVO:" + newContentVersionVO.getId() + "\n";
                              oldContentVersionVO = null;
                              debug += "SHIT - same version allready - must find other";
                              List<SmallestContentVersionVO> contentVersionVOList = ContentVersionController.getContentVersionController().getSmallestContentVersionVOList(new Integer(contentId));
                              for(SmallestContentVersionVO cvVO : contentVersionVOList)
                              {
                                if(!cvVO.getId().equals(newContentVersionVO.getId()) && cvVO.getStateId().equals(new Integer(CmsPropertyHandler.getOperatingMode())) && cvVO.getLanguageId().equals(newContentVersionVO.getLanguageId()) && cvVO.getIsActive() && (oldContentVersionVO == null || oldContentVersionVO.getId() < cvVO.getId()))
                                {
                                  oldContentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(cvVO.getId());
                                }
                              }
                              debug += "oldContentVersionVO:" + (oldContentVersionVO == null ? "null" : oldContentVersionVO.getId()) + "\n";
                            }
                           
                            //System.out.println("Now we should have current and previous version:" + newContentVersionVO + " / " + oldContentVersionVO);
                            if(newContentVersionVO != null && oldContentVersionVO != null)
                              changes = ContentVersionController.getContentVersionController().getChangedAttributeNames(newContentVersionVO, oldContentVersionVO);
                          }

                          //t.printElapsedTime("Changes analyzed");
                        //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Changes analyzed", t.getElapsedTime());

                          if((changes == null || changes.size() == 0&& CmsPropertyHandler.getOperatingMode().equals("3"))
                          {
                            if(oldContentVersionVO == null || newContentVersionVO == null)
                            {
                              //Hur kan det bli detta????
                              logger.warn("Fishy 1: " + oldContentVersionVO + ":" + newContentVersionVO + " in " + CmsPropertyHandler.getContextRootPath());
                              logger.warn("DEBUG: " + debug);
                            }
                            else
                            {
                              logger.warn("Fishy 2: No changes found between content versions " + newContentVersionVO.getId() + " and " + oldContentVersionVO.getId() + " in " + CmsPropertyHandler.getContextRootPath());
                              logger.warn("DEBUG: " + debug);
                              logger.warn("Fishy: newContentVersionVO: " + newContentVersionVO.getVersionValue());
                              logger.warn("Fishy: newContentVersionVO: " + oldContentVersionVO.getVersionValue());
                            }
                            logger.warn("Just to make sure pages are updated we pretend all attributes changed until we find the bug");
                            changes = ContentVersionController.getContentVersionController().getAttributeNames(newContentVersionVO);
                          }
                         
                          //System.out.println("changes:" + changes);
                          for(String changedAttributeName : changes)
                          {
                            logger.warn("changedAttributeName: " + changedAttributeName);
                            if(changedAttributeName.indexOf("ComponentStructure") > -1 && cacheName.equals("pageCache"))
                            {
                              //Map allreadyFlushedEntries....
                              //It's something wrong here..
                              GeneralCacheAdministrator pageCacheExtraInstance = (GeneralCacheAdministrator)caches.get("pageCacheExtra");
                              String cacheGroupKey = "content_" + contentId + "_ComponentStructureDependency";
                              //Set<String> groupEntries = (Set<String>)cacheInstance.getCache().cacheMap.getGroup("content_" + contentId + "_ComponentStructureDependency");
                              Set<String> groupEntries = (Set<String>)cacheInstance.getCache().cacheMap.getGroup(getPooledString(cacheGroupKey.hashCode()));
                              //System.out.println("groupEntries:" + groupEntries);
                              if(groupEntries != null)
                              {
                                outer:for(String key : groupEntries)
                                {
                                logger.info("key 2:" + key);
                                try
                                {
                                  //String[] usedEntities = (String[])pageCacheExtraInstance.getFromCache(key + "_entities");
                                    byte[] usedEntitiesByteArray = (byte[])pageCacheExtraInstance.getFromCache(key + "_entitiesAsByte");
                                    String usedEntitiesString = compressionHelper.decompress(usedEntitiesByteArray);
                                    //t.printElapsedTime("Decompress to " + usedEntitiesString.length() + " took");
                                    String[] usedEntities = StringUtils.split(usedEntitiesString, ",");
                                    //t.printElapsedTime("Split to usedEntities " + usedEntities.length + " took");
                                 
                                    ContentVersionVO newestContentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(new Integer(entityId));
                                    String newComponentStructure = ContentVersionController.getContentVersionController().getAttributeValue(newestContentVersionVO, "ComponentStructure", false);
   
                                    for(String usedEntity : usedEntities)
                                    {
                                      //System.out.println("usedEntity:" + usedEntity);
                                      if(usedEntity.startsWith("content_" + contentId + "_ComponentStructure("))
                                      {
                                        //System.out.println("Match - now lets parse: " + usedEntity);
                                        String arguments = usedEntity.substring(usedEntity.indexOf("(") + 1, usedEntity.indexOf(")"));
                                        Integer oldComponentPropertyHash = new Integer(usedEntity.substring(usedEntity.indexOf("=") + 1));
                                        String[] args = arguments.split(",");
                                        Integer componentId = new Integer(args[0]);
                                        String propertyName = args[1];
                                        Integer siteNodeId = new Integer(args[2]);
                                        Integer languageId = new Integer(args[3]);
                                        //System.out.println("componentId:" + componentId);
                                        //System.out.println("propertyName:" + propertyName);
                                        //System.out.println("siteNodeId:" + siteNodeId);
                                        //System.out.println("languageId:" + languageId);
                                     
                                        int newComponentPropertyHash = getPropertyAsStringHashCode(newComponentStructure, componentId, propertyName, siteNodeId, languageId);
                                        //System.out.println("oldComponentPropertyHash:" + oldComponentPropertyHash);
                                        //System.out.println("newComponentPropertyHash:" + newComponentPropertyHash);
                                        if(oldComponentPropertyHash.intValue() != newComponentPropertyHash)
                                        {
                                          //System.out.println("Yes - clearing - must have changed something important:" + usedEntity);
                                          //cacheInstance.flushGroup(usedEntity);
                                          cacheInstance.flushGroup(getPooledString(usedEntity.hashCode()));
                                          //clearFileCacheForGroup(cacheInstance, usedEntity);
                                        }
                                        else
                                        {
                                          //System.out.println("Flushing content_" + currentPageMetaInfoContentId + "_ComponentStructure just to catch page itself");
                                          //cacheInstance.flushGroup("content_" + currentPageMetaInfoContentId + "_ComponentStructure");
                                          //System.out.println("Flushing content_" + contentId + "_ComponentStructure just to catch page itself");
                                          String componentStructureKey = "content_" + contentId + "_ComponentStructure";
                                          //cacheInstance.flushGroup(componentStructureKey);
                                          cacheInstance.flushGroup(getPooledString(componentStructureKey.hashCode()));
                                          cacheInstance.flushGroup(getPooledString(usedEntity.hashCode()));
                                        }
                                       
                                      }
                                      else if(usedEntity.startsWith("content_" + contentId + "_ComponentStructure:"))
                                      {
                                        //System.out.println("Match - now lets parse component order etc: " + usedEntity);
                                        String xPath = usedEntity.substring(usedEntity.indexOf(":") + 1, usedEntity.lastIndexOf("="));
                                        Integer oldComponentPropertyHash = new Integer(usedEntity.substring(usedEntity.lastIndexOf("=") + 1));
                                        //System.out.println("xPath:" + xPath);
                                       
                                        int newComponentPropertyHash = getComponentsAsStringHashCode(newComponentStructure, xPath);
                                        //System.out.println("oldComponentPropertyHash:" + oldComponentPropertyHash);
                                        //System.out.println("newComponentPropertyHash:" + newComponentPropertyHash);
                                        if(oldComponentPropertyHash.intValue() != newComponentPropertyHash)
                                        {
                                          //System.out.println("Yes - clearing - must have changed order or added/subtracted components:" + usedEntity);
                                          cacheInstance.flushGroup(getPooledString(usedEntity.hashCode()));
                                          //cacheInstance.flushGroup(usedEntity);
                                        }
                                      }
   
                                    }
                                }
                                catch(Exception ex)
                                {
                                  //logger.error("Got error trying to update cache:" + ex.getMessage());
                                    logger.warn("Got error trying to update cache:" + ex.getMessage(), ex);
                                   
                                    try
                                    {
                                      String attributeKey = "content_" + contentId + "_" + changedAttributeName;
                                      //cacheInstance.flushGroup(attributeKey);
                                      cacheInstance.flushGroup(getPooledString(attributeKey.hashCode()));
                                      logger.warn("Cleared pageCache for " + getPooledString(attributeKey.hashCode()));
                                    }
                                  catch(Exception ex2)
                                  {
                                    logger.error("Got error trying to flushGroup 2:" + ex2.getMessage());
                                    cacheInstance.flushAll();
                                  }
                                    break outer;
                                }
                                t.printElapsedTime("Handled group entries");
                                //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Handled group entries", t.getElapsedTime());
                                }
                              }
                            }
                            else
                            {
                              String attributeKey = "content_" + contentId + "_" + changedAttributeName;
                              //cacheInstance.flushGroup("content_" + contentId + "_" + changedAttributeName);
                              cacheInstance.flushGroup(getPooledString(attributeKey.hashCode()));
                              logger.info("Cleared pageCache for " + "content_" + contentId + "_" + changedAttributeName);
                            }
                          } 
                          //cacheInstance.flushGroup("content_" + contentId);
                        }
                        else
                        {
                          String contentTypeDefKey = "selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentTypeDefinitionId;
                          //cacheInstance.flushGroup(contentTypeDefKey);
                          cacheInstance.flushGroup(contentTypeDefKey);
                          //System.out.println("Cleared for " + "content_" + contentId + " on cache " + cacheName);
                          String contentKey = "content_" + contentId;
                          cacheInstance.flushGroup(contentKey);
                          //cacheInstance.flushGroup(contentKey);
                        }

                        //t.printElapsedTime("Handled page cache");
                      //RequestAnalyser.getRequestAnalyser().registerComponentStatistics("Handled page cache", t.getElapsedTime()); 
                        logger.info("After flushGroup2...");
                      }
                      //}

                    if (cacheName.equals("contentVersionCache"))
                    {
                      new AssetUpdatingThread(entityId).start();
                    }
                    }
                    catch(SystemException se)
                    {
                      se.printStackTrace();
                      logger.info("Missing content version: " + se.getMessage());
                    }
                    catch(Exception ex)
                    {
                      ex.printStackTrace();
                    }
                  }
                  else if(selectiveCacheUpdate && (entity.indexOf("Content") > 0 && entity.indexOf("ContentTypeDefinition") == -1 && entity.indexOf("ContentCategory") == -1) && useSelectivePageCacheUpdate)
                  {
                    logger.info("Content entity was sent: " + entity + ":" + entityId);
                    //System.out.println("Content entity was called and needs to be fixed:" + entity);
                   
                    //String[] changedAttributes = new String[]{"Title","NavigationTitle"};
                    /*
                    ContentVO contentVO = null;
                    if(isObjectCachedInCastor(SmallContentImpl.class, new Integer(entityId)))
                      contentVO = ContentController.getContentController().getContentVOWithId(new Integer(entityId));
                    */
                   
                    String repositoryId = sentRepositoryId;
                    String contentTypeDefinitionId = sentContentTypeDefinitionId;
                    String contentIsProtected = sentContentIsProtected;
                    if(repositoryId == null || contentTypeDefinitionId == null || contentIsProtected == null)
                    {
                      //System.out.println("repositoryId:" + repositoryId);
                      //System.out.println("contentTypeDefinitionId:" + contentTypeDefinitionId);
                      //System.out.println("contentIsProtected:" + contentIsProtected);
                      try
                      {
                        ContentVO contentVO = ContentController.getContentController().getContentVOWithId(new Integer(entityId));
                        //t.printElapsedTime("clearCaches cv u1 contentVO", 10);
                      repositoryId = ""+contentVO.getRepositoryId();
                      contentTypeDefinitionId = ""+contentVO.getContentTypeDefinitionId();
                      contentIsProtected = ""+contentVO.getIsProtected();
                      }
                      catch (Exception e2)
                      {
                        logger.info("Error loading content with id " + entityId + ":" + e2.getMessage());
                    }
                    }
                   
                    if(cacheName.equals("componentPropertyCacheRepoGroups") || cacheName.equals("componentPropertyVersionIdCacheRepoGroups"))
                    {
                      cacheInstance.flushGroup("" + repositoryId);
                      logger.info("Clearing componentPropertyCacheRepoGroups for repo:" + repositoryId);
                    }

                    if(cacheName.equals("pageCacheExtra"))
                    {
                      //clearFileCacheForGroup(cacheInstance, "content_" + entityId);
                      PageCacheHelper.getInstance().notify("content_" + entityId);

                      try
                      {
                        //cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentVO.getContentTypeDefinitionId());
                        if(contentTypeDefinitionId != null)
                        {
                          //clearFileCacheForGroup(cacheInstance, "selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentVO.getContentTypeDefinitionId());
                          PageCacheHelper.getInstance().notify("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentTypeDefinitionId);
                        }
                      }
                      catch (Exception e2)
                      {
                        logger.warn("Could not find content type to clear pages based on: " + e2.getMessage(), e2);
                    }
                    }
                    else if(cacheName.equals("pageCache"))
                    {
                      logger.info("Flushing page cache for {" + entityId + "} and {content_" + entityId + "}");
                     
                      String entityKey = "" + entityId;
                      String contentEntityKey = "content_" + entityId;
                      //cacheInstance.flushGroup("" + entityId);
                      //cacheInstance.flushGroup(contentEntityKey);
                      cacheInstance.flushGroup(entityKey);
                      cacheInstance.flushGroup(contentEntityKey);
                      try
                      {
                        if(contentTypeDefinitionId != null)
                        {
                          String contentTypeCacheKey = "selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentTypeDefinitionId;
                          //cacheInstance.flushGroup(contentTypeCacheKey);
                          cacheInstance.flushGroup(contentTypeCacheKey);
                        }
                      }
                      catch (Exception e2)
                      {
                        logger.warn("Could not find content type to clear pages based on: " + e2.getMessage(), e2);
                    }
                    }
                    else
                    {
                      cacheInstance.flushGroup("" + entityId);
                      cacheInstance.flushGroup("content_" + entityId);
                      logger.info("clearing " + e.getKey() + " with selectiveCacheUpdateNonApplicable");
                      cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");
                      if(contentTypeDefinitionId != null)
                      {
                        cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentTypeDefinitionId);
                      }
                    }
                   
                    if(contentTypeDefinitionId != null)
                    {
                      //System.out.println("****************************************************************");
                      if(contentIsProtected.equals(""+ContentVO.YES.intValue()))
                      {
                        List<InterceptionPointVO> interceptionPointVOList = InterceptionPointController.getController().getInterceptionPointVOList("Content");
                        for(InterceptionPointVO interceptionPointVO : interceptionPointVOList)
                        {
                          if(interceptionPointVO.getName().endsWith(".Read"))
                          {
                            String acKey = "" + interceptionPointVO.getId() + "_" + entityId;
                            //System.out.println("Clearing access rights for:" + acKey);
                            CacheController.clearUserAccessCache(acKey);                     
                          }
                        }
                      }
                    }
                    //System.out.println("************************END************************************");

                    logger.info("clearing " + e.getKey() + " with group " + "content_" + entityId);
                }
                  else if(selectiveCacheUpdate && entity.indexOf("DigitalAsset") > -1)
                  {
                    logger.info("Asset entity was sent: " + entity + ":" + entityId);
                    Integer contentId = assetContentIdMapping.get(new Integer(entityId));
                    if(contentId == null)
                    {
                      logger.info("Checking fot cv for asset:" + entityId);
                      List<SmallestContentVersionVO> contentVersions = DigitalAssetController.getContentVersionVOListConnectedToAssetWithId(new Integer(entityId));
                      if(contentVersions != null)
                      {
                        for(SmallestContentVersionVO contentVersionVO : contentVersions)
                        {
                          contentId = contentVersionVO.getContentId();
                          assetContentIdMapping.put(new Integer(entityId), contentId);
                          break;
                        }
                      }
                    }
                    else
                      logger.info("Using read asset");
                   
                    //Integer contentId = null;
                   
                    ContentVO contentVO = null;
                    try
                    {
                      contentVO = ContentController.getContentController().getContentVOWithId(contentId);
                   
                      if(cacheName.equals("componentPropertyCacheRepoGroups") || cacheName.equals("componentPropertyVersionIdCacheRepoGroups"))
                      {
                        cacheInstance.flushGroup("" + contentVO.getRepositoryId());
                        logger.info("Clearing componentPropertyCacheRepoGroups for repo:" + contentVO.getRepositoryId());
                      }
                    }
                    catch (Exception e2)
                    {
                      logger.info("Error loading content with id " + contentId + ":" + e2.getMessage());
                  }
                    //ContentVO contentVO = ContentController.getContentController().getContentVOWithId(new Integer(entityId));
                   
                    if(cacheName.equals("pageCacheExtra"))
                    {
                      //clearFileCacheForGroup(cacheInstance, "content_" + entityId);
                      PageCacheHelper.getInstance().notify("content_" + contentId);

                      try
                      {
                        //cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentVO.getContentTypeDefinitionId());
                        if(contentVO != null)
                        {
                          //clearFileCacheForGroup(cacheInstance, "selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentVO.getContentTypeDefinitionId());
                          PageCacheHelper.getInstance().notify("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentVO.getContentTypeDefinitionId());
                        }
                      }
                      catch (Exception e2)
                      {
                        logger.warn("Could not find content type to clear pages based on: " + e2.getMessage(), e2);
                    }
                    }
                    else if(cacheName.equals("pageCache"))
                    {
                      logger.info("Flushing page cache for {" + contentId + "} and {content_" + contentId + "}");
                     
                      String entityKey = "" + contentId;
                      String contentEntityKey = "content_" + contentId;
                      //cacheInstance.flushGroup("" + entityId);
                      //cacheInstance.flushGroup(contentEntityKey);
                      cacheInstance.flushGroup(entityKey);
                      cacheInstance.flushGroup(contentEntityKey);
                      try
                      {
                        if(contentVO != null)
                        {
                          String contentTypeCacheKey = "selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentVO.getContentTypeDefinitionId();
                          //cacheInstance.flushGroup(contentTypeCacheKey);
                          cacheInstance.flushGroup(contentTypeCacheKey);
                        }
                      }
                      catch (Exception e2)
                      {
                        logger.warn("Could not find content type to clear pages based on: " + e2.getMessage(), e2);
                    }
                    }
                    else
                    {
                      cacheInstance.flushGroup("" + contentId);
                      cacheInstance.flushGroup("content_" + contentId);
                      logger.info("clearing " + e.getKey() + " with selectiveCacheUpdateNonApplicable");
                      cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");
                    }

                    logger.info("clearing " + e.getKey() + " with group " + "content_" + entityId);
                }
                  else if(selectiveCacheUpdate && entity.indexOf("Publication") > 0 && useSelectivePageCacheUpdate && (operatingMode != null && operatingMode.equalsIgnoreCase("3")) && CmsPropertyHandler.getLivePublicationThreadClass().equalsIgnoreCase("org.infoglue.deliver.util.SelectiveLivePublicationThread"))
                  {
                    logger.info("Now we will ease out the publication...");
                  /*
                    List publicationDetailVOList = PublicationController.getController().getPublicationDetailVOList(new Integer(entityId));
                  Iterator publicationDetailVOListIterator = publicationDetailVOList.iterator();
                  while(publicationDetailVOListIterator.hasNext())
                  {
                    PublicationDetailVO publicationDetailVO = (PublicationDetailVO)publicationDetailVOListIterator.next();
                    logger.info("publicationDetailVO.getEntityClass():" + publicationDetailVO.getEntityClass());
                    logger.info("publicationDetailVO.getEntityId():" + publicationDetailVO.getEntityId());
                    if(Class.forName(publicationDetailVO.getEntityClass()).getName().equals(ContentVersion.class.getName()))
                    {
                      logger.error("We clear all caches having references to contentVersion: " + publicationDetailVO.getEntityId());
                      Integer contentId = ContentVersionController.getContentVersionController().getContentIdForContentVersion(publicationDetailVO.getEntityId());

                        cacheInstance.flushGroup("content_" + contentId);
                        cacheInstance.flushGroup(CacheController.getPooledString(2, publicationDetailVO.getEntityId().toString()));
                        cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable");
                        logger.info("clearing " + e.getKey() + " with group " + "content_" + contentId);
                        logger.info("clearing " + e.getKey() + " with group " + "content_" + contentId);
                    }
                    else if(Class.forName(publicationDetailVO.getEntityClass()).getName().equals(SiteNodeVersion.class.getName()))
                    {
                      Integer siteNodeId = SiteNodeVersionController.getController().getSiteNodeVersionVOWithId(publicationDetailVO.getEntityId()).getSiteNodeId();
                        CacheController.clearCaches(publicationDetailVO.getEntityClass(), publicationDetailVO.getEntityId().toString(), null);
                    }
                   
                  }
                  */
                }
                  else if(entity.equals("org.infoglue.cms.entities.management.impl.simple.AccessRightImpl"))
                  {
                    //System.out.println("This was an access right update - do we handle it:" + cacheName);
                    if(!CmsPropertyHandler.getOperatingMode().equalsIgnoreCase("3"))
                    {
                      try
                      {
                        AccessRightVO acVO = AccessRightController.getController().getAccessRightVOWithId(new Integer(entityId));
                        InterceptionPointVO icpVO = InterceptionPointController.getController().getInterceptionPointVOWithId(acVO.getInterceptionPointId());
                        //System.out.println("icpVO:" + icpVO.getName());
                        if(icpVO.getName().indexOf("Content.") > -1)
                        {
                          //System.out.println("Was a content access... let's clear caches for that content.");
                          String idAsString = acVO.getParameters();
                          if(idAsString != null && !idAsString.equals(""))
                            clearCaches("org.infoglue.cms.entities.content.impl.simple.ContentImpl", idAsString, null, cachesToSkip, forceClear);
                        }
                        else if(icpVO.getName().indexOf("ContentVersion.") > -1)
                        {
                          //System.out.println("Was a contentversion access... let's clear caches for that content.");
                          String idAsString = acVO.getParameters();
                          if(idAsString != null && !idAsString.equals(""))
                            clearCaches("org.infoglue.cms.entities.content.impl.simple.ContentVersionImpl", idAsString, null, cachesToSkip, forceClear);                       
                        }
                        else if(icpVO.getName().indexOf("SiteNode.") > -1)
                        {
                          //System.out.println("Was a sitenode access... let's clear caches for that content.");
                          String idAsString = acVO.getParameters();
                          if(idAsString != null && !idAsString.equals(""))
                            clearCaches("org.infoglue.cms.entities.structure.impl.simple.SiteNodeImpl", idAsString, null, cachesToSkip, forceClear);                                               
                        }
                      else if(icpVO.getName().indexOf("SiteNodeVersion.") > -1)
                      {
                        //System.out.println("Was a sitenode version access... let's clear caches for that content.");
                          String idAsString = acVO.getParameters();
                          if(idAsString != null && !idAsString.equals(""))
                            clearCaches("org.infoglue.cms.entities.structure.impl.simple.SiteNodeVersionImpl", idAsString, null, cachesToSkip, forceClear);                                               
                      }
                      else
                      {
                        //System.out.println("****************************");
                        //System.out.println("* WHAT TO DO WITH IN CACHECONTROLLER: " + icpVO.getName() + " *");
                        //System.out.println("****************************");
                      }
                      }
                      catch(Exception e2)
                      {
                        logger.error("Error handling access right update: " + e2.getMessage(), e2);
                      }
                    }
                    else
                      logger.info("Skipping it as this is live mode..");
                  }
                  else if(selectiveCacheUpdate && (entity.indexOf("ServiceBinding") > 0 || entity.indexOf("Qualifyer") > 0))
                  {
                    logger.info("Ignoring this kind of notification... never used anymore:" + cacheName);
                  }
                  else if(entity.indexOf("AccessRightImpl") > -1)
                  {
                    logger.info("Ignoring handling of entity:" + entity);
                  }
                  else if(cacheName.equalsIgnoreCase("matchingContentsCache") && entity.indexOf("MediumContentCategoryImpl") > 0)
                  {
                    try
                    {
                      String contentId = sentContentId;
                      //if(contentId == null || contentId.equals(""))
                       
                      ContentCategoryVO contentCategoryVO = ContentCategoryController.getController().findById(new Integer(entityId));
                      ContentVersionVO contentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(contentCategoryVO.getContentVersionId());
                      ContentVO contentVO = ContentController.getContentController().getContentVOWithId(contentVersionVO.getContentId());
                      String contentTypeDefinitionId = "" + contentVO.getContentTypeDefinitionId();
                      cacheInstance.flushGroup("selectiveCacheUpdateNonApplicable_contentTypeDefinitionId_" + contentTypeDefinitionId);
                      cacheInstance.putInCache("recacheMark_" + contentTypeDefinitionId, "" + System.currentTimeMillis());
                      cacheInstance.putInCache("recacheMark", "" + System.currentTimeMillis());
                    }
                    catch (Exception e2)
                    {
                      cacheInstance.putInCache("recacheAllMark", "" + System.currentTimeMillis());
                      logger.warn("Flushing all as it was a missing entity - was probably a delete: " + e2.getMessage());
                      cacheInstance.flushAll();
                  }
                  }
                  else if(entity.indexOf("MediumContentCategoryImpl") > 0)
                  {
                    logger.info("Special handling - no handling");
                  }
                  else if(cacheName.equalsIgnoreCase("componentEditorVersionIdCache") && entity.indexOf("ContentVersionImpl") > 0)
                  {
                    logger.info("Special handling componentEditorVersionIdCache");
                    String contentId = sentContentId;
                    if(contentId == null || contentId.equals(""))
                      contentId = ""+ContentVersionController.getContentVersionController().getContentIdForContentVersion(new Integer(entityId));

                    cacheInstance.flushGroup("content_" + contentId);
                    cacheInstance.flushGroup("contentVersion_" + entityId);
                  }
                  else if((cacheName.equalsIgnoreCase("componentEditorCache") ||
                      cacheName.equalsIgnoreCase("componentPropertyCache") ||
                      cacheName.equalsIgnoreCase("componentPropertyVersionIdCache") ||
                      cacheName.equalsIgnoreCase("pageComponentsCache"))
                      && entity.indexOf("ContentVersionImpl") > 0)
                  {
                    try
                    {
                      logger.info("Special handling componentEditorVersionIdCache");
                      String contentId = sentContentId;
                      if(contentId == null || contentId.equals(""))
                        contentId = ""+ContentVersionController.getContentVersionController().getContentIdForContentVersion(new Integer(entityId));
                     
                      ContentVO contentVO = ContentController.getContentController().getContentVOWithId(new Integer(contentId));
                      if(contentVO != null && contentVO.getContentTypeDefinitionId() != null)
                      {
                        ContentTypeDefinitionVO ctdVO = ContentTypeDefinitionController.getController().getContentTypeDefinitionVOWithId(contentVO.getContentTypeDefinitionId());
                        if(ctdVO.getName().equals("Meta info"))
                          cacheInstance.flushAll();
                        else
                        {
                          if(cacheName.equalsIgnoreCase("componentEditorCache") && (ctdVO.getName().equals("HTMLTemplate") || ctdVO.getName().equals("PagePartTemplate")))
                          {
                            cacheInstance.flushAll(); //CacheController.clearCache("componentEditorCache");
                          }
                          else
                            logger.info("No need to clear page stuff");
                        }
                      }
                    }
                    catch (Exception e2)
                    {
                      if(e2.getCause() instanceof ObjectNotFoundException || (e2.getCause() != null && e2.getCause().getCause() instanceof ObjectNotFoundException))
                        logger.info("Error clearing caches - object was probably deleted.");
                      else
                        logger.warn("Error handling mixed caches: " + e2.getMessage(), e2);
                  }
                  }
                  else
                  {
                    if(entity.indexOf("EventImpl") == -1 && entity.indexOf(".Publication") == -1)
                    {
                      if(logger.isInfoEnabled())
                        logger.info("WHOOOAAAAAAAAAA.. clearing all... on " + cacheName + ":" + entity);
                      //System.out.println("selectiveCacheUpdate:" + selectiveCacheUpdate);
                      //System.out.println("entity:" + entity);
                      //System.out.println("cacheName:" + cacheName);
                      //logger.info("Flushing all:" + cacheName);
                      cacheInstance.flushAll();
                      if(logger.isInfoEnabled())
                        logger.info("clearing:" + e.getKey());
                    //t.printElapsedTime("WHOOOAAAAAAAAAA.. clearing all... ", 10);
                  }
                  }
              } //BACK
            }
           
            long elapsedTime = t.getElapsedTime();
            if(elapsedTime > 20)
              logger.warn("Clear cache end took " + e.getKey() + ": " + elapsedTime);
            logger.info("Cleared cache:" + e.getKey());
 
            if(!selectiveCacheUpdate)
                i.remove();
           
          }
          else
          {
            logger.info("Did not clear " + e.getKey());
          }
        }
      //}
     
        if(!useSelectivePageCacheUpdate || entity.indexOf("AccessRight") > -1)
        {
          logger.info("Clearing all pageCaches");
          CacheController.clearFileCaches("pageCache");
        }
    }
       
    t.printElapsedTime("clearCaches stop", 100);
    /*
    logger.info("clearCaches stop");
    long time = t.getElapsedTime();
    if(time > 3000)
      logger.warn("clearCaches took long time:" + time);
    */
  }
 
  private static void printThreads()
  {
      ThreadGroup tg = Thread.currentThread().getThreadGroup();
      int n = tg.activeCount();
        logger.warn("Number of active threads: " + n);
      Thread[] threadArray = new Thread[n];
        n = tg.enumerate(threadArray, false);
        for (int i=0; i<n; i++)
        {
             String currentThreadId = "" + threadArray[i].getId();
          Thread t = threadArray[i];
          Map stacks = t.getAllStackTraces();
         
          Iterator stacksIterator = stacks.values().iterator();
          while(stacksIterator.hasNext())
          {
            StackTraceElement[] el = (StackTraceElement[])stacksIterator.next();
           
            String stackString = "";
            if (el != null && el.length != 0)
            {
                for (int j = 0; j < el.length; j++)
                {
                  StackTraceElement frame = el[j];
                  if (frame == null)
                    stackString += "    null stack frame" + "<br/>";
                  else 
                      stackString += "    null stack frame" + frame.toString() + "<br/>";
          }                   
                logger.warn("\n\nThreads:\n\n " + stackString);
             }
          }
        } 
  }

  public static void clearCastorCaches(DefeatCacheParameters dcp) throws Exception
  {
      if(CmsPropertyHandler.getApplicationName().equals("cms"))
        logger.info("Emptying the Castor Caches - why");
     
    long wait = 0;
   
    while(!getForcedCacheEvictionMode() && RequestAnalyser.getRequestAnalyser().getApproximateNumberOfDatabaseQueries() > 0)
    //while(!getForcedCacheEvictionMode() && RequestAnalyser.getRequestAnalyser().getNumberOfActiveRequests() > 0)
    {
        if(wait > 1000)
      {
        logger.warn("The clearCastorCaches method waited over " + ((wait * 10) / 1000) + " seconds but there seems to be " + RequestAnalyser.getRequestAnalyser().getApproximateNumberOfDatabaseQueries() + " queries blocking all the time. Continuing anyway.");
        break;
      }

          if(wait > 100)
        setForcedCacheEvictionMode(true);

      Thread.sleep(10);
      wait++;
      }
     
    Database db = CastorDatabaseService.getDatabase();
    //CastorDatabaseService.setBlock(true);
   
    try
    {   
        //db.getCacheManager().expireCache();
      Map<Class,List<Object>> entities = dcp.getEntities();
      Iterator<Class> keyIterator = entities.keySet().iterator();
      while(keyIterator.hasNext())
      {
        Class clazz = keyIterator.next();
        List<Object> ids = entities.get(clazz);
        if(ids.size() > 0)
        {
          clearCache(clazz, ids.toArray(), true, db);
          logger.info("Emptied clazz:" + clazz + " with ids:" + ids);
        }
        else
        {
          clearCache(db, clazz);
          logger.info("Emptied clazz:" + clazz);
        }
      }
        //commitTransaction(db);

      logger.info("Emptied the Castor Caches");
    }
    catch(Exception e)
    {
        logger.error("Exception when tried empty the Castor Caches");
        rollbackTransaction(db);
    }
    finally
    {
      db.close();
      //CastorDatabaseService.setBlock(false);
    }
  }
 
  public static void clearCastorCaches() throws Exception
  {
    if(CmsPropertyHandler.getApplicationName().equals("cms"))
        System.out.println("Emptying the Castor Caches... why");
           
    long wait = 0;
   
    while(!getForcedCacheEvictionMode() && RequestAnalyser.getRequestAnalyser().getApproximateNumberOfDatabaseQueries() > 0)
    //while(!getForcedCacheEvictionMode() && RequestAnalyser.getRequestAnalyser().getNumberOfActiveRequests() > 0)
    {
        if(wait > 1000)
      {
        logger.warn("The clearCastorCaches method waited over " + ((wait * 10) / 1000) + " seconds but there seems to be " + RequestAnalyser.getRequestAnalyser().getApproximateNumberOfDatabaseQueries() + " queries blocking all the time. Continuing anyway.");
        break;
      }

          if(wait > 100)
        setForcedCacheEvictionMode(true);

      Thread.sleep(10);
      wait++;
      }
     
    Database db = CastorDatabaseService.getDatabase();
    //CastorDatabaseService.setBlock(true);
   
    try
    {   
        //db.getCacheManager().expireCache();

        clearCache(db, SmallContentImpl.class);
        clearCache(db, SmallishContentImpl.class);
      clearCache(db, MediumContentImpl.class);
      clearCache(db, ContentImpl.class);
      clearCache(db, ContentRelationImpl.class);
      clearCache(db, SmallContentVersionImpl.class);
      clearCache(db, SmallestContentVersionImpl.class);
      clearCache(db, ContentVersionImpl.class);
      clearCache(db, DigitalAssetImpl.class);
      clearCache(db, SmallDigitalAssetImpl.class);
      clearCache(db, MediumDigitalAssetImpl.class);
      clearCache(db, SmallAvailableServiceBindingImpl.class);
      clearCache(db, AvailableServiceBindingImpl.class);
      clearCache(db, ContentTypeDefinitionImpl.class);
      clearCache(db, LanguageImpl.class);
      clearCache(db, RepositoryImpl.class);
      clearCache(db, RepositoryLanguageImpl.class);
      clearCache(db, RoleImpl.class);
      clearCache(db, GroupImpl.class);
      clearCache(db, SmallRoleImpl.class);
      clearCache(db, SmallGroupImpl.class);
      clearCache(db, SystemUserRoleImpl.class);
      clearCache(db, SystemUserGroupImpl.class);
      clearCache(db, ServiceDefinitionImpl.class);
      clearCache(db, SiteNodeTypeDefinitionImpl.class);
      clearCache(db, SystemUserImpl.class);
      clearCache(db, SmallSystemUserImpl.class);
      clearCache(db, QualifyerImpl.class);
      clearCache(db, ServiceBindingImpl.class);
      clearCache(db, SmallSiteNodeImpl.class);
      clearCache(db, SiteNodeImpl.class);
      clearCache(db, SiteNodeVersionImpl.class);
      clearCache(db, SmallSiteNodeVersionImpl.class);
      clearCache(db, PublicationImpl.class);
      //clearCache(db, PublicationDetailImpl.class); // This class depends on publication
      clearCache(db, ActionImpl.class);
      clearCache(db, ActionDefinitionImpl.class);
      clearCache(db, ActorImpl.class);
      clearCache(db, ConsequenceImpl.class);
      clearCache(db, ConsequenceDefinitionImpl.class);
      clearCache(db, EventImpl.class);
      clearCache(db, WorkflowImpl.class);
      clearCache(db, WorkflowDefinitionImpl.class);
      clearCache(db, CategoryImpl.class);
      clearCache(db, ContentCategoryImpl.class);
      clearCache(db, RegistryImpl.class);
      clearCache(db, RedirectImpl.class);
     
      clearCache(db, InterceptionPointImpl.class);
      clearCache(db, InterceptorImpl.class);
      clearCache(db, AccessRightImpl.class);
      clearCache(db, AccessRightRoleImpl.class);
      clearCache(db, AccessRightGroupImpl.class);
      clearCache(db, AccessRightUserImpl.class);
 
      clearCache(db, RolePropertiesImpl.class);
      clearCache(db, UserPropertiesImpl.class);
      clearCache(db, GroupPropertiesImpl.class);
      clearCache(db, UserContentTypeDefinitionImpl.class);
      clearCache(db, RoleContentTypeDefinitionImpl.class);
      clearCache(db, GroupContentTypeDefinitionImpl.class);     

      clearCache(db, PropertiesCategoryImpl.class);
     
      clearCache(db, ServerNodeImpl.class);     

      clearCache(db, SubscriptionImpl.class);
      clearCache(db, FormEntryImpl.class);
      clearCache(db, FormEntryValueImpl.class);

        //commitTransaction(db);

      logger.info("Emptied the Castor Caches");
    }
    catch(Exception e)
    {
        logger.error("Exception when tried empty the Castor Caches");
        rollbackTransaction(db);
    }
    finally
    {
      db.close();
      //CastorDatabaseService.setBlock(false);
    }
  }
 

  public static void clearCache(Class type, Object[] ids) throws Exception
  {
    clearCache(type, ids, false);
  }
 
  public static void clearCache(Class type, Object[] ids, boolean forceClear) throws Exception
  {   
    Timer t = new Timer();
   
    if(CmsPropertyHandler.getOperatingMode().equals("3"))
    {
      long wait = 0;
      while(!forceClear && !getForcedCacheEvictionMode() && RequestAnalyser.getRequestAnalyser().getApproximateNumberOfDatabaseQueries() > 0)
      {
            logger.warn("Number of requests: " + RequestAnalyser.getRequestAnalyser().getNumberOfCurrentRequests() + " was more than 0 - lets wait a bit.");
            if(wait > 1000)
        {
          logger.warn("The clearCache method waited over " + ((wait * 10) / 1000) + " seconds but there seems to be " + RequestAnalyser.getRequestAnalyser().getNumberOfCurrentRequests() + " requests blocking all the time. Continuing anyway.");
          //printThreads();
          break;
        }
 
            if(wait > 100)
          setForcedCacheEvictionMode(true);
 
        Thread.sleep(10);
        wait++;
        }
    }
   
      Database db = CastorDatabaseService.getDatabase();
    try
    {
      if(type.getName().contains(".SiteNodeVersionImpl") ||
         type.getName().contains(".MediumSiteNodeVersionImpl") ||
         type.getName().contains(".SiteNodeImpl") ||
         type.getName().contains(".LanguageImpl") ||
         type.getName().contains(".RepositoryImpl") ||
         type.getName().contains(".RepositoryLanguageImpl") ||
         type.getName().contains(".DigitalAssetImpl") ||
         type.getName().contains(".MediumDigitalAssetImpl") ||
         type.getName().contains(".ContentVersionImpl") ||
         type.getName().contains(".AccessRightRoleImpl") ||
         type.getName().contains(".AccessRightGroupImpl") ||
         type.getName().contains(".AccessRightUserImpl") ||
         type.getName().contains(".RegistryImpl"))
      {
        logger.info("Skipping clear of " + type);
      }
      else
      {
        logger.info("Clearing " + type);
          CacheManager manager = db.getCacheManager();
          manager.expireCache(type, ids);
          //Class[] types = {type};
          //db.expireCache(types, ids);
      }
     
        if(type.getName().equalsIgnoreCase(SmallContentImpl.class.getName()) ||
           type.getName().equalsIgnoreCase(SmallishContentImpl.class.getName()) ||
           type.getName().equalsIgnoreCase(MediumContentImpl.class.getName()) ||
           type.getName().equalsIgnoreCase(ContentImpl.class.getName()) ||
           type.getName().equalsIgnoreCase(SmallSiteNodeImpl.class.getName()) ||
         type.getName().equalsIgnoreCase(SiteNodeImpl.class.getName()))
        {
            expireDateTime = null;
            publishDateTime = null;
        }
    }
    catch(Exception e)
    {
      logger.error("Error clearing cache:" + e.getMessage() + " for type:" + type + ":" + ids + ":" + forceClear);
    }
    finally
    {
      try
      {
        db.close();
      }
      catch (Exception e)
      {
        logger.error("Error closing database: " + e.getMessage());
      }
    }
  }

  public static void clearCache(Class c) throws Exception
  {
      Database db = CastorDatabaseService.getDatabase();

    try
    {
      clearCache(db, c);
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
    finally
    {
      db.close();     
    }
  } 
 
  public static void clearCache(Class type, Object[] ids, Database db) throws Exception
  {
    clearCache(type, ids, false, db);
  }
 
  public static void clearCache(Class type, Object[] ids, boolean forceClear, Database db) throws Exception
  {
    long wait = 0;
      while(!forceClear && !getForcedCacheEvictionMode() && RequestAnalyser.getRequestAnalyser().getApproximateNumberOfDatabaseQueries() > 0)
    {
          if(wait > 1000)
      {
        logger.warn("The clearCache method waited over " + ((wait * 10) / 1000) + " seconds but there seems to be " + RequestAnalyser.getRequestAnalyser().getNumberOfCurrentRequests() + " requests blocking all the time. Continuing anyway.");
        //printThreads();
        break;
      }

          if(wait > 100)
        setForcedCacheEvictionMode(true);

          Thread.sleep(10);
          wait++;
      }
   
    if(type.getName().contains(".SiteNodeVersionImpl") ||
       type.getName().contains(".MediumSiteNodeVersionImpl") ||
       type.getName().contains(".SiteNodeImpl") ||
       type.getName().contains(".LanguageImpl") ||
       type.getName().contains(".RepositoryImpl") ||
       type.getName().contains(".RepositoryLanguageImpl") ||
       type.getName().contains(".DigitalAssetImpl") ||
       type.getName().contains(".MediumDigitalAssetImpl") ||
       type.getName().contains(".ContentVersionImpl") ||
       type.getName().contains(".AccessRightRoleImpl") ||
       type.getName().contains(".AccessRightGroupImpl") ||
       type.getName().contains(".AccessRightUserImpl") ||
       type.getName().contains(".RegistryImpl"))
    {
      logger.info("Skipping clear of " + type);
    }
    else
    {
      logger.info("Clearing for real: " + type);
        CacheManager manager = db.getCacheManager();
        manager.expireCache(type, ids);
        //Class[] types = {type};
        //db.expireCache(types, ids);
    }
   
      if(type.getName().equalsIgnoreCase(SmallContentImpl.class.getName()) ||
        type.getName().equalsIgnoreCase(SmallishContentImpl.class.getName()) ||
         type.getName().equalsIgnoreCase(MediumContentImpl.class.getName()) ||
         type.getName().equalsIgnoreCase(ContentImpl.class.getName()) ||
         type.getName().equalsIgnoreCase(SmallSiteNodeImpl.class.getName()) ||
       type.getName().equalsIgnoreCase(SiteNodeImpl.class.getName()))
      {
          expireDateTime = null;
          publishDateTime = null;
      }
  }

  public static void clearCache(Database db, Class c) throws Exception
  {
    long wait = 0;
    while(!getForcedCacheEvictionMode() && RequestAnalyser.getRequestAnalyser().getApproximateNumberOfDatabaseQueries() > 0)
    {
          if(wait > 1000)
      {
        logger.warn("The clearCache method waited over " + ((wait * 10) / 1000) + " seconds but there seems to be " + RequestAnalyser.getRequestAnalyser().getNumberOfCurrentRequests() + " requests blocking all the time. Continuing anyway.");
        //printThreads();
        break;
      }

          if(wait > 100)
        setForcedCacheEvictionMode(true);

          Thread.sleep(10);
          wait++;
      }

    if(c.getName().contains(".SiteNodeVersionImpl") ||
       c.getName().contains(".MediumSiteNodeVersionImpl") ||
       c.getName().contains(".SiteNodeImpl") ||
       c.getName().contains(".LanguageImpl") ||
       c.getName().contains(".RepositoryImpl") ||
       c.getName().contains(".RepositoryLanguageImpl") ||
       c.getName().contains(".DigitalAssetImpl") ||
       c.getName().contains(".MediumDigitalAssetImpl") ||
       c.getName().contains(".ContentVersionImpl") ||
       c.getName().contains(".MediumContentVersionImpl") ||
       c.getName().contains(".AccessRightRoleImpl") ||
       c.getName().contains(".AccessRightGroupImpl") ||
       c.getName().contains(".AccessRightUserImpl") ||
       c.getName().contains(".RegistryImpl"))
    {
      logger.info("Skipping " + c.getName() + " as they have no castor cache");
    }
    else
    {
      logger.info("Clearing for real: " + c);
      Class[] types = {c};
      CacheManager manager = db.getCacheManager();
      manager.expireCache(types);
      //db.expireCache(types, null);
    }
   
      if(c.getName().equalsIgnoreCase(SmallContentImpl.class.getName()) ||
        c.getName().equalsIgnoreCase(SmallishContentImpl.class.getName()) ||
         c.getName().equalsIgnoreCase(MediumContentImpl.class.getName()) ||
         c.getName().equalsIgnoreCase(ContentImpl.class.getName()) ||
         c.getName().equalsIgnoreCase(SmallSiteNodeImpl.class.getName()) ||
       c.getName().equalsIgnoreCase(SiteNodeImpl.class.getName()))
      {
          expireDateTime = null;
          publishDateTime = null;
      }
  }

 
  public void run()
  {
    while(this.continueRunning && expireCacheAutomatically)
    {
      logger.info("Clearing caches");
      try
      {
          clearCastorCaches();
      }
      catch(Exception e)
      {
          logger.error("Error clearing cache in expireCacheAutomatically thread:" + e.getMessage(), e);
      }
      logger.info("Castor cache cleared");
      try
      {
        clearCaches(null, null, null);
      }
      catch(Exception e)
      {
          logger.error("Error clearing other caches in expireCacheAutomatically thread:" + e.getMessage(), e);
      }
      logger.info("All other caches cleared");
     
      try
      {
        sleep(cacheExpireInterval);
      }
      catch (InterruptedException e){}
    }
  }

  public static void cacheCentralCastorCaches() throws Exception
  {
      Database db = CastorDatabaseService.getDatabase();

      DatabaseWrapper dbWrapper = new DatabaseWrapper(db);

    try
    {
       
        beginTransaction(db);
       
        String siteNodesToRecacheOnPublishing = CmsPropertyHandler.getSiteNodesToRecacheOnPublishing();
        String recachePublishingMethod = CmsPropertyHandler.getRecachePublishingMethod();
        logger.info("siteNodesToRecacheOnPublishing:" + siteNodesToRecacheOnPublishing);
        if(siteNodesToRecacheOnPublishing != null && !siteNodesToRecacheOnPublishing.equals("") && siteNodesToRecacheOnPublishing.indexOf("siteNodesToRecacheOnPublishing") == -1)
        {
            String[] siteNodeIdArray = siteNodesToRecacheOnPublishing.split(",");
            for(int i=0; i<siteNodeIdArray.length; i++)
            {
                Integer siteNodeId = new Integer(siteNodeIdArray[i]);
              logger.info("siteNodeId to recache:" + siteNodeId);
              if(recachePublishingMethod != null && recachePublishingMethod.equalsIgnoreCase("contentCentric"))
                  new ContentCentricCachePopulator().recache(dbWrapper, siteNodeId);
              else if(recachePublishingMethod != null && recachePublishingMethod.equalsIgnoreCase("requestCentric"))
                  new RequestCentricCachePopulator().recache(dbWrapper, siteNodeId);
              else if(recachePublishingMethod != null && recachePublishingMethod.equalsIgnoreCase("requestAndMetaInfoCentric"))
                  new RequestAndMetaInfoCentricCachePopulator().recache(dbWrapper, siteNodeId);
              else
                  logger.warn("No recaching was made during publishing - set the parameter recachePublishingMethod to 'contentCentric' or 'requestCentric' to recache.");
            }
        }
       
        commitTransaction(db);
    }
    catch(Exception e)
    {
      logger.error("An error occurred when we tried to rebuild the castor cache:" + e.getMessage(), e);
        rollbackTransaction(db);
    }
    finally
    {
        closeDatabase(db);
    }
  }
 
 
  public void stopThread()
  {
    this.continueRunning = false;
  }

  public boolean getExpireCacheAutomatically()
  {
    return expireCacheAutomatically;
  }

  public void setExpireCacheAutomatically(boolean expireCacheAutomatically)
  {
    this.expireCacheAutomatically = expireCacheAutomatically;
  }

    public static Map getCaches()
    {
        return caches;
    }

    public static void evictWaitingCache() throws Exception
    {     
      Timer t = new Timer();
         String operatingMode = CmsPropertyHandler.getOperatingMode();
      synchronized(RequestAnalyser.getRequestAnalyser())
      {
           if(RequestAnalyser.getRequestAnalyser().getBlockRequests() && RequestAnalyser.getRequestAnalyser().getBlockRequestTime() < 30000)
        {
          logger.warn("evictWaitingCache allready in progress - returning to avoid conflict");
          return;
        }
           else if(RequestAnalyser.getRequestAnalyser().getBlockRequests() && RequestAnalyser.getRequestAnalyser().getBlockRequestTime() > 30000)
             logger.warn("An block must have gone wrong... there has gone over 30 seconds and still not reported done.. let's run anyway.");

           RequestAnalyser.getRequestAnalyser().setBlockRequests(true);
    }
     
      logger.info("evictWaitingCache starting");
      logger.info("blocking");
      synchronized(notifications)
        {
          if(notifications == null || notifications.size() == 0)
          {
            logger.info("No notifications...");
            RequestAnalyser.getRequestAnalyser().setBlockRequests(false);
            return;
          }
        }
      logger.info("Had some notifications to handle:" + notifications.size());

      WorkingPublicationThread wpt = new WorkingPublicationThread();
     
      SelectiveLivePublicationThread pt = null;
      String livePublicationThreadClass = "";
      try
      {
        livePublicationThreadClass = CmsPropertyHandler.getLivePublicationThreadClass();
        if(operatingMode != null && operatingMode.equalsIgnoreCase("3")) //If published-mode we update entire cache to be sure..
      {
            if(livePublicationThreadClass.equalsIgnoreCase("org.infoglue.deliver.util.SelectiveLivePublicationThread"))
            pt = new SelectiveLivePublicationThread(notifications);
          }
      }
      catch (Exception e)
      {
      logger.error("Could not get livePublicationThreadClass:" + e.getMessage(), e);
    }
     
      List localNotifications = new ArrayList();
     
      boolean startedThread = false;

      if(pt == null)
      {
        logger.info("before notifications:" + notifications.size());
        synchronized(notifications)
          {
          localNotifications.addAll(notifications);
          notifications.clear();
          }
       
        Iterator i = localNotifications.iterator();
      while(i.hasNext())
      {
          CacheEvictionBean cacheEvictionBean = (CacheEvictionBean)i.next();
          String className = cacheEvictionBean.getClassName();
         
        logger.info("className:" + className);
        logger.info("pt:" + pt);
        //RequestAnalyser.getRequestAnalyser().addPublication("" + formatter.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss") + " - " + cacheEvictionBean.getClassName() + " - " + cacheEvictionBean.getObjectId());
       
          if(pt == null)
            wpt.getCacheEvictionBeans().add(cacheEvictionBean);
          //else
          //  pt.getCacheEvictionBeans().add(cacheEvictionBean);
            
        try
          {
          //Here we do what we need to if the server properties has changed.
            if(className != null && className.equalsIgnoreCase("ServerNodeProperties"))
            {
            try
            {
              logger.info("clearing InfoGlueAuthenticationFilter");
              clearServerNodeProperty(true);
              logger.info("cleared InfoGlueAuthenticationFilter");
              InfoGlueAuthenticationFilter.initializeProperties();
              logger.info("initialized InfoGlueAuthenticationFilter");
              logger.info("Shortening page stats");
              RequestAnalyser.shortenPageStatistics();
            }
            catch (Exception e1)
            {
              logger.warn("Could not refresh authentication filter:" + e1.getMessage(), e1);
            }
            catch (Throwable throwable)
            {
              logger.warn("Could not refresh authentication filter:" + throwable.getMessage(), throwable);
            }
            }
 
            if(operatingMode != null && !operatingMode.equalsIgnoreCase("3") && className != null && className.equalsIgnoreCase("PortletRegistry"))
            {
            logger.info("clearing portletRegistry");
            clearPortlets();
            logger.info("cleared portletRegistry");
            }
 
          if(operatingMode != null && operatingMode.equalsIgnoreCase("3")) //If published-mode we update entire cache to be sure..
          {
            if(!livePublicationThreadClass.equalsIgnoreCase("org.infoglue.deliver.util.SelectiveLivePublicationThread"))
            { 
                  logger.info("Starting publication thread...");
                    PublicationThread lpt = new PublicationThread();
                    lpt.setPriority(Thread.MIN_PRIORITY);
                    lpt.start();
                    startedThread = true;
                    logger.info("Done starting publication thread...");
                  }
                }
          }
          catch(Exception e)
          {
              logger.error("Cache eviction reported an error:" + e.getMessage(), e);
          }
 
            logger.info("Cache evicted..");
 
        i.remove();
      }
      }
     
    if(operatingMode != null && !operatingMode.equalsIgnoreCase("3"))
    {
      logger.info("Starting the work method");
      //wpt.setPriority(Thread.MAX_PRIORITY);
      //wpt.start();
        wpt.work();
        startedThread = true;
          logger.info("Done starting working publication thread...");
    }

    if(operatingMode != null && operatingMode.equalsIgnoreCase("3") && pt != null) //If published-mode we update entire cache to be sure..
    {
      int size = 0;
      synchronized(notifications)
          {
        size = notifications.size();
          }
     
      if(size > 0)
      {
        logger.info("Starting selective publication thread [" + pt.getClass().getName() + "]");
          pt.setPriority(Thread.MIN_PRIORITY);
          pt.start();
          startedThread = true;
          logger.info("Done starting publication thread...");
      }
    }
   
      if(!startedThread)
        RequestAnalyser.getRequestAnalyser().setBlockRequests(false);
     
      t.printElapsedTime("evict done");

        logger.info("evictWaitingCache stop");
    }

  public static void clearPortlets()
  {
     //run registry services to load new portlet info from the registry files
    String[] svcs =
    {
       "org.apache.pluto.portalImpl.services.portletdefinitionregistry.PortletDefinitionRegistryService",
       "org.apache.pluto.portalImpl.services.portletentityregistry.PortletEntityRegistryService"
     };
       
     int len = svcs.length;
     for (int i = 0; i < len; i++)
     {       
       try
       {
        ServiceManager.hotInit(ServletConfigContainer.getContainer().getServletConfig(), svcs[i]);
       }
       catch (Throwable e)
       {
         String svc = svcs[i].substring(svcs[i].lastIndexOf('.') + 1);
         String msg = "Initialization of " + svc + " service for hot deployment failed!";
         logger.error(msg);
         break;
       }
  
       try
       {
        ServiceManager.postHotInit(ServletConfigContainer.getContainer().getServletConfig(), svcs[i]);
       }
       catch (Throwable e)
       {
         String svc = svcs[i].substring(svcs[i].lastIndexOf('.') + 1);
         String msg = "Post initialization of " + svc + " service for hot deployment failed!";
         logger.error(msg);
         break;
       }
    }   
    
        try
    {
      PortletEntityRegistry.load();
    }
        catch (IOException e)
    {
      e.printStackTrace();
    }

  }
 
  public static String[] getPublicationPersistentCacheNames()
  {
    List<String> caches = new ArrayList<String>();

    caches.add("redirectCache");
    caches.add("languageCache");
    caches.add("childSiteNodesCache");
    caches.add("childPagesCache");
    caches.add("parentSiteNodeCache");
    caches.add("contentTypeDefinitionCache");
    caches.add("componentContentsCache");
    caches.add("contentVersionIdCache");
    caches.add("rootSiteNodeCache");
    caches.add("contentCache");
    caches.add("relatedCategoriesCache");
    caches.add("matchingContentsCache");
    caches.add("propertiesCategoryCache");
    caches.add("userCache");
    caches.add("siteNodeCache");
    caches.add("contentCategoryCache");
    caches.add("contentVersionCache");
    caches.add("digitalAssetCache");
    caches.add("latestSiteNodeVersionCache");
    caches.add("interceptionPointCache");
    caches.add("contentAttributeCache");   
    caches.add("metaInfoContentAttributeCache");   
    caches.add("ServerNodeProperties");
    caches.add("serverNodePropertiesCache");
    caches.add("pageCache");
    caches.add("pageCacheExtra");
    caches.add("componentCache");
    caches.add("NavigationCache");
    caches.add("pagePathCache");
    caches.add("userCache");
    caches.add("pageCacheParentSiteNodeCache");
    caches.add("pageCacheLatestSiteNodeVersions");
    caches.add("pageCacheSiteNodeTypeDefinition");
    caches.add("JNDIAuthorizationCache");
    caches.add("WebServiceAuthorizationCache");
    caches.add("importTagResultCache");
    caches.add("assetUrlCacheWithGroups");
    caches.add("componentPropertyCacheRepoGroups");
    caches.add("pageDeliveryMetaDataCache");

    List<String> userCaches = CmsPropertyHandler.getExtraPublicationPersistentCacheNames();
    logger.info("Adding ExtraPublicationPersistentCacheNames:" + userCaches);
    caches.addAll(userCaches);
   
    String[] cachesArr = caches.toArray(new String[caches.size()])
   
    return cachesArr;
  }
 
 
    /**
     * Composer of the pageCacheKey.
     *
     * @param siteNodeId
     * @param languageId
     * @param contentId
     * @param userAgent
     * @param queryString
     * @return
     */
   
    public static String getPageCacheKey(HttpSession session, HttpServletRequest request, Integer siteNodeId, Integer languageId, Integer contentId, String userAgent, String queryString, String extra)
    {       
      String originalRequestURL = request.getParameter("originalRequestURL");
      if(originalRequestURL == null || originalRequestURL.length() == 0)
        originalRequestURL = request.getRequestURL().toString();

      String pageKey = null;
      String pageKeyProperty = CmsPropertyHandler.getPageKey();
      if(pageKeyProperty != null && pageKeyProperty.length() > 0)
      {   
          pageKey = pageKeyProperty;
          pageKey = pageKey.replaceAll("\\$siteNodeId", "" + siteNodeId);
          pageKey = pageKey.replaceAll("\\$languageId", "" + languageId);
          pageKey = pageKey.replaceAll("\\$contentId", "" + contentId);
          pageKey = pageKey.replaceAll("\\$useragent", "" + userAgent);
          pageKey = pageKey.replaceAll("\\$queryString", "" + queryString);
         
          if(logger.isInfoEnabled())
          logger.info("Raw pageKey:" + pageKey);

          int sessionAttributeStartIndex = pageKey.indexOf("$session.");
          while(sessionAttributeStartIndex > -1)
          {
              int sessionAttributeEndIndex = pageKey.indexOf("_", sessionAttributeStartIndex);
              String sessionAttribute = null;
              if(sessionAttributeEndIndex > -1)
                  sessionAttribute = pageKey.substring(sessionAttributeStartIndex + 9, sessionAttributeEndIndex);
              else
                  sessionAttribute = pageKey.substring(sessionAttributeStartIndex + 9);

              Object sessionAttributeValue = session.getAttribute(sessionAttribute);
              if(sessionAttributeValue == null && sessionAttribute.equalsIgnoreCase("principal"))
                sessionAttributeValue = session.getAttribute("infogluePrincipal");
             
              if(logger.isInfoEnabled())
                logger.info("sessionAttribute:" + sessionAttribute);

              pageKey = pageKey.replaceAll("_\\$session." + sessionAttribute, "" + (sessionAttributeValue == null ? "" : "_" + sessionAttributeValue));         
         
              sessionAttributeStartIndex = pageKey.indexOf("$session.");
          }
        
          if(logger.isInfoEnabled())
          logger.info("after session pageKey:" + pageKey);

          int cookieAttributeStartIndex = pageKey.indexOf("$cookie.");
          while(cookieAttributeStartIndex > -1)
          {
              int cookieAttributeEndIndex = pageKey.indexOf("_", cookieAttributeStartIndex);
              String cookieAttribute = null;
              if(cookieAttributeEndIndex > -1)
                  cookieAttribute = pageKey.substring(cookieAttributeStartIndex + 8, cookieAttributeEndIndex);
              else
                  cookieAttribute = pageKey.substring(cookieAttributeStartIndex + 8);

              HttpHelper httpHelper = new HttpHelper();
              pageKey = pageKey.replaceAll("\\$cookie." + cookieAttribute, "" + httpHelper.getCookie(request, cookieAttribute));         
         
              cookieAttributeStartIndex = pageKey.indexOf("$cookie.");
          }
         
      }
      else
          pageKey  = "" + siteNodeId + "_" + languageId + "_" + contentId + "_" + userAgent + "_" + queryString;
     
      return originalRequestURL + "_" + pageKey + extra;
    }
   
    /**
     * Composer of the componentCacheKey.
     *
     * @param siteNodeId
     * @param languageId
     * @param contentId
     * @param userAgent
     * @param queryString
     * @return
     */
   
    public static String getComponentCacheKey(String keyPattern, String pageKey, HttpSession session, HttpServletRequest request, Integer siteNodeId, Integer languageId, Integer contentId, String userAgent, String queryString, InfoGlueComponent component, String extra)
    {       
      String originalRequestURL = request.getParameter("originalRequestURL");
      if(originalRequestURL == null || originalRequestURL.length() == 0)
        originalRequestURL = request.getRequestURL().toString();

      String componentKey = null;
      if(keyPattern != null && keyPattern.length() > 0)
      {   
        componentKey = keyPattern;
        componentKey = componentKey.replaceAll("\\$siteNodeId", "" + siteNodeId);
        componentKey = componentKey.replaceAll("\\$languageId", "" + languageId);
        componentKey = componentKey.replaceAll("\\$contentId", "" + contentId);
        componentKey = componentKey.replaceAll("\\$useragent", "" + userAgent);
        componentKey = componentKey.replaceAll("\\$queryString", "" + queryString);
         
        componentKey = componentKey.replaceAll("\\$pageKey", "" + pageKey);
        componentKey = componentKey.replaceAll("\\$component.id", "" + component.getId());
        componentKey = componentKey.replaceAll("\\$component.slotName", "" + component.getSlotName());
        componentKey = componentKey.replaceAll("\\$component.contentId", "" + component.getContentId());
        componentKey = componentKey.replaceAll("\\$component.isInherited", "" + component.getIsInherited());

          int sessionAttributeStartIndex = componentKey.indexOf("$session.");
          while(sessionAttributeStartIndex > -1)
          {
              int sessionAttributeEndIndex = componentKey.indexOf("_", sessionAttributeStartIndex);
              String sessionAttribute = null;
              if(sessionAttributeEndIndex > -1)
                  sessionAttribute = componentKey.substring(sessionAttributeStartIndex + 9, sessionAttributeEndIndex);
              else
                  sessionAttribute = componentKey.substring(sessionAttributeStartIndex + 9);

              Object sessionAttributeValue = session.getAttribute(sessionAttribute);
              if(sessionAttributeValue == null && sessionAttribute.equalsIgnoreCase("principal"))
                sessionAttributeValue = session.getAttribute("infogluePrincipal");

              componentKey = componentKey.replaceAll("\\$session." + sessionAttribute, "" + sessionAttributeValue);         
         
              sessionAttributeStartIndex = componentKey.indexOf("$session.");
          }
         
          int cookieAttributeStartIndex = componentKey.indexOf("$cookie.");
          while(cookieAttributeStartIndex > -1)
          {
              int cookieAttributeEndIndex = componentKey.indexOf("_", cookieAttributeStartIndex);
              String cookieAttribute = null;
              if(cookieAttributeEndIndex > -1)
                  cookieAttribute = componentKey.substring(cookieAttributeStartIndex + 8, cookieAttributeEndIndex);
              else
                  cookieAttribute = componentKey.substring(cookieAttributeStartIndex + 8);

              HttpHelper httpHelper = new HttpHelper();
              componentKey = componentKey.replaceAll("\\$cookie." + cookieAttribute, "" + httpHelper.getCookie(request, cookieAttribute));         
         
              cookieAttributeStartIndex = componentKey.indexOf("$cookie.");
          }
         
      }
     
      return componentKey;
    }

    private static String getCachedContentFromFile(String cacheName, String key, String charEncoding)
    {
      return getCachedContentFromFile(cacheName, key, null, charEncoding);
    }
   
    private static String getCachedContentFromFile(String cacheName, String key, Integer updateInterval, String charEncoding)
    {
      Timer t = new Timer();
      if(!logger.isInfoEnabled())
        t.setActive(false);

    String compressPageCache = CmsPropertyHandler.getCompressPageCache();

      String contents = null;
      try
      {
        String firstPart = ("" + key.hashCode()).substring(0, 3);
            String filePath = CmsPropertyHandler.getDigitalAssetPath() + File.separator + "caches" + File.separator + cacheName + File.separator + firstPart + File.separator + key.hashCode();
            File file = new File(filePath);
            if(file.exists())
            {
            //logger.info("updateInterval:" + updateInterval);
              if(updateInterval != null)
              {
                long updateDateTime = file.lastModified();
                long now = System.currentTimeMillis();
                //logger.info("diff:" + (now - updateDateTime) / 1000);
                if((now - updateDateTime) / 1000 < updateInterval)
                {
                  if(cacheName.equals("pageCache") && compressPageCache != null && compressPageCache.equals("true"))
                  {
                    byte[] cachedCompressedData = FileHelper.getFileBytes(file);
                     if(cachedCompressedData != null && cachedCompressedData.length > 0)
                       contents = compressionHelper.decompress(cachedCompressedData);   
                  }
                  else
                  {
                    //logger.info("getting file anyway:" + updateInterval);
                    contents = FileHelper.getFileAsStringOpt(file, charEncoding);
                  }

                  //contents = FileHelper.getFileAsString(file, charEncoding);
                }
                else
                {
                  //logger.info("Old file - skipping:" + ((now - updateDateTime) / 1000));
                  if(logger.isInfoEnabled())
                  logger.info("Old file - skipping:" + ((now - updateDateTime) / 1000));
                }
            }
              else
              {
                //logger.info("getting file:" + file);
                if(cacheName.equals("pageCache") && compressPageCache != null && compressPageCache.equals("true"))
                {
                  byte[] cachedCompressedData = FileHelper.getFileBytes(file);
                   if(cachedCompressedData != null && cachedCompressedData.length > 0)
                     contents = compressionHelper.decompress(cachedCompressedData);
                }
                else
                {
                  //logger.info("getting file anyway:" + updateInterval);
                  contents = FileHelper.getFileAsStringOpt(file, charEncoding);
                }
                //contents = FileHelper.getFileAsString(file, charEncoding);
              }
            }
            else
            {
              if(logger.isInfoEnabled())
              logger.info("No filecache existed:" + filePath);
            }
      }
      catch (Exception e)
      {
        logger.warn("Problem loading data from file:" + e.getMessage());
      }
     
      return contents;
    }
   
    private static void putCachedContentInFile(String cacheName, String key, String value, String fileCacheCharEncoding)
    {
      try
      {
        String firstPart = ("" + key.hashCode()).substring(0, 3);
            String dir = CmsPropertyHandler.getDigitalAssetPath() + File.separator + "caches" + File.separator + cacheName + File.separator + firstPart;
            File dirFile = new File(dir);
            dirFile.mkdirs();
            File file = new File(dir + File.separator + key.hashCode());
            File tmpOutputFile = new File(dir + File.separator + Thread.currentThread().getId() + "_tmp_" + key.hashCode());

        FileHelper.write(tmpOutputFile, value, false, fileCacheCharEncoding);
     
        if(logger.isInfoEnabled())
          logger.info("Wrote file..");
            if(tmpOutputFile.exists())
      {
        if(tmpOutputFile.length() == 0)
        {
          tmpOutputFile.delete();
        }
        else
        {
          if(logger.isInfoEnabled())
              logger.info("Renaming file " + tmpOutputFile.getAbsolutePath() + " to " + file.getAbsolutePath());
          if(logger.isInfoEnabled())
              logger.info("file:" + file.exists() + ":" + file.length());
          if(file.exists())
            file.delete();
          boolean renamed = tmpOutputFile.renameTo(file);
          if(logger.isInfoEnabled())
              logger.info("renamed:" + renamed);
          if(cacheName.equals("pageCache"))
            numberOfPageCacheFiles.incrementAndGet();
       
      }
      }
      catch (Exception e)
      {
        logger.warn("Problem storing data to file:" + e.getMessage());
    }
    }

    private static void putCachedCompressedContentInFile(String cacheName, String key, byte[] value)
    {
      try
      {
        String firstPart = ("" + key.hashCode()).substring(0, 3);
            String dir = CmsPropertyHandler.getDigitalAssetPath() + File.separator + "caches" + File.separator + cacheName + File.separator + firstPart;
            File dirFile = new File(dir);
            dirFile.mkdirs();
            File file = new File(dir + File.separator + key.hashCode());
            File tmpOutputFile = new File(dir + File.separator + Thread.currentThread().getId() + "_tmp_" + key.hashCode());

        FileHelper.writeToFile(tmpOutputFile, value);
     
        if(logger.isInfoEnabled())
          logger.info("Wrote file..");
       
            if(tmpOutputFile.exists())
      {
        if(tmpOutputFile.length() == 0)
        {
          tmpOutputFile.delete();
        }
        else
        {
          if(logger.isInfoEnabled())
              logger.info("Renaming file " + tmpOutputFile.getAbsolutePath() + " to " + file.getAbsolutePath());
          if(logger.isInfoEnabled())
              logger.info("file:" + file.exists() + ":" + file.length());
          if(file.exists())
            file.delete();
          boolean renamed = tmpOutputFile.renameTo(file);
          if(logger.isInfoEnabled())
              logger.info("renamed:" + renamed);
          if(cacheName.equals("pageCache"))
            numberOfPageCacheFiles.incrementAndGet();
       
      }
      }
      catch (Exception e)
      {
        logger.warn("Problem storing data to file:" + e.getMessage());
    }
    }

    public static void clearPageCache(String key)
    {       
      clearCache("pageCache", key);
      /*
      try
      {
          String firstPart = ("" + key.hashCode()).substring(0, 3);
            String dir = CmsPropertyHandler.getDigitalAssetPath() + File.separator + "caches" + File.separator + "pageCache" + File.separator + firstPart;
            File dirFile = new File(dir);
            dirFile.mkdirs();
            File file = new File(dir + File.separator + key.hashCode());
            if(logger.isInfoEnabled())
              logger.info("Deleting " + file.getPath() + ":" + file.exists());
            if(file.exists())
            {
              boolean deleted = file.delete();
              if(logger.isInfoEnabled())
                logger.info("Deleted: " + deleted);
            }
      }
      catch (Exception e)
      {
        logger.warn("Problem storing data to file:" + e.getMessage());
    }
    */
    }
   
    private static void removeCachedContentInFile(String cacheName, String key)
    {
      try
      {
        String firstPart = ("" + key).substring(0, 3);
            String dir = CmsPropertyHandler.getDigitalAssetPath() + File.separator + "caches" + File.separator + cacheName + File.separator + firstPart;
            File dirFile = new File(dir);
            dirFile.mkdirs();
            File file = new File(dir + File.separator + key);
            logger.info("Deleting " + file.getPath());
            file.delete();
      }
      catch (Exception e)
      {
        logger.warn("Problem storing data to file:" + e.getMessage());
    }
    }

  public static void clearFileCaches()
  {
    String dir = CmsPropertyHandler.getDigitalAssetPath() + File.separator + "caches";
        File dirFile = new File(dir);
        File dirOldFile = new File(dir+"CAN_BE_REMOVED");
        if(dirFile.exists())
          dirFile.renameTo(dirOldFile);
       
        new Thread(new Runnable() { public void run() {try {CacheController.clearFileCachesImpl(new File(CmsPropertyHandler.getDigitalAssetPath() + File.separator + "caches_CAN_BE_REMOVED"));} catch (Exception e) {}}}).start();
  }
 
  public static void clearFileCachesImpl(File dirFile)
  {
        //System.out.println("dirFile:" + dirFile.exists());
        if(dirFile.exists())
        {
            File[] subCaches = dirFile.listFiles();
            for(int i=0; i<subCaches.length; i++)
            {
              File subCacheDir = subCaches[i];
              //System.out.println("subCacheDir:" + subCacheDir.getName());
              if(subCacheDir.isDirectory())
              {
                  File[] subSubCacheFiles = subCacheDir.listFiles();
                  for(int j=0; j<subSubCacheFiles.length; j++)
                  {
                    File subSubCacheDir = subSubCacheFiles[j];
                      if(subSubCacheDir.isDirectory())
                      {
                          File[] cacheFiles = subSubCacheDir.listFiles();
                          for(int k=0; k<cacheFiles.length; k++)
                          {
                            File cacheFile = cacheFiles[k];
                            //System.out.println("cacheFile:" + cacheFile.getName());
                          cacheFile.delete();
                          }

                        subCacheDir.delete();
                      }                     

                    //System.out.println("cacheFile:" + cacheFile.getName());
                      subSubCacheDir.delete();
                  }

                subCacheDir.delete();
               }                     
            }
        }
  }

  public static void clearFileCaches(String cacheName)
  {
    CacheController.clearFileCachesImpl(cacheName);
        //new Thread(new Runnable() { public void run() {try {CacheController.clearFileCachesImpl(cacheName);} catch (Exception e) {}}}).start();
  }
 
  public static void clearFileCachesImpl(String cacheName)
  {
        String dir = CmsPropertyHandler.getDigitalAssetPath() + File.separator + "caches";
        File dirFile = new File(dir);
        //System.out.println("dirFile:" + dirFile.exists());
        if(dirFile.exists())
        {
            File[] subCaches = dirFile.listFiles();
            for(int i=0; i<subCaches.length; i++)
            {
              File subCacheDir = subCaches[i];
              //System.out.println("subCacheDir:" + subCacheDir.getName());
              if(subCacheDir.isDirectory() && subCacheDir.getName().equals(cacheName) || (cacheName.equals("pageCache") && subCacheDir.getName().startsWith(cacheName)))
              {
                try
                {
                    File[] subSubCacheFiles = subCacheDir.listFiles();
                    for(int j=0; j<subSubCacheFiles.length; j++)
                    {
                      File subSubCacheDir = subSubCacheFiles[j];
                        if(subSubCacheDir.isDirectory())
                        {
                            File[] cacheFiles = subSubCacheDir.listFiles();
                            if(cacheFiles != null)
                            {
                              for(int k=0; k<cacheFiles.length; k++)
                              {
                                File cacheFile = cacheFiles[k];
                                //System.out.println("cacheFile:" + cacheFile.getName());
                              cacheFile.delete();
                              }
                            }
                           
                          subCacheDir.delete();
                        }                     
 
                      //System.out.println("cacheFile:" + cacheFile.getName());
                        subSubCacheDir.delete();
                    }
                  subCacheDir.delete();

                }
                catch (Exception e)
                {
                  logger.warn("It seems the cache dir: " + cacheName + " was allready empty or removed. Error: " + e.getMessage());
          }
              }
            }
        }
  }

  /**
   * Rollbacks a transaction on the named database
   */
     /*
  public static void closeTransaction(Database db) throws SystemException
  {
      //if(db != null && !db.isClosed() && db.isActive())
          commitTransaction(db);
  }
*/
   
  /**
   * Begins a transaction on the named database
   */
        
  public static void beginTransaction(Database db) throws SystemException
  {
    try
    {
      db.begin();
    }
    catch(Exception e)
    {
      logger.error("An error occurred when we tried to begin an transaction. Reason:" + e.getMessage());
      throw new SystemException("An error occurred when we tried to begin an transaction. Reason:" + e.getMessage(), e);   
    }
  }

  /**
   * Ends a transaction on the named database
   */
 
    static void commitTransaction(Database db) throws SystemException
  {
    try
    {
        if (db.isActive())
        {
          db.commit();
      }
    }
    catch(Exception e)
    {
      logger.error("An error occurred when we tried to commit an transaction. Reason:" + e.getMessage());
      throw new SystemException("An error occurred when we tried to commit an transaction. Reason:" + e.getMessage(), e);   
    }
  }

  /**
   * Rollbacks a transaction on the named database
   */
   
  public static void rollbackTransaction(Database db)
  {
    try
    {
      if (db.isActive())
      {
          db.rollback();
      }
    }
    catch(Exception e)
    {
      logger.error("An error occurred when we tried to rollback an transaction. Reason:" + e.getMessage());
    }
  }

  /**
   * Close the database
   */
    
  public static void closeDatabase(Database db)
  {
    try
    {
      db.close();
    }
    catch(Exception e)
    {
      logger.error("An error occurred when we tried to close a database. Reason:" + e.getMessage(), e);   
    }
  }

  public static int getPropertyAsStringHashCode(String inheritedPageComponentsXML, Integer componentId, String propertyName, Integer siteNodeId, Integer languageId) throws Exception
  {
    Map property = null;
   
        XmlInfosetBuilder builder = XmlInfosetBuilder.newInstance();
        XmlDocument doc = builder.parseReader(new StringReader( inheritedPageComponentsXML ) );
       
    String propertyXPath = "//component[@id=" + componentId + "]/properties/property[@name='" + propertyName + "']";
   
    Xb1XPath xpathObject = new Xb1XPath( propertyXPath );

        List anl = xpathObject.selectNodes( doc );

    //If not found on the same component id - let's check them all and use the first we find.
    if(anl == null || anl.size() == 0)
    {
      String globalPropertyXPath = "(//component/properties/property[@name='" + propertyName + "'])[1]";
     
      Xb1XPath globalXpathObject = new Xb1XPath( globalPropertyXPath );
          anl = globalXpathObject.selectNodes( doc );
    }     

    StringBuilder sb = new StringBuilder();
   
    Iterator anlIterator = anl.iterator();
    while(anlIterator.hasNext())
    {
      XmlElement infosetItem = (XmlElement)anlIterator.next();
      String propertyXML = builder.serializeToString(infosetItem);
      //System.out.println("propertyXML:" + propertyXML);
     
      sb.append(propertyXML);
    }
    //System.out.println("propertyXML HASH:" + sb.toString().hashCode());
   
    return sb.toString().hashCode();
  }
 
  public static int getComponentsAsStringHashCode(String inheritedPageComponentsXML, String componentXPath) throws Exception
  {
        XmlInfosetBuilder builder = XmlInfosetBuilder.newInstance();
        XmlDocument doc = builder.parseReader(new StringReader( inheritedPageComponentsXML ) );

    Xb1XPath xpathObject = new Xb1XPath( componentXPath );

        //This keeps track of the cached inherited components.
        StringBuilder sb = new StringBuilder();
       
        List componentNodeList = xpathObject.selectNodes( doc.getDocumentElement() );
    Iterator componentNodeListIterator = componentNodeList.iterator();
    while(componentNodeListIterator.hasNext())
    {
      XmlElement child   = (XmlElement)componentNodeListIterator.next();
     
      String componentString = builder.serializeToString(child).trim();
      sb.append(componentString);
      //System.out.println("componentString:" + componentString);
     
    }
    //System.out.println("propertyXML HASH:" + sb.toString().hashCode());
   
    return sb.toString().hashCode();
  }
 
    public static Map getEventListeners()
    {
        return eventListeners;
    }


}
TOP

Related Classes of org.infoglue.deliver.util.CacheController

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.