Author: rwatler
Date: Wed Mar 3 19:34:46 2010
New Revision: 918656
URL: http://svn.apache.org/viewvc?rev=918656&view=rev
Log:
Scoped Fragment Property Cache Refactoring
-----------------------------------------------------
- add DBPM cache of user/principal specific scoped fragment properties.
- merge principal and global scoped fragment properties on DBPM access.
- revise DBPM cache notifications to minimize clustered PSML and properties
cache notifications.
- upgrade ehcache to 1.7.2 to ensure removeQuiet() operations are not
replicated in clustered environment.
- extend cache test cases to include tests of new scoped fragment properties
cache operation.
Added:
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManagerCachedFragmentPropertyList.java
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManagerFragmentKeyCacheObject.java
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManagerPrincipalKeyCacheObject.java
Modified:
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/FragmentPropertyList.java
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManager.java
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManagerCache.java
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManagerCacheObject.java
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/TransactionedOperation.java
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/java/org/apache/jetspeed/page/cache/DatabasePageManagerServer.java
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/java/org/apache/jetspeed/page/cache/TestDatabasePageManagerCache.java
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/resources/database-page-manager-base.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/resources/database-page-manager.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/resources/distributed-ehcache.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/resources/ehcache.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/resources/log4j-stdout.properties
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/resources/log4j.properties
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/resources/secure-database-page-manager.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/resources/secure-permissions-database-page-manager.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-portal-site/src/test/resources/cache-test.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/assembly/cache-test.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-profiler/src/test/resources/cache-test.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/test/resources/cache-test.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-security/src/test/resources/cache-test.xml
portals/jetspeed-2/portal/trunk/components/jetspeed-sso/src/test/resources/cache-test.xml
portals/jetspeed-2/portal/trunk/etc/import/assembly/import-page-manager.xml
portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/cache.xml
portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/page-manager.xml
portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/db-ojb/distributed-ehcache.xml
portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/db-ojb/ehcache.xml
Modified:
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/FragmentPropertyList.java
URL:
http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/FragmentPropertyList.java?rev=918656&r1=918655&r2=918656&view=diff
==============================================================================
---
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/FragmentPropertyList.java
(original)
+++
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/FragmentPropertyList.java
Wed Mar 3 19:34:46 2010
@@ -182,6 +182,18 @@
}
return null;
}
+
+ /**
+ * Clear all transient properties.
+ */
+ public synchronized void clearProperties()
+ {
+ properties.clear();
+ if (removedProperties != null)
+ {
+ removedProperties.clear();
+ }
+ }
/**
* Recycle removed property.
Modified:
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManager.java
URL:
http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManager.java?rev=918656&r1=918655&r2=918656&view=diff
==============================================================================
---
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManager.java
(original)
+++
portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/impl/DatabasePageManager.java
Wed Mar 3 19:34:46 2010
@@ -18,6 +18,7 @@
import java.security.AccessController;
import java.security.Principal;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -117,6 +118,9 @@
import org.apache.ojb.broker.query.QueryByCriteria;
import org.apache.ojb.broker.query.QueryFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* DatabasePageManager
*
@@ -126,6 +130,8 @@
*/
public class DatabasePageManager extends InitablePersistenceBrokerDaoSupport
implements PageManager
{
+ private static Logger log =
LoggerFactory.getLogger(DatabasePageManager.class);
+
private static ThreadLocal fragmentPropertyListsCache = new ThreadLocal();
private static Map modelClasses = new HashMap();
@@ -166,11 +172,12 @@
private PageManager pageManagerProxy;
- public DatabasePageManager(String repositoryPath, IdGenerator generator,
boolean isPermissionsSecurity, boolean isConstraintsSecurity, JetspeedCache
oidCache, JetspeedCache pathCache, JetspeedCache propertiesCache, JetspeedCache
propertiesPathCache)
+ public DatabasePageManager(String repositoryPath, IdGenerator generator,
boolean isPermissionsSecurity, boolean isConstraintsSecurity, JetspeedCache
oidCache, JetspeedCache pathCache,
+ JetspeedCache propertiesCache, JetspeedCache
propertiesPathCache, JetspeedCache principalPropertiesCache, JetspeedCache
principalPropertiesPathCache)
{
super(repositoryPath);
delegator = new DelegatingPageManager(generator,
isPermissionsSecurity, isConstraintsSecurity, modelClasses);
- DatabasePageManagerCache.cacheInit(oidCache, pathCache,
propertiesCache, propertiesPathCache, this);
+ DatabasePageManagerCache.cacheInit(oidCache, pathCache,
propertiesCache, propertiesPathCache, principalPropertiesCache,
principalPropertiesPathCache, this);
}
/**
@@ -2561,11 +2568,11 @@
if (pages.length > 0 && pages[0].getPath().equals("/tx__test1.psml"))
{
// for tx testing
- System.out.println("Adding first page");
+ log.debug("Adding first page");
this.updatePage(pages[0]);
- System.out.println("Adding second page");
+ log.debug("Adding second page");
this.updatePage(pages[1]);
- System.out.println("About to throw ex");
+ log.debug("About to throw ex");
throw new NodeException("Its gonna blow captain!");
}
for (int ix = 0; ix < pages.length; ix++)
@@ -2663,41 +2670,32 @@
public FragmentPropertyList
getFragmentPropertyList(BaseFragmentElementImpl baseFragmentElementImpl,
FragmentPropertyList transientList)
{
// access thread local fragment property lists cache
- String cacheKey =
getFragmentPropertyListCacheKey(baseFragmentElementImpl);
+ String fragmentKey =
getFragmentPropertyListFragmentKey(baseFragmentElementImpl);
+ Subject subject = JSSubject.getSubject(AccessController.getContext());
+ Principal userPrincipal = ((subject != null) ?
SubjectHelper.getBestPrincipal(subject, User.class) : null);
+ String fragmentListKey = getFragmentPropertyListKey(fragmentKey,
userPrincipal);
Map threadLocalCache = (Map)fragmentPropertyListsCache.get();
+ FragmentPropertyList list = ((threadLocalCache != null) ?
(FragmentPropertyList)threadLocalCache.get(fragmentListKey) : null);
- // get cached persistent list
- FragmentPropertyList list = ((threadLocalCache != null) ?
(FragmentPropertyList)threadLocalCache.get(cacheKey) : null);
+ // get and cache persistent list
if (list == null)
{
- // lookup fragment property list in cache
- list =
DatabasePageManagerCache.fragmentPropertyListCacheLookup(cacheKey);
-
- // save fragment property list in thread local cache
- if (list != null)
+ // get cached fragment property list components or
+ // query from database if not cached and cache
+ DatabasePageManagerCachedFragmentPropertyList
globalFragmentPropertyList =
DatabasePageManagerCache.fragmentPropertyListCacheLookup(fragmentKey);
+ if (globalFragmentPropertyList == null)
{
- if (threadLocalCache == null)
- {
- threadLocalCache = new HashMap();
- fragmentPropertyListsCache.set(threadLocalCache);
- }
- threadLocalCache.put(cacheKey, list);
+ globalFragmentPropertyList = new
DatabasePageManagerCachedFragmentPropertyList(baseFragmentElementImpl.getBaseFragmentsElement().getPath());
+ Criteria filter = new Criteria();
+ filter.addEqualTo("fragment", new
Integer(baseFragmentElementImpl.getIdentity()));
+ filter.addIsNull("scope");
+ QueryByCriteria query =
QueryFactory.newQuery(FragmentPropertyImpl.class, filter);
+ Collection fragmentProperties =
getPersistenceBrokerTemplate().getCollectionByQuery(query);
+ globalFragmentPropertyList.addAll(fragmentProperties);
+
DatabasePageManagerCache.fragmentPropertyListCacheAdd(fragmentKey,
globalFragmentPropertyList, false);
}
- }
- if (list == null)
- {
- // use transient list or create new fragment property list
- list = ((transientList != null) ? transientList : new
FragmentPropertyList(baseFragmentElementImpl));
-
- // build fragment properties database query
- Criteria filter = new Criteria();
- filter.addEqualTo("fragment", new
Integer(baseFragmentElementImpl.getIdentity()));
- Criteria scopesFilter = new Criteria();
- Criteria globalScopeFilter = new Criteria();
- globalScopeFilter.addIsNull("scope");
- scopesFilter.addOrCriteria(globalScopeFilter);
- // add scopes for current user, groups, and roles
- Subject subject =
JSSubject.getSubject(AccessController.getContext());
+ Map principalFragmentPropertyLists = null;
+ DatabasePageManagerCachedFragmentPropertyList
userFragmentPropertyList = null;
if (subject != null)
{
if (GROUP_AND_ROLE_PROPERTY_SCOPES_ENABLED)
@@ -2707,61 +2705,116 @@
while (principalsIter.hasNext())
{
Principal principal = (Principal)principalsIter.next();
+ String principalScope = null;
if (principal instanceof User)
{
- Criteria userScopeFilter = new Criteria();
- userScopeFilter.addEqualTo("scope",
USER_PROPERTY_SCOPE);
- userScopeFilter.addEqualTo("scopeValue",
principal.getName());
- scopesFilter.addOrCriteria(userScopeFilter);
+ principalScope = USER_PROPERTY_SCOPE;
}
else if (principal instanceof Group)
{
- Criteria groupScopeFilter = new Criteria();
- groupScopeFilter.addEqualTo("scope",
GROUP_PROPERTY_SCOPE);
- groupScopeFilter.addEqualTo("scopeValue",
principal.getName());
- scopesFilter.addOrCriteria(groupScopeFilter);
+ principalScope = GROUP_PROPERTY_SCOPE;
}
else if (principal instanceof Role)
{
- Criteria roleScopeFilter = new Criteria();
- roleScopeFilter.addEqualTo("scope",
ROLE_PROPERTY_SCOPE);
- roleScopeFilter.addEqualTo("scopeValue",
principal.getName());
- scopesFilter.addOrCriteria(roleScopeFilter);
+ principalScope = ROLE_PROPERTY_SCOPE;
+ }
+ if (principalScope != null)
+ {
+ String principalKey =
getFragmentPropertyListPrincipalKey(principalScope, principal.getName());
+ DatabasePageManagerCachedFragmentPropertyList
principalFragmentPropertyList =
DatabasePageManagerCache.principalFragmentPropertyListCacheLookup(principalKey);
+ if (principalFragmentPropertyList == null)
+ {
+ principalFragmentPropertyList = new
DatabasePageManagerCachedFragmentPropertyList(principalScope, principalKey);
+ Criteria filter = new Criteria();
+ filter.addEqualTo("scope", principalScope);
+ filter.addEqualTo("scopeValue",
principal.getName());
+ QueryByCriteria query =
QueryFactory.newQuery(FragmentPropertyImpl.class, filter);
+ Collection fragmentProperties =
getPersistenceBrokerTemplate().getCollectionByQuery(query);
+
principalFragmentPropertyList.addAll(fragmentProperties);
+
DatabasePageManagerCache.principalFragmentPropertyListCacheAdd(principalKey,
principalFragmentPropertyList, false);
+ }
+ if (principalFragmentPropertyList != null)
+ {
+ if (principalFragmentPropertyLists == null)
+ {
+ principalFragmentPropertyLists = new
HashMap();
+ }
+
principalFragmentPropertyLists.put(principalKey, principalFragmentPropertyList);
+ }
}
}
}
- else
+ else if (userPrincipal != null)
{
- Principal userPrincipal =
SubjectHelper.getBestPrincipal(subject, User.class);
- if (userPrincipal != null)
+ String principalKey =
getFragmentPropertyListPrincipalKey(USER_PROPERTY_SCOPE,
userPrincipal.getName());
+ userFragmentPropertyList =
DatabasePageManagerCache.principalFragmentPropertyListCacheLookup(principalKey);
+ if (userFragmentPropertyList == null)
{
- Criteria userScopeFilter = new Criteria();
- userScopeFilter.addEqualTo("scope",
USER_PROPERTY_SCOPE);
- userScopeFilter.addEqualTo("scopeValue",
userPrincipal.getName());
- scopesFilter.addOrCriteria(userScopeFilter);
+ userFragmentPropertyList = new
DatabasePageManagerCachedFragmentPropertyList(USER_PROPERTY_SCOPE,
principalKey);
+ Criteria filter = new Criteria();
+ filter.addEqualTo("scope", USER_PROPERTY_SCOPE);
+ filter.addEqualTo("scopeValue",
userPrincipal.getName());
+ QueryByCriteria query =
QueryFactory.newQuery(FragmentPropertyImpl.class, filter);
+ Collection fragmentProperties =
getPersistenceBrokerTemplate().getCollectionByQuery(query);
+ userFragmentPropertyList.addAll(fragmentProperties);
+
DatabasePageManagerCache.principalFragmentPropertyListCacheAdd(principalKey,
userFragmentPropertyList, false);
}
}
}
- filter.addAndCriteria(scopesFilter);
- // query for fragment properties for list using database query
- QueryByCriteria query =
QueryFactory.newQuery(FragmentPropertyImpl.class, filter);
- Collection fragmentProperties =
getPersistenceBrokerTemplate().getCollectionByQuery(query);
- list.getProperties().addAll(fragmentProperties);
-
- // save fragment property list in thread local cache
- if (threadLocalCache == null)
+
+ // assemble fragment property list instance, (use transient
+ // list or create new fragment property list)
+ list = new FragmentPropertyList(baseFragmentElementImpl);
+ list.getProperties().addAll(globalFragmentPropertyList);
+ if (subject != null)
{
- threadLocalCache = new HashMap();
- fragmentPropertyListsCache.set(threadLocalCache);
+ if (GROUP_AND_ROLE_PROPERTY_SCOPES_ENABLED)
+ {
+ if (principalFragmentPropertyLists != null)
+ {
+ Set principals = subject.getPrincipals();
+ Iterator principalsIter = principals.iterator();
+ while (principalsIter.hasNext())
+ {
+ Principal principal =
(Principal)principalsIter.next();
+ String principalScope = null;
+ if (principal instanceof User)
+ {
+ principalScope = USER_PROPERTY_SCOPE;
+ }
+ else if (principal instanceof Group)
+ {
+ principalScope = GROUP_PROPERTY_SCOPE;
+ }
+ else if (principal instanceof Role)
+ {
+ principalScope = ROLE_PROPERTY_SCOPE;
+ }
+ if (principalScope != null)
+ {
+ String principalKey =
getFragmentPropertyListPrincipalKey(principalScope, principal.getName());
+ DatabasePageManagerCachedFragmentPropertyList
principalFragmentPropertyList =
(DatabasePageManagerCachedFragmentPropertyList)principalFragmentPropertyLists.get(principalKey);
+ List principalFragmentProperties =
filterPrincipalFragmentPropertyList(principalFragmentPropertyList,
baseFragmentElementImpl);
+ if (principalFragmentProperties != null)
+ {
+
list.getProperties().addAll(principalFragmentProperties);
+ }
+ }
+ }
+ }
+ }
+ else if (userFragmentPropertyList != null)
+ {
+ List userFragmentProperties =
filterPrincipalFragmentPropertyList(userFragmentPropertyList,
baseFragmentElementImpl);
+ if (userFragmentProperties != null)
+ {
+ list.getProperties().addAll(userFragmentProperties);
+ }
+ }
}
- threadLocalCache.put(cacheKey, list);
- // save fragment property list in cache
- DatabasePageManagerCache.fragmentPropertyListCacheAdd(cacheKey,
list, false, false);
- }
- else if (transientList != null)
- {
- synchronized (list)
+ // merge results into transient list if specified
+ if ((list != null) && (transientList != null))
{
synchronized (transientList)
{
@@ -2786,14 +2839,17 @@
}
// clear transient list
- transientList.getProperties().clear();
- List removedProperties =
transientList.getRemovedProperties();
- if (removedProperties != null)
- {
- removedProperties.clear();
- }
+ transientList.clearProperties();
}
}
+
+ // save fragment property list in thread local cache
+ if (threadLocalCache == null)
+ {
+ threadLocalCache = new HashMap();
+ fragmentPropertyListsCache.set(threadLocalCache);
+ }
+ threadLocalCache.put(fragmentListKey, list);
}
return list;
}
@@ -2811,35 +2867,141 @@
FragmentPropertyList list =
getFragmentPropertyList(baseFragmentElementImpl, transientList);
if (list != null)
{
+ // get subject
+ Subject subject =
JSSubject.getSubject(AccessController.getContext());
+ Principal userPrincipal = ((subject != null) ?
SubjectHelper.getBestPrincipal(subject, User.class) : null);
+ String userPrincipalKey = ((userPrincipal != null) ?
getFragmentPropertyListPrincipalKey(USER_PROPERTY_SCOPE,
userPrincipal.getName()) : null);
+
// update fragment properties in list in database
boolean updateAllScopes = ((scope != null) &&
scope.equals(ALL_PROPERTY_SCOPE));
synchronized (list)
{
- // store property objects for add/update
- boolean update = false;
- boolean sharedUpdate = false;
- Iterator propertiesIter = list.getProperties().iterator();
+ // store property objects for add/update and decompose
+ // update into cache updates, (assumes scoped property
+ // extents are fully represented in list).
+ boolean updateTransaction = false;
+ DatabasePageManagerCachedFragmentPropertyList
globalFragmentPropertyList = null;
+ Map principalPartialFragmentPropertyLists = null;
+ String fragmentKey =
getFragmentPropertyListFragmentKey(baseFragmentElementImpl);
+ List properties = list.getProperties();
+ List removedProperties = list.getRemovedProperties();
+
+ // construct scoped properties lists for cache updates from
+ // all properties, (add, update, and remove)
+ List allProperties = new ArrayList(properties);
+ if (removedProperties != null)
+ {
+ allProperties.addAll(removedProperties);
+ }
+ Iterator allPropertiesIter = allProperties.iterator();
+ while (allPropertiesIter.hasNext())
+ {
+ FragmentPropertyImpl property =
(FragmentPropertyImpl)allPropertiesIter.next();
+ property.setFragment(baseFragmentElementImpl);
+ String propertyScope = property.getScope();
+ String propertyScopeValue = property.getScopeValue();
+ if (updateAllScopes || ((scope == null) && (propertyScope
== null)) || ((scope != null) && scope.equals(propertyScope)))
+ {
+ // classify property by scopes and create scoped lists
+ if (propertyScope == null)
+ {
+ if (globalFragmentPropertyList == null)
+ {
+ globalFragmentPropertyList = new
DatabasePageManagerCachedFragmentPropertyList(baseFragmentElementImpl.getBaseFragmentsElement().getPath());
+ }
+ }
+ else if ((subject != null) &&
GROUP_AND_ROLE_PROPERTY_SCOPES_ENABLED)
+ {
+ boolean subjectHasPrincipal = false;
+ if (propertyScope.equals(USER_PROPERTY_SCOPE))
+ {
+ subjectHasPrincipal = ((userPrincipal != null)
&& userPrincipal.getName().equals(propertyScopeValue));
+ }
+ else if
(propertyScope.equals(GROUP_PROPERTY_SCOPE))
+ {
+ subjectHasPrincipal =
(SubjectHelper.getPrincipal(subject, Group.class, propertyScopeValue) != null);
+ }
+ else if (propertyScope.equals(ROLE_PROPERTY_SCOPE))
+ {
+ subjectHasPrincipal =
(SubjectHelper.getPrincipal(subject, Role.class, propertyScopeValue) != null);
+ }
+ if (subjectHasPrincipal)
+ {
+ if (principalPartialFragmentPropertyLists ==
null)
+ {
+ principalPartialFragmentPropertyLists =
new HashMap();
+ }
+ String principalKey =
getFragmentPropertyListPrincipalKey(propertyScope, propertyScopeValue);
+ DatabasePageManagerCachedFragmentPropertyList
principalPartialFragmentPropertyList =
(DatabasePageManagerCachedFragmentPropertyList)principalPartialFragmentPropertyLists.get(principalKey);
+ if (principalPartialFragmentPropertyList ==
null)
+ {
+ principalPartialFragmentPropertyList = new
DatabasePageManagerCachedFragmentPropertyList(propertyScope, principalKey);
+
principalPartialFragmentPropertyLists.put(principalKey,
principalPartialFragmentPropertyList);
+ }
+ }
+ }
+ else if ((subject != null) &&
propertyScope.equals(USER_PROPERTY_SCOPE))
+ {
+ if ((userPrincipal != null) &&
userPrincipal.getName().equals(propertyScopeValue))
+ {
+ if (principalPartialFragmentPropertyLists ==
null)
+ {
+ principalPartialFragmentPropertyLists =
new HashMap();
+ }
+ DatabasePageManagerCachedFragmentPropertyList
principalPartialFragmentPropertyList =
(DatabasePageManagerCachedFragmentPropertyList)principalPartialFragmentPropertyLists.get(userPrincipalKey);
+ if (principalPartialFragmentPropertyList ==
null)
+ {
+ principalPartialFragmentPropertyList = new
DatabasePageManagerCachedFragmentPropertyList(USER_PROPERTY_SCOPE,
userPrincipalKey);
+
principalPartialFragmentPropertyLists.put(userPrincipalKey,
principalPartialFragmentPropertyList);
+ }
+ }
+ }
+ }
+ }
+
+ // populate properties lists for cache updates and
+ // update persistent properties
+ Iterator propertiesIter = properties.iterator();
while (propertiesIter.hasNext())
{
FragmentPropertyImpl storeProperty =
(FragmentPropertyImpl)propertiesIter.next();
- storeProperty.setFragment(baseFragmentElementImpl);
String storePropertyScope = storeProperty.getScope();
+ String storePropertyScopeValue =
storeProperty.getScopeValue();
if (updateAllScopes || ((scope == null) &&
(storePropertyScope == null)) || ((scope != null) &&
scope.equals(storePropertyScope)))
{
- // track operation type
- if (storeProperty.getIdentity() != 0)
+ // classify and decompose update into individual
caches:
+ // allow update only if scoped properties list created
above
+ // exists since the subject matching rules are checked
there
+ updateTransaction = (updateTransaction ||
(storeProperty.getIdentity() != 0));
+ boolean store = false;
+ if (storePropertyScope == null)
+ {
+ if (globalFragmentPropertyList != null)
+ {
+ globalFragmentPropertyList.add(storeProperty);
+ store = true;
+ }
+ }
+ else if (subject != null)
{
- update = true;
+ if (principalPartialFragmentPropertyLists != null)
+ {
+ String principalKey =
getFragmentPropertyListPrincipalKey(storePropertyScope,
storePropertyScopeValue);
+ DatabasePageManagerCachedFragmentPropertyList
principalPartialFragmentPropertyList =
(DatabasePageManagerCachedFragmentPropertyList)principalPartialFragmentPropertyLists.get(principalKey);
+ if (principalPartialFragmentPropertyList !=
null)
+ {
+
principalPartialFragmentPropertyList.add(storeProperty);
+ store = true;
+ }
+ }
}
- if ((storePropertyScope == null) ||
!storePropertyScope.equals(USER_PROPERTY_SCOPE))
+ // store persistent property object
+ if (store)
{
- sharedUpdate = true;
+
getPersistenceBrokerTemplate().store(storeProperty);
}
- // store property object
- getPersistenceBrokerTemplate().store(storeProperty);
}
}
- List removedProperties = list.getRemovedProperties();
if (removedProperties != null)
{
Iterator removedPropertiesIter =
removedProperties.iterator();
@@ -2848,25 +3010,66 @@
FragmentPropertyImpl deleteProperty =
(FragmentPropertyImpl)removedPropertiesIter.next();
deleteProperty.setFragment(baseFragmentElementImpl);
String deletePropertyScope = deleteProperty.getScope();
+ String deletePropertyScopeValue =
deleteProperty.getScopeValue();
if (updateAllScopes || ((scope == null) &&
(deletePropertyScope == null)) || ((scope != null) &&
scope.equals(deletePropertyScope)))
{
- // track operation type
- update = true;
- if ((deletePropertyScope == null) ||
!deletePropertyScope.equals(USER_PROPERTY_SCOPE))
+ // classify and decompose delete: allow delete only
+ // if scoped properties list created above exists
+ // since the subject matching rules are checked
there
+ updateTransaction = true;
+ boolean delete = false;
+ if (deletePropertyScope == null)
{
- sharedUpdate = true;
+ delete = (globalFragmentPropertyList != null);
+ }
+ else if (subject != null)
+ {
+ if (principalPartialFragmentPropertyLists !=
null)
+ {
+ String principalKey =
getFragmentPropertyListPrincipalKey(deletePropertyScope,
deletePropertyScopeValue);
+ delete =
principalPartialFragmentPropertyLists.containsKey(principalKey);
+ }
+ }
+ // delete persistent property object
+ if (delete)
+ {
+
getPersistenceBrokerTemplate().delete(deleteProperty);
}
- // delete property object
-
getPersistenceBrokerTemplate().delete(deleteProperty);
}
}
}
// interoperate with cache to signal update operations and
// record thread transactions
- String cacheKey =
getFragmentPropertyListCacheKey(baseFragmentElementImpl);
- String transactionOperationPath =
DatabasePageManagerCache.fragmentPropertyListCacheAdd(cacheKey, list, (update
|| sharedUpdate), sharedUpdate);
- DatabasePageManagerCache.addTransaction(new
TransactionedOperation(transactionOperationPath, (update ?
TransactionedOperation.UPDATE_FRAGMENT_PROPERTIES_OPERATION :
TransactionedOperation.ADD_FRAGMENT_PROPERTIES_OPERATION)));
+ if (globalFragmentPropertyList != null)
+ {
+ // cache new global fragment property list
+
DatabasePageManagerCache.fragmentPropertyListCacheAdd(fragmentKey,
globalFragmentPropertyList, true);
+ DatabasePageManagerCache.addTransaction(new
TransactionedOperation(fragmentKey, (updateTransaction ?
TransactionedOperation.UPDATE_FRAGMENT_PROPERTIES_OPERATION :
TransactionedOperation.ADD_FRAGMENT_PROPERTIES_OPERATION)));
+ }
+ if (principalPartialFragmentPropertyLists != null)
+ {
+ // update cached principal scoped fragment property lists
+ Iterator listsIter =
principalPartialFragmentPropertyLists.entrySet().iterator();
+ while (listsIter.hasNext())
+ {
+ Map.Entry entry = (Map.Entry)listsIter.next();
+ String principalKey = (String)entry.getKey();
+ DatabasePageManagerCachedFragmentPropertyList
principalPartialFragmentPropertyList =
(DatabasePageManagerCachedFragmentPropertyList)entry.getValue();
+ // update cached principal scoped fragment property
list
+ DatabasePageManagerCachedFragmentPropertyList
cachedPrincipalFragmentPropertyList =
DatabasePageManagerCache.principalFragmentPropertyListCacheLookup(principalKey);
+ if (cachedPrincipalFragmentPropertyList != null)
+ {
+ synchronized (cachedPrincipalFragmentPropertyList)
+ {
+
removeAllPrincipalFragmentPropertyList(cachedPrincipalFragmentPropertyList,
baseFragmentElementImpl);
+
cachedPrincipalFragmentPropertyList.addAll(principalPartialFragmentPropertyList);
+ }
+
DatabasePageManagerCache.principalFragmentPropertyListCacheAdd(principalKey,
cachedPrincipalFragmentPropertyList, true);
+ }
+ DatabasePageManagerCache.addTransaction(new
TransactionedOperation(principalKey, (updateTransaction ?
TransactionedOperation.UPDATE_PRINCIPAL_FRAGMENT_PROPERTIES_OPERATION :
TransactionedOperation.ADD_PRINCIPAL_FRAGMENT_PROPERTIES_OPERATION)));
+ }
+ }
}
}
}
@@ -2880,73 +3083,125 @@
public void removeFragmentPropertyList(BaseFragmentElementImpl
baseFragmentElementImpl, FragmentPropertyList transientList)
{
// access thread local fragment property lists cache
- String cacheKey =
getFragmentPropertyListCacheKey(baseFragmentElementImpl);
+ String fragmentKey =
getFragmentPropertyListFragmentKey(baseFragmentElementImpl);
+ Subject subject = JSSubject.getSubject(AccessController.getContext());
+ Principal userPrincipal = ((subject != null) ?
SubjectHelper.getBestPrincipal(subject, User.class) : null);
+ String fragmentListKey = getFragmentPropertyListKey(fragmentKey,
userPrincipal);
Map threadLocalCache = (Map)fragmentPropertyListsCache.get();
+ FragmentPropertyList list = ((threadLocalCache != null) ?
(FragmentPropertyList)threadLocalCache.get(fragmentListKey) : null);
// remove cached persistent list
- FragmentPropertyList list = ((threadLocalCache != null) ?
(FragmentPropertyList)threadLocalCache.get(cacheKey) : null);
if (list != null)
{
// remove list from cache
- threadLocalCache.remove(cacheKey);
+ threadLocalCache.remove(fragmentKey);
// cleanup list
- synchronized (list)
- {
- list.getProperties().clear();
- List removedProperties = list.getRemovedProperties();
- if (removedProperties != null)
- {
- removedProperties.clear();
- }
- }
+ list.clearProperties();
}
-
// cleanup transient list
if (transientList != null)
{
- synchronized (transientList)
- {
- transientList.getProperties().clear();
- List removedProperties = transientList.getRemovedProperties();
- if (removedProperties != null)
- {
- removedProperties.clear();
- }
- }
+ transientList.clearProperties();
}
// remove all fragment properties in list from database
+ Integer fragmentId = new
Integer(baseFragmentElementImpl.getIdentity());
Criteria filter = new Criteria();
- filter.addEqualTo("fragment", new
Integer(baseFragmentElementImpl.getIdentity()));
+ filter.addEqualTo("fragment", fragmentId);
QueryByCriteria query =
QueryFactory.newQuery(FragmentPropertyImpl.class, filter);
getPersistenceBrokerTemplate().deleteByQuery(query);
// interoperate with cache to signal remove operations
- String path =
baseFragmentElementImpl.getBaseFragmentsElement().getPath();
- DatabasePageManagerCache.fragmentPropertyListCacheRemove(path);
+ DatabasePageManagerCache.fragmentPropertyListCacheRemove(fragmentKey);
+ DatabasePageManagerCache.addTransaction(new
TransactionedOperation(fragmentKey,
TransactionedOperation.UPDATE_FRAGMENT_PROPERTIES_OPERATION));
+ }
+
+ /**
+ * Compute thread local fragment property list key for fragment properties.
+ *
+ * @param fragmentKey fragment key
+ * @param userPrincipal current subject user principal
+ * @return fragment property list key string
+ */
+ private static String getFragmentPropertyListKey(String fragmentKey,
Principal userPrincipal)
+ {
+ if (userPrincipal != null)
+ {
+ return fragmentKey+"/"+userPrincipal.getName();
+ }
+ return fragmentKey;
}
/**
- * Compute thread local cache key for fragment properties.
+ * Compute fragment key for fragment properties.
*
* @param baseFragmentElementImpl owner of fragment properties
- * @return key string
+ * @return fragment key string
*/
- private static String
getFragmentPropertyListCacheKey(BaseFragmentElementImpl baseFragmentElementImpl)
+ private static String
getFragmentPropertyListFragmentKey(BaseFragmentElementImpl
baseFragmentElementImpl)
{
- // base key
- String key =
baseFragmentElementImpl.getBaseFragmentsElement().getPath()+"/"+baseFragmentElementImpl.getId();
- // append current user if available
- Subject subject = JSSubject.getSubject(AccessController.getContext());
- if (subject != null)
+ return
baseFragmentElementImpl.getBaseFragmentsElement().getPath()+"/"+baseFragmentElementImpl.getId()+":"+baseFragmentElementImpl.getIdentity();
+ }
+
+ /**
+ * Compute principal key for fragment properties.
+ *
+ * @param principalType principal type
+ * @param principalName principal name
+ * @return principal key string
+ */
+ private static String getFragmentPropertyListPrincipalKey(String
principalType, String principalName)
+ {
+ return principalType+":"+principalName;
+ }
+
+ /**
+ * Filter principal fragment property list.
+ *
+ * @param principalFragmentPropertyList principal fragment property list
+ * @param baseFragmentElementImpl fragment property owning fragment
+ * @return fragment property list for owning fragment
+ */
+ private static List
filterPrincipalFragmentPropertyList(DatabasePageManagerCachedFragmentPropertyList
principalFragmentPropertyList, BaseFragmentElementImpl baseFragmentElementImpl)
+ {
+ List filteredList = null;
+ synchronized (principalFragmentPropertyList)
+ {
+ for (Iterator iter = principalFragmentPropertyList.iterator();
iter.hasNext();)
+ {
+ FragmentPropertyImpl fragmentProperty =
(FragmentPropertyImpl)iter.next();
+ if
(((BaseFragmentElementImpl)fragmentProperty.getFragment()).getIdentity() ==
baseFragmentElementImpl.getIdentity())
+ {
+ if (filteredList == null)
+ {
+ filteredList = new ArrayList();
+ }
+ filteredList.add(fragmentProperty);
+ }
+ }
+ }
+ return filteredList;
+ }
+
+ /**
+ * Remove matching principal fragment properties from list.
+ *
+ * @param principalFragmentPropertyList principal fragment property list
+ * @param baseFragmentElementImpl fragment property owning fragment
+ */
+ private static void
removeAllPrincipalFragmentPropertyList(DatabasePageManagerCachedFragmentPropertyList
principalFragmentPropertyList, BaseFragmentElementImpl baseFragmentElementImpl)
+ {
+ synchronized (principalFragmentPropertyList)
{
- Principal userPrincipal = SubjectHelper.getBestPrincipal(subject,
User.class);
- if (userPrincipal != null)
+ for (Iterator iter = principalFragmentPropertyList.iterator();
iter.hasNext();)
{
- key = key+"/"+userPrincipal.getName();
+ FragmentPropertyImpl fragmentProperty =
(FragmentPropertyImpl)iter.next();
+ if
(((BaseFragmentElementImpl)fragmentProperty.getFragment()).getIdentity() ==
baseFragmentElementImpl.getIdentity())
+ {
+ iter.remove();
+ }
}
}
- return key;
}
/**
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]