diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml
index 346ba768f9..82aeb287c4 100644
--- a/config/alfresco/core-services-context.xml
+++ b/config/alfresco/core-services-context.xml
@@ -814,10 +814,7 @@
-
-
-
-
+
diff --git a/config/alfresco/ehcache-default.xml b/config/alfresco/ehcache-default.xml
index 63f4f46e1e..a5b4647338 100644
--- a/config/alfresco/ehcache-default.xml
+++ b/config/alfresco/ehcache-default.xml
@@ -379,6 +379,7 @@
+
-
-
+
-
-
-
-
-
-
> urisCache = new EhCacheAdapter>();
- urisCache.setCache(urisEhCache);
+ Cache namespaceEhCache = new Cache("namespaceCache", 50, false, true, 0L, 0L);
+ cacheManager.addCache(namespaceEhCache);
+ EhCacheAdapter namespaceCache = new EhCacheAdapter();
+ namespaceCache.setCache(namespaceEhCache);
- namespaceDAO.setUrisCache(urisCache);
-
- Cache prefixesEhCache = new Cache("prefixesCache", 50, false, true, 0L, 0L);
- cacheManager.addCache(prefixesEhCache);
- EhCacheAdapter> prefixesCache = new EhCacheAdapter>();
- prefixesCache.setCache(prefixesEhCache);
-
- namespaceDAO.setPrefixesCache(prefixesCache);
+ namespaceDAO.setNamespaceDataCache(namespaceCache);
}
diff --git a/source/java/org/alfresco/repo/dictionary/DiffModelTest.java b/source/java/org/alfresco/repo/dictionary/DiffModelTest.java
index 7babcdf93c..3bed6a386c 100755
--- a/source/java/org/alfresco/repo/dictionary/DiffModelTest.java
+++ b/source/java/org/alfresco/repo/dictionary/DiffModelTest.java
@@ -1,3 +1,27 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
package org.alfresco.repo.dictionary;
import java.io.ByteArrayInputStream;
@@ -11,7 +35,7 @@ import net.sf.ehcache.CacheManager;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.cache.EhCacheAdapter;
-import org.alfresco.repo.dictionary.M2ModelDiff;
+import org.alfresco.repo.dictionary.NamespaceDAOImpl.NamespaceData;
import org.alfresco.repo.tenant.SingleTServiceImpl;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.namespace.QName;
@@ -784,19 +808,12 @@ public class DiffModelTest extends TestCase
{
CacheManager cacheManager = new CacheManager();
- Cache urisEhCache = new Cache("urisCache", 50, false, true, 0L, 0L);
- cacheManager.addCache(urisEhCache);
- EhCacheAdapter> urisCache = new EhCacheAdapter>();
- urisCache.setCache(urisEhCache);
+ Cache namespaceEhCache = new Cache("namespaceCache", 50, false, true, 0L, 0L);
+ cacheManager.addCache(namespaceEhCache);
+ EhCacheAdapter namespaceCache = new EhCacheAdapter();
+ namespaceCache.setCache(namespaceEhCache);
- namespaceDAO.setUrisCache(urisCache);
-
- Cache prefixesEhCache = new Cache("prefixesCache", 50, false, true, 0L, 0L);
- cacheManager.addCache(prefixesEhCache);
- EhCacheAdapter> prefixesCache = new EhCacheAdapter>();
- prefixesCache.setCache(prefixesEhCache);
-
- namespaceDAO.setPrefixesCache(prefixesCache);
+ namespaceDAO.setNamespaceDataCache(namespaceCache);
}
public void testDeleteModel()
diff --git a/source/java/org/alfresco/repo/dictionary/NamespaceDAOImpl.java b/source/java/org/alfresco/repo/dictionary/NamespaceDAOImpl.java
index 16b453258b..2b327da2aa 100644
--- a/source/java/org/alfresco/repo/dictionary/NamespaceDAOImpl.java
+++ b/source/java/org/alfresco/repo/dictionary/NamespaceDAOImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -55,10 +55,13 @@ public class NamespaceDAOImpl implements NamespaceDAO
private Lock readLock = lock.readLock();
private Lock writeLock = lock.writeLock();
- // internal caches that are clusterable
- private SimpleCache> urisCache;
- private SimpleCache> prefixesCache;
-
+ // Internal cache (clusterable)
+ private SimpleCache namespaceDataCache;
+
+ // used to reset the cache
+ private ThreadLocal namespaceDataThreadLocal = new ThreadLocal();
+ private ThreadLocal defaultNamespaceDataThreadLocal = new ThreadLocal();
+
// Dependencies
private TenantService tenantService;
private DictionaryDAO dictionaryDAO;
@@ -68,37 +71,24 @@ public class NamespaceDAOImpl implements NamespaceDAO
{
this.tenantService = tenantService;
}
-
- public void setUrisCache(SimpleCache> urisCache)
- {
- this.urisCache = urisCache;
- }
- public void setPrefixesCache(SimpleCache> prefixesCache)
+ public void setNamespaceDataCache(SimpleCache namespaceDataCache)
{
- this.prefixesCache = prefixesCache;
+ this.namespaceDataCache = namespaceDataCache;
}
public void registerDictionary(DictionaryDAO dictionaryDAO)
{
this.dictionaryDAO = dictionaryDAO;
}
-
+
/**
* Initialise empty namespaces
*/
public void init()
{
- String tenantDomain = getTenantDomain();
-
- putUrisCtx(tenantDomain, new ArrayList());
- putPrefixesCtx(tenantDomain, new HashMap());
-
- if (logger.isDebugEnabled())
- {
- logger.debug("Empty namespaces initialised");
- }
+ initNamespace(getTenantDomain());
}
/**
@@ -107,9 +97,8 @@ public class NamespaceDAOImpl implements NamespaceDAO
public void destroy()
{
String tenantDomain = getTenantDomain();
-
- removeUrisCtx(tenantDomain);
- removePrefixesCtx(tenantDomain);
+
+ removeNamespaceData(tenantDomain);
if (logger.isDebugEnabled())
{
@@ -118,31 +107,90 @@ public class NamespaceDAOImpl implements NamespaceDAO
}
/**
- * Resets the namespaces (by resetting the dictionary)
+ * Resets the namespaces (by re-initialising the dictionary)
*/
- private void reset()
+ private NamespaceData reset(String tenantDomain)
{
- if (logger.isDebugEnabled())
- {
- logger.debug("Resetting namespaces ...");
- }
-
- if (dictionaryDAO == null)
- {
- // Unexpected
- throw new AlfrescoRuntimeException("Dictionary should be registered in order to perform reset");
- }
- else
- {
- dictionaryDAO.reset();
- }
-
- if (logger.isDebugEnabled())
- {
- logger.debug("... resetting namespaces completed");
- }
+ if (dictionaryDAO == null)
+ {
+ // Unexpected
+ throw new AlfrescoRuntimeException("Dictionary should be registered in order to perform reset");
+ }
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Resetting namespaces ...");
+ }
+
+ dictionaryDAO.init();
+
+ NamespaceData namespaceData = getNamespaceData(tenantDomain);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("... resetting namespaces completed");
+ }
+
+ return namespaceData;
}
-
+
+ private NamespaceData initNamespace(String tenantDomain)
+ {
+ try
+ {
+ createNamespaceLocal(tenantDomain);
+
+ NamespaceData namespaceData = initNamespaceData(tenantDomain);
+
+ if (namespaceData == null)
+ {
+ // unexpected
+ throw new AlfrescoRuntimeException("Failed to init namespaceData " + tenantDomain);
+ }
+
+ try
+ {
+ writeLock.lock();
+ namespaceDataCache.put(tenantDomain, namespaceData);
+ }
+ finally
+ {
+ writeLock.unlock();
+ }
+
+ return namespaceData;
+ }
+ finally
+ {
+ try
+ {
+ readLock.lock();
+ if (namespaceDataCache.get(tenantDomain) != null)
+ {
+ removeNamespaceLocal(tenantDomain);
+ }
+ }
+ finally
+ {
+ readLock.unlock();
+ }
+ }
+ }
+
+ private NamespaceData initNamespaceData(String tenantDomain)
+ {
+ getNamespaceData(tenantDomain).setUrisCache(new ArrayList());
+ getNamespaceData(tenantDomain).setPrefixesCache(new HashMap());
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Empty namespaces initialised");
+ }
+
+ return getNamespaceDataLocal(tenantDomain);
+ }
+
+
/* (non-Javadoc)
* @see org.alfresco.repo.ref.NamespacePrefixResolver#getURIs()
*/
@@ -175,8 +223,8 @@ public class NamespaceDAOImpl implements NamespaceDAO
return Collections.unmodifiableCollection(urisFiltered);
}
}
-
-
+
+
/* (non-Javadoc)
* @see org.alfresco.repo.ref.NamespacePrefixResolver#getPrefixes()
*/
@@ -209,7 +257,7 @@ public class NamespaceDAOImpl implements NamespaceDAO
return Collections.unmodifiableCollection(prefixesFiltered);
}
}
-
+
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.NamespaceDAO#addURI(java.lang.String)
@@ -222,7 +270,7 @@ public class NamespaceDAOImpl implements NamespaceDAO
}
getUrisCtx().add(uri);
}
-
+
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.NamespaceDAO#addPrefix(java.lang.String, java.lang.String)
@@ -235,8 +283,8 @@ public class NamespaceDAOImpl implements NamespaceDAO
}
getPrefixesCtx().put(prefix, uri);
}
-
-
+
+
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.NamespaceDAO#removeURI(java.lang.String)
*/
@@ -244,7 +292,7 @@ public class NamespaceDAOImpl implements NamespaceDAO
{
getUrisCtx().remove(uri);
}
-
+
/* (non-Javadoc)
* @see org.alfresco.repo.dictionary.impl.NamespaceDAO#removePrefix(java.lang.String)
@@ -253,8 +301,8 @@ public class NamespaceDAOImpl implements NamespaceDAO
{
getPrefixesCtx().remove(prefix);
}
-
-
+
+
/* (non-Javadoc)
* @see org.alfresco.repo.ref.NamespacePrefixResolver#getNamespaceURI(java.lang.String)
*/
@@ -280,7 +328,7 @@ public class NamespaceDAOImpl implements NamespaceDAO
}
}
}
-
+
/* (non-Javadoc)
* @see org.alfresco.repo.ref.NamespacePrefixResolver#getPrefixes(java.lang.String)
@@ -343,6 +391,120 @@ public class NamespaceDAOImpl implements NamespaceDAO
}
}
+
+ // re-entrant (eg. via reset)
+ private NamespaceData getNamespaceData(String tenantDomain)
+ {
+ NamespaceData namespaceData = null;
+ try
+ {
+ // check cache first - return if set
+ readLock.lock();
+ namespaceData = namespaceDataCache.get(tenantDomain);
+
+ if (namespaceData != null)
+ {
+ return namespaceData; // return cached config
+ }
+ }
+ finally
+ {
+ readLock.unlock();
+ }
+
+ // check threadlocal second - return if set
+ namespaceData = getNamespaceDataLocal(tenantDomain);
+ if (namespaceData != null)
+ {
+ return namespaceData; // return local namespaceData
+ }
+
+ // reset caches - may have been invalidated (e.g. in a cluster)
+ namespaceData = reset(tenantDomain);
+
+ if (namespaceData == null)
+ {
+ // unexpected
+ throw new AlfrescoRuntimeException("Failed to get namespaceData " + tenantDomain);
+ }
+
+ return namespaceData;
+ }
+
+ // create threadlocal
+ private void createNamespaceLocal(String tenantDomain)
+ {
+ // create threadlocal, if needed
+ NamespaceData namespaceData = getNamespaceDataLocal(tenantDomain);
+ if (namespaceData == null)
+ {
+ namespaceData = new NamespaceData(tenantDomain);
+
+ if (tenantDomain.equals(TenantService.DEFAULT_DOMAIN))
+ {
+ defaultNamespaceDataThreadLocal.set(namespaceData);
+ }
+ else
+ {
+ namespaceDataThreadLocal.set(namespaceData);
+ }
+ }
+ }
+
+ // get threadlocal
+ private NamespaceData getNamespaceDataLocal(String tenantDomain)
+ {
+ NamespaceData namespaceData = null;
+
+ if (tenantDomain.equals(TenantService.DEFAULT_DOMAIN))
+ {
+ namespaceData = this.defaultNamespaceDataThreadLocal.get();
+ }
+ else
+ {
+ namespaceData = this.namespaceDataThreadLocal.get();
+ }
+
+ // check to see if domain switched (eg. during login)
+ if ((namespaceData != null) && (tenantDomain.equals(namespaceData.getTenantDomain())))
+ {
+ return namespaceData; // return threadlocal, if set
+ }
+
+ return null;
+ }
+
+ // remove threadlocal
+ private void removeNamespaceLocal(String tenantDomain)
+ {
+ if (tenantDomain.equals(TenantService.DEFAULT_DOMAIN))
+ {
+ defaultNamespaceDataThreadLocal.set(null); // it's in the cache, clear the threadlocal
+ }
+ else
+ {
+ namespaceDataThreadLocal.set(null); // it's in the cache, clear the threadlocal
+ }
+ }
+
+ private void removeNamespaceData(String tenantDomain)
+ {
+ try
+ {
+ writeLock.lock();
+ if (namespaceDataCache.get(tenantDomain) != null)
+ {
+ namespaceDataCache.remove(tenantDomain);
+ }
+
+ removeNamespaceLocal(tenantDomain);
+ }
+ finally
+ {
+ writeLock.unlock();
+ }
+ }
+
/**
* Get URIs from the cache (in the context of the current user's tenant domain)
*
@@ -361,82 +523,9 @@ public class NamespaceDAOImpl implements NamespaceDAO
*/
private List getUrisCtx(String tenantDomain)
{
- List uris = null;
- try
- {
- readLock.lock();
- uris = urisCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
-
- if (uris == null)
- {
- reset(); // reset caches - may have been invalidated (e.g. in a cluster)
-
- try
- {
- readLock.lock();
- uris = urisCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (uris == null)
- {
- // unexpected
- throw new AlfrescoRuntimeException("Failed to re-initialise urisCache " + tenantDomain);
- }
- }
- return uris;
+ return getNamespaceData(tenantDomain).getUrisCache();
}
- /**
- * Put URIs into the cache
- *
- * @param tenantDomain
- * @param uris
- */
- private void putUrisCtx(String tenantDomain, List uris)
- {
- try
- {
- writeLock.lock();
- urisCache.put(tenantDomain, uris);
- }
- finally
- {
- writeLock.unlock();
- }
- }
-
- /**
- * Remove URIs from the cache
- *
- * @param tenantDomain
- */
- private void removeUrisCtx(String tenantDomain)
- {
- try
- {
- writeLock.lock();
- if (urisCache.get(tenantDomain) != null)
- {
- urisCache.get(tenantDomain).clear();
- urisCache.remove(tenantDomain);
- }
- }
- finally
- {
- writeLock.unlock();
- }
- }
-
/**
* Get prefixes from the cache
*
@@ -446,7 +535,7 @@ public class NamespaceDAOImpl implements NamespaceDAO
{
return getPrefixesCtx(getTenantDomain());
}
-
+
/**
* Get prefixes from the cache
*
@@ -455,81 +544,8 @@ public class NamespaceDAOImpl implements NamespaceDAO
*/
private Map getPrefixesCtx(String tenantDomain)
{
- Map prefixes = null;
- try
- {
- readLock.lock();
- prefixes = prefixesCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (prefixes == null)
- {
- reset(); // reset caches - may have been invalidated (e.g. in a cluster)
-
- try
- {
- readLock.lock();
- prefixes = prefixesCache.get(tenantDomain);
- }
- finally
- {
- readLock.unlock();
- }
-
- if (prefixes == null)
- {
- // unexpected
- throw new AlfrescoRuntimeException("Failed to re-initialise prefixesCache " + tenantDomain);
- }
- }
-
- return prefixes;
- }
-
- /**
- * Put prefixes into the cache
- *
- * @param tenantDomain
- * @param prefixes
- */
- private void putPrefixesCtx(String tenantDomain, Map prefixes)
- {
- try
- {
- writeLock.lock();
- prefixesCache.put(tenantDomain, prefixes);
- }
- finally
- {
- writeLock.unlock();
- }
- }
-
- /**
- * Remove prefixes from the cache
- *
- * @param tenantDomain
- */
- private void removePrefixesCtx(String tenantDomain)
- {
- try
- {
- writeLock.lock();
- if (prefixesCache.get(tenantDomain) != null)
- {
- prefixesCache.get(tenantDomain).clear();
- prefixesCache.remove(tenantDomain);
- }
- }
- finally
- {
- writeLock.unlock();
- }
- }
+ return getNamespaceData(tenantDomain).getPrefixesCache();
+ }
/**
* Local helper - returns tenant domain (or empty string if default non-tenant)
@@ -538,4 +554,42 @@ public class NamespaceDAOImpl implements NamespaceDAO
{
return tenantService.getCurrentUserDomain();
}
+
+ /* package */ class NamespaceData
+ {
+ private List urisCache;
+ private Map prefixesCache;
+
+ private String tenantDomain;
+
+ public NamespaceData(String tenantDomain)
+ {
+ this.tenantDomain = tenantDomain;
+ }
+
+ public String getTenantDomain()
+ {
+ return tenantDomain;
+ }
+
+ public List getUrisCache()
+ {
+ return urisCache;
+ }
+
+ public void setUrisCache(List urisCache)
+ {
+ this.urisCache = urisCache;
+ }
+
+ public Map getPrefixesCache()
+ {
+ return prefixesCache;
+ }
+
+ public void setPrefixesCache(Map prefixesCache)
+ {
+ this.prefixesCache = prefixesCache;
+ }
+ }
}
diff --git a/source/java/org/alfresco/repo/dictionary/TestModel.java b/source/java/org/alfresco/repo/dictionary/TestModel.java
index 689806c100..84e3ea9886 100644
--- a/source/java/org/alfresco/repo/dictionary/TestModel.java
+++ b/source/java/org/alfresco/repo/dictionary/TestModel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -32,6 +32,7 @@ import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import org.alfresco.repo.cache.EhCacheAdapter;
+import org.alfresco.repo.dictionary.NamespaceDAOImpl.NamespaceData;
import org.alfresco.repo.tenant.SingleTServiceImpl;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.namespace.QName;
@@ -132,18 +133,11 @@ public class TestModel
{
CacheManager cacheManager = new CacheManager();
- Cache urisEhCache = new Cache("urisCache", 50, false, true, 0L, 0L);
- cacheManager.addCache(urisEhCache);
- EhCacheAdapter> urisCache = new EhCacheAdapter>();
- urisCache.setCache(urisEhCache);
+ Cache namespaceEhCache = new Cache("namespaceCache", 50, false, true, 0L, 0L);
+ cacheManager.addCache(namespaceEhCache);
+ EhCacheAdapter namespaceCache = new EhCacheAdapter();
+ namespaceCache.setCache(namespaceEhCache);
- namespaceDAO.setUrisCache(urisCache);
-
- Cache prefixesEhCache = new Cache("prefixesCache", 50, false, true, 0L, 0L);
- cacheManager.addCache(prefixesEhCache);
- EhCacheAdapter> prefixesCache = new EhCacheAdapter>();
- prefixesCache.setCache(prefixesEhCache);
-
- namespaceDAO.setPrefixesCache(prefixesCache);
+ namespaceDAO.setNamespaceDataCache(namespaceCache);
}
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/policy/PolicyComponentTest.java b/source/java/org/alfresco/repo/policy/PolicyComponentTest.java
index b07059741e..95ae4dbe0a 100644
--- a/source/java/org/alfresco/repo/policy/PolicyComponentTest.java
+++ b/source/java/org/alfresco/repo/policy/PolicyComponentTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -27,13 +27,13 @@ package org.alfresco.repo.policy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
import junit.framework.TestCase;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import org.alfresco.repo.cache.EhCacheAdapter;
+import org.alfresco.repo.cache.NullCache;
import org.alfresco.repo.dictionary.DictionaryBootstrap;
import org.alfresco.repo.dictionary.DictionaryComponent;
import org.alfresco.repo.dictionary.DictionaryDAOImpl;
@@ -112,23 +112,11 @@ public class PolicyComponentTest extends TestCase
dictionaryDAO.setCompiledModelsCache(compileModelCache);
}
+ @SuppressWarnings("unchecked")
private void initNamespaceCaches(NamespaceDAOImpl namespaceDAO)
{
- CacheManager cacheManager = new CacheManager();
-
- Cache urisEhCache = new Cache("urisCache", 50, false, true, 0L, 0L);
- cacheManager.addCache(urisEhCache);
- EhCacheAdapter> urisCache = new EhCacheAdapter>();
- urisCache.setCache(urisEhCache);
-
- namespaceDAO.setUrisCache(urisCache);
-
- Cache prefixesEhCache = new Cache("prefixesCache", 50, false, true, 0L, 0L);
- cacheManager.addCache(prefixesEhCache);
- EhCacheAdapter> prefixesCache = new EhCacheAdapter>();
- prefixesCache.setCache(prefixesEhCache);
-
- namespaceDAO.setPrefixesCache(prefixesCache);
+ // note: unit tested here with null cache
+ namespaceDAO.setNamespaceDataCache(new NullCache());
}
public void testJavaBehaviour()