Author: rwatler Date: Wed Dec 23 18:02:53 2009 New Revision: 893587 URL: http://svn.apache.org/viewvc?rev=893587&view=rev Log: Scoped Fragment Properties -------------------------------------------------------------- - Initial DBPM/DBPSML implementation of scoped fragment properties with uncached DB query. - Thread based caching of scoped/extended fragment properties.
To Do: -------------------------------------------------------------- - Add shared cache of fragment properties with cluster eviction notifications. Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/BaseFragmentElementImpl.java portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/FragmentPropertyImpl.java 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/resources/JETSPEED-INF/ojb/page-manager-repository.xml portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/java/org/apache/jetspeed/page/TestDatabasePageManager.java Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/BaseFragmentElementImpl.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/BaseFragmentElementImpl.java?rev=893587&r1=893586&r2=893587&view=diff ============================================================================== --- portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/BaseFragmentElementImpl.java (original) +++ portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/BaseFragmentElementImpl.java Wed Dec 23 18:02:53 2009 @@ -27,6 +27,8 @@ import org.apache.jetspeed.om.page.PageSecurity; import org.apache.jetspeed.page.impl.DatabasePageManager; import org.apache.jetspeed.page.impl.DatabasePageManagerUtils; +import org.apache.ojb.broker.PersistenceBroker; +import org.apache.ojb.broker.PersistenceBrokerAware; /** * BaseFragmentElementImpl @@ -34,7 +36,7 @@ * @author <a href="mailto:rwat...@apache.org">Randy Watler</a> * @version $Id$ */ -public abstract class BaseFragmentElementImpl extends BaseElementImpl implements BaseFragmentElement +public abstract class BaseFragmentElementImpl extends BaseElementImpl implements BaseFragmentElement, PersistenceBrokerAware { private String ojbConcreteClass = getClass().getName(); private String fragmentId; @@ -776,20 +778,17 @@ // if fragment is not newly constructed if (getIdentity() != 0) { - fragmentProperties = null; DatabasePageManager pageManager = getPageManager(); if (pageManager != null) { - FragmentPropertyList properties = pageManager.getFragmentPropertiesList(this); - if (properties != null) - { - return properties; - } + FragmentPropertyList properties = pageManager.getFragmentPropertiesList(this, fragmentProperties); + fragmentProperties = null; + return properties; } } + // create transient properties list place holder if (fragmentProperties == null) { - // create properties list place holder fragmentProperties = new FragmentPropertyList(this); } return fragmentProperties; @@ -1066,6 +1065,79 @@ } } + /* (non-Javadoc) + * @see org.apache.ojb.broker.PersistenceBrokerAware#afterDelete(org.apache.ojb.broker.PersistenceBroker) + */ + public void afterDelete(PersistenceBroker broker) + { + } + + /* (non-Javadoc) + * @see org.apache.ojb.broker.PersistenceBrokerAware#afterInsert(org.apache.ojb.broker.PersistenceBroker) + */ + public void afterInsert(PersistenceBroker broker) + { + // notify page manager of fragment insert so that fragment + // properties can be inserted as part of the insert operation + DatabasePageManager pageManager = getPageManager(); + if (pageManager != null) + { + pageManager.updateFragmentPropertiesList(this, fragmentProperties); + fragmentProperties = null; + } + } + + /* (non-Javadoc) + * @see org.apache.ojb.broker.PersistenceBrokerAware#afterLookup(org.apache.ojb.broker.PersistenceBroker) + */ + public void afterLookup(PersistenceBroker broker) + { + } + + /* (non-Javadoc) + * @see org.apache.ojb.broker.PersistenceBrokerAware#afterUpdate(org.apache.ojb.broker.PersistenceBroker) + */ + public void afterUpdate(PersistenceBroker broker) + { + // notify page manager of fragment update so that fragment + // properties can be updated as part of the update operation + DatabasePageManager pageManager = getPageManager(); + if (pageManager != null) + { + pageManager.updateFragmentPropertiesList(this, fragmentProperties); + fragmentProperties = null; + } + } + + /* (non-Javadoc) + * @see org.apache.ojb.broker.PersistenceBrokerAware#beforeDelete(org.apache.ojb.broker.PersistenceBroker) + */ + public void beforeDelete(PersistenceBroker broker) + { + // notify page manager of fragment delete so that fragment + // properties can be removed as part of the remove operation + DatabasePageManager pageManager = getPageManager(); + if (pageManager != null) + { + pageManager.removeFragmentPropertiesList(this, fragmentProperties); + fragmentProperties = null; + } + } + + /* (non-Javadoc) + * @see org.apache.ojb.broker.PersistenceBrokerAware#beforeInsert(org.apache.ojb.broker.PersistenceBroker) + */ + public void beforeInsert(PersistenceBroker broker) + { + } + + /* (non-Javadoc) + * @see org.apache.ojb.broker.PersistenceBrokerAware#beforeUpdate(org.apache.ojb.broker.PersistenceBroker) + */ + public void beforeUpdate(PersistenceBroker broker) + { + } + /** * Validate fragment using specified validation listener. * Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/FragmentPropertyImpl.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/FragmentPropertyImpl.java?rev=893587&r1=893586&r2=893587&view=diff ============================================================================== --- portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/FragmentPropertyImpl.java (original) +++ portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/om/page/impl/FragmentPropertyImpl.java Wed Dec 23 18:02:53 2009 @@ -16,6 +16,7 @@ */ package org.apache.jetspeed.om.page.impl; +import org.apache.jetspeed.om.page.BaseFragmentElement; import org.apache.jetspeed.om.page.BaseFragmentPropertyImpl; import org.apache.jetspeed.om.page.FragmentProperty; @@ -28,11 +29,42 @@ public class FragmentPropertyImpl extends BaseFragmentPropertyImpl implements FragmentProperty { private int id; + private BaseFragmentElement fragment; private String name; private String scope; private String scopeValue; private String value; + /** + * Get implementation identity key. + * + * @return identity key. + */ + public int getIdentity() + { + return id; + } + + /** + * Get owning fragment instance. + * + * @return owning fragment + */ + public BaseFragmentElement getFragment() + { + return fragment; + } + + /** + * Set owning fragment instance. + * + * @param fragment owning fragment + */ + public void setFragment(BaseFragmentElement fragment) + { + this.fragment = fragment; + } + /* (non-Javadoc) * @see org.apache.jetspeed.om.page.FragmentProperty#getName() */ @@ -144,25 +176,15 @@ } /** - * Get implementation identity key. - * - * @return identity key. - */ - public int getIdentity() - { - return id; - } - - /** * Test whether property object matches. * * @param other match candidate * @return match flag */ - boolean match(FragmentPropertyImpl other) + protected boolean match(FragmentProperty other) { - return ((((name != null) && name.equals(other.name)) || ((name == null) && (other.name == null))) && - (((scope != null) && scope.equals(other.scope)) || ((scope == null) && (other.scope == null))) && - (((scopeValue != null) && scopeValue.equals(other.scopeValue)) || ((scopeValue == null) && (other.scopeValue == null)))); + return ((((name != null) && name.equals(other.getName())) || ((name == null) && (other.getName() == null))) && + (((scope != null) && scope.equals(other.getScope())) || ((scope == null) && (other.getScope() == null))) && + (((scopeValue != null) && scopeValue.equals(other.getScopeValue())) || ((scopeValue == null) && (other.getScopeValue() == null)))); } } 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=893587&r1=893586&r2=893587&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 Dec 23 18:02:53 2009 @@ -21,7 +21,8 @@ import java.util.Iterator; import java.util.List; -import org.apache.jetspeed.om.page.BaseFragmentElement;; +import org.apache.jetspeed.om.page.BaseFragmentElement; +import org.apache.jetspeed.om.page.FragmentProperty; /** * FragmentPropertyList @@ -46,7 +47,7 @@ /* (non-Javadoc) * @see java.util.List#add(int,java.lang.Object) */ - public void add(int index, Object element) + public synchronized void add(int index, Object element) { // implement for modifiable AbstractList: FragmentPropertyImpl add = (FragmentPropertyImpl)element; @@ -73,7 +74,7 @@ /* (non-Javadoc) * @see java.util.List#get(int) */ - public Object get(int index) + public synchronized Object get(int index) { // implement for modifiable AbstractList return properties.get(index); @@ -82,7 +83,7 @@ /* (non-Javadoc) * @see java.util.List#remove(int) */ - public Object remove(int index) + public synchronized Object remove(int index) { // implement for modifiable AbstractList: // save removed element @@ -93,7 +94,7 @@ /* (non-Javadoc) * @see java.util.List#set(int,java.lang.Object) */ - public Object set(int index, Object element) + public synchronized Object set(int index, Object element) { // implement for modifiable AbstractList: FragmentPropertyImpl set = (FragmentPropertyImpl)element; @@ -127,7 +128,7 @@ /* (non-Javadoc) * @see java.util.List#size() */ - public int size() + public synchronized int size() { // implement for modifiable AbstractList return properties.size(); @@ -144,12 +145,32 @@ } /** + * Get underlying fragment properties list. + * + * @return fragment property list + */ + public List getProperties() + { + return properties; + } + + /** + * Get underlying removed fragment properties list. + * + * @return removed fragment property list + */ + public List getRemovedProperties() + { + return removedProperties; + } + + /** * Find matching property. * * @param match match property * @return matching property */ - protected FragmentPropertyImpl getMatchingProperty(FragmentPropertyImpl match) + public synchronized FragmentPropertyImpl getMatchingProperty(FragmentProperty match) { Iterator matchIter = properties.iterator(); while (matchIter.hasNext()) 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=893587&r1=893586&r2=893587&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 Dec 23 18:02:53 2009 @@ -16,11 +16,14 @@ */ package org.apache.jetspeed.page.impl; +import java.security.AccessController; +import java.security.Principal; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import javax.security.auth.Subject; @@ -104,6 +107,11 @@ import org.apache.jetspeed.page.document.NodeException; import org.apache.jetspeed.page.document.NodeSet; import org.apache.jetspeed.page.document.impl.NodeImpl; +import org.apache.jetspeed.security.Group; +import org.apache.jetspeed.security.JSSubject; +import org.apache.jetspeed.security.Role; +import org.apache.jetspeed.security.SubjectHelper; +import org.apache.jetspeed.security.User; import org.apache.ojb.broker.core.proxy.ProxyHelper; import org.apache.ojb.broker.query.Criteria; import org.apache.ojb.broker.query.QueryByCriteria; @@ -2607,26 +2615,121 @@ * @param baseFragmentElement owning fragment of fragment property list * @return new or cached fragment property list */ - public FragmentPropertyList getFragmentPropertiesList(BaseFragmentElementImpl baseFragmentElement) + public FragmentPropertyList getFragmentPropertiesList(BaseFragmentElementImpl baseFragmentElement, FragmentPropertyList transientList) { - // check thread local fragment property lists cache - String cacheKey = baseFragmentElement.getBaseFragmentsElement().getPath()+"/"+baseFragmentElement.getId(); - Map cache = (Map)fragmentPropertyListsCache.get(); - FragmentPropertyList list = ((cache != null) ? (FragmentPropertyList)cache.get(cacheKey) : null); + // access thread local fragment property lists cache + String threadLocalCacheKey = getFragmentPropertiesListThreadLocalCacheKey(baseFragmentElement); + Map threadLocalCache = (Map)fragmentPropertyListsCache.get(); + + // get cached persistent list + FragmentPropertyList list = ((threadLocalCache != null) ? (FragmentPropertyList)threadLocalCache.get(threadLocalCacheKey) : null); if (list == null) { - // create new fragment property list - list = new FragmentPropertyList(baseFragmentElement); + // use transient list or create new fragment property list + list = ((transientList != null) ? transientList : new FragmentPropertyList(baseFragmentElement)); - // TODO: query for fragment property list using database query + // build fragment properties database query + Criteria filter = new Criteria(); + filter.addEqualTo("fragment", new Integer(baseFragmentElement.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()); + if (subject != null) + { + if (FragmentProperty.GROUP_AND_ROLE_PROPERTY_SCOPES_ENABLED) + { + Set principals = subject.getPrincipals(); + Iterator principalsIter = principals.iterator(); + while (principalsIter.hasNext()) + { + Principal principal = (Principal)principalsIter.next(); + if (principal instanceof User) + { + Criteria userScopeFilter = new Criteria(); + userScopeFilter.addEqualTo("scope", FragmentProperty.USER_PROPERTY_SCOPE); + userScopeFilter.addEqualTo("scopeValue", principal.getName()); + scopesFilter.addOrCriteria(userScopeFilter); + } + else if (principal instanceof Group) + { + Criteria groupScopeFilter = new Criteria(); + groupScopeFilter.addEqualTo("scope", FragmentProperty.GROUP_PROPERTY_SCOPE); + groupScopeFilter.addEqualTo("scopeValue", principal.getName()); + scopesFilter.addOrCriteria(groupScopeFilter); + } + else if (principal instanceof Role) + { + Criteria roleScopeFilter = new Criteria(); + roleScopeFilter.addEqualTo("scope", FragmentProperty.ROLE_PROPERTY_SCOPE); + roleScopeFilter.addEqualTo("scopeValue", principal.getName()); + scopesFilter.addOrCriteria(roleScopeFilter); + } + } + } + else + { + Principal userPrincipal = SubjectHelper.getBestPrincipal(subject, User.class); + if (userPrincipal != null) + { + Criteria userScopeFilter = new Criteria(); + userScopeFilter.addEqualTo("scope", FragmentProperty.USER_PROPERTY_SCOPE); + userScopeFilter.addEqualTo("scopeValue", userPrincipal.getName()); + scopesFilter.addOrCriteria(userScopeFilter); + } + } + } + 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 (cache == null) + if (threadLocalCache == null) { - cache = new HashMap(); - fragmentPropertyListsCache.set(cache); + threadLocalCache = new HashMap(); + fragmentPropertyListsCache.set(threadLocalCache); + } + threadLocalCache.put(threadLocalCacheKey, list); + } + else if (transientList != null) + { + synchronized (list) + { + synchronized (transientList) + { + // merge into persistent list; this is unsafe due to the + // lack of transactional isolation in shared objects, but + // this should only happen before new objects are committed + // and here we are assuming that only the current user has + // access to the new objects + Iterator sourceIter = transientList.iterator(); + while (sourceIter.hasNext()) + { + FragmentProperty sourceProperty = (FragmentProperty)sourceIter.next(); + FragmentProperty targetProperty = list.getMatchingProperty(sourceProperty); + if (targetProperty != null) + { + targetProperty.setValue(sourceProperty.getValue()); + } + else + { + list.add(sourceProperty); + } + } + + // clear transient list + transientList.getProperties().clear(); + List removedProperties = transientList.getRemovedProperties(); + if (removedProperties != null) + { + removedProperties.clear(); + } + } } - cache.put(cacheKey, list); } return list; } @@ -2636,9 +2739,35 @@ * * @param list fragment property list */ - public void updateFragmentPropertiesList(FragmentPropertyList list) + public void updateFragmentPropertiesList(BaseFragmentElementImpl baseFragmentElement, FragmentPropertyList transientList) { - // TODO: NYI + // update persistent list + FragmentPropertyList list = getFragmentPropertiesList(baseFragmentElement, transientList); + if (list != null) + { + // update fragment properties in list in database + synchronized (list) + { + Iterator propertiesIter = list.getProperties().iterator(); + while (propertiesIter.hasNext()) + { + FragmentPropertyImpl storeProperty = (FragmentPropertyImpl)propertiesIter.next(); + storeProperty.setFragment(baseFragmentElement); + getPersistenceBrokerTemplate().store(storeProperty); + } + List removedProperties = list.getRemovedProperties(); + if (removedProperties != null) + { + Iterator removedPropertiesIter = removedProperties.iterator(); + while (removedPropertiesIter.hasNext()) + { + FragmentPropertyImpl deleteProperty = (FragmentPropertyImpl)removedPropertiesIter.next(); + deleteProperty.setFragment(baseFragmentElement); + getPersistenceBrokerTemplate().delete(deleteProperty); + } + } + } + } } /** @@ -2646,11 +2775,74 @@ * * @param list fragment property list */ - public void removeFragmentPropertiesList(FragmentPropertyList list) + public void removeFragmentPropertiesList(BaseFragmentElementImpl baseFragmentElement, FragmentPropertyList transientList) { - // TODO: NYI - } + // access thread local fragment property lists cache + String threadLocalCacheKey = getFragmentPropertiesListThreadLocalCacheKey(baseFragmentElement); + Map threadLocalCache = (Map)fragmentPropertyListsCache.get(); + + // remove cached persistent list + FragmentPropertyList list = ((threadLocalCache != null) ? (FragmentPropertyList)threadLocalCache.get(threadLocalCacheKey) : null); + if (list != null) + { + // remove list from cache + threadLocalCache.remove(threadLocalCacheKey); + // cleanup list + synchronized (list) + { + list.getProperties().clear(); + List removedProperties = list.getRemovedProperties(); + if (removedProperties != null) + { + removedProperties.clear(); + } + } + } + + // cleanup transient list + if (transientList != null) + { + synchronized (transientList) + { + transientList.getProperties().clear(); + List removedProperties = transientList.getRemovedProperties(); + if (removedProperties != null) + { + removedProperties.clear(); + } + } + } + // remove all fragment properties in list from database + Criteria filter = new Criteria(); + filter.addEqualTo("fragment", new Integer(baseFragmentElement.getIdentity())); + QueryByCriteria query = QueryFactory.newQuery(FragmentPropertyImpl.class, filter); + getPersistenceBrokerTemplate().deleteByQuery(query); + } + + /** + * Compute thread local cache key for fragment properties. + * + * @param baseFragmentElement owner of fragment properties + * @return key string + */ + private static String getFragmentPropertiesListThreadLocalCacheKey(BaseFragmentElementImpl baseFragmentElement) + { + // base key + String key = baseFragmentElement.getBaseFragmentsElement().getPath()+"/"+baseFragmentElement.getId(); + // append current user if available + Subject subject = JSSubject.getSubject(AccessController.getContext()); + if (subject != null) + { + Principal userPrincipal = SubjectHelper.getBestPrincipal(subject, User.class); + if (userPrincipal != null) + { + key = key+"/"+userPrincipal.getName(); + } + } + return key; + } + /** * Rollback transactions registered with current thread. */ Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/resources/JETSPEED-INF/ojb/page-manager-repository.xml URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/resources/JETSPEED-INF/ojb/page-manager-repository.xml?rev=893587&r1=893586&r2=893587&view=diff ============================================================================== --- portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/resources/JETSPEED-INF/ojb/page-manager-repository.xml (original) +++ portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/main/resources/JETSPEED-INF/ojb/page-manager-repository.xml Wed Dec 23 18:02:53 2009 @@ -2831,6 +2831,22 @@ access="anonymous" /> + <reference-descriptor + name="fragment" + class-ref="org.apache.jetspeed.om.page.impl.BaseFragmentElementImpl" + auto-retrieve="true" + auto-delete="link" + auto-update="link" + > + <foreignkey field-ref="fragmentId"/> + </reference-descriptor> + + <field-descriptor + name="name" + column="NAME" + jdbc-type="VARCHAR" + /> + <field-descriptor name="scope" column="SCOPE" Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/java/org/apache/jetspeed/page/TestDatabasePageManager.java URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/java/org/apache/jetspeed/page/TestDatabasePageManager.java?rev=893587&r1=893586&r2=893587&view=diff ============================================================================== --- portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/java/org/apache/jetspeed/page/TestDatabasePageManager.java (original) +++ portals/jetspeed-2/portal/trunk/components/jetspeed-page-manager/src/test/java/org/apache/jetspeed/page/TestDatabasePageManager.java Wed Dec 23 18:02:53 2009 @@ -16,10 +16,16 @@ */ package org.apache.jetspeed.page; +import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Set; + +import javax.security.auth.Subject; + import org.apache.jetspeed.components.util.DatasourceEnabledSpringTestCase; import org.apache.jetspeed.om.common.SecurityConstraint; import org.apache.jetspeed.om.common.SecurityConstraints; @@ -47,6 +53,8 @@ import org.apache.jetspeed.page.document.DocumentNotFoundException; import org.apache.jetspeed.page.document.FailedToUpdateDocumentException; import org.apache.jetspeed.page.document.Node; +import org.apache.jetspeed.security.JSSubject; +import org.apache.jetspeed.security.PrincipalsSet; import junit.framework.Test; @@ -286,17 +294,50 @@ root.setTitle("Root Fragment"); root.setState("Normal"); root.setLayoutSizes("50%,50%"); - /* - TODO: reenable once extended properties supported FragmentProperty property1 = pageManager.newFragmentProperty(); property1.setName("custom-prop1"); property1.setValue("custom-prop-value1"); root.getProperties().add(property1); FragmentProperty property2 = pageManager.newFragmentProperty(); - property2.setName("custom-prop1"); - property2.setValue("custom-prop-value1"); + property2.setName("custom-prop2"); + property2.setValue("custom-prop-value2"); root.getProperties().add(property2); - */ + root.setProperty("custom-0", null, null, "custom-value-0"); + root.setProperty("custom-1", null, null, "custom-value-1"); + root.setProperty("custom-2", null, null, "custom-value-2"); + root.setProperty("custom-3", null, null, "custom-value-3"); + final Fragment userRootFragment = root; + Exception userException = (Exception)JSSubject.doAsPrivileged(constructUserSubject(), new PrivilegedAction() + { + public Object run() + { + try + { + if (FragmentProperty.GROUP_AND_ROLE_PROPERTY_SCOPES_ENABLED) + { + userRootFragment.setProperty("custom-1", FragmentProperty.ROLE_PROPERTY_SCOPE, "role", "custom-value-role-1"); + userRootFragment.setProperty("custom-2", FragmentProperty.ROLE_PROPERTY_SCOPE, "role", "custom-value-role-2"); + userRootFragment.setProperty("custom-2", FragmentProperty.GROUP_PROPERTY_SCOPE, "group", "custom-value-group-2"); + userRootFragment.setProperty("custom-3", FragmentProperty.ROLE_PROPERTY_SCOPE, "role", "custom-value-role-3"); + userRootFragment.setProperty("custom-3", FragmentProperty.GROUP_PROPERTY_SCOPE, "group", "custom-value-group-3"); + } + userRootFragment.setProperty("custom-3", FragmentProperty.USER_PROPERTY_SCOPE, "user", "custom-value-user-3"); + return null; + } + catch (Exception e) + { + return e; + } + finally + { + JSSubject.clearSubject(); + } + } + }, null); + if (userException != null) + { + throw userException; + } Fragment portlet = pageManager.newPortletFragment(); portlet.setName("security::LoginPortlet"); @@ -815,10 +856,64 @@ assertEquals("Normal", check.getRootFragment().getState()); assertEquals("50%,50%", check.getRootFragment().getLayoutSizes()); assertNotNull(check.getRootFragment().getProperties()); - /* - TODO: reenable once extended properties supported assertEquals("custom-prop-value1", check.getRootFragment().getProperty("custom-prop1")); - */ + assertEquals("custom-value-0", checkRootFragment.getProperty("custom-0")); + assertEquals("custom-value-1", checkRootFragment.getProperty("custom-1")); + assertEquals("custom-value-2", checkRootFragment.getProperty("custom-2")); + assertEquals("custom-value-3", checkRootFragment.getProperty("custom-3")); + final Fragment checkUserFragment = checkRootFragment; + Exception userException = (Exception)JSSubject.doAsPrivileged(constructUserSubject(), new PrivilegedAction() + { + public Object run() + { + try + { + List properties = checkUserFragment.getProperties(); + assertNotNull(properties); + assertEquals((FragmentProperty.GROUP_AND_ROLE_PROPERTY_SCOPES_ENABLED ? 12 : 7), properties.size()); + assertEquals("50%,50%", checkUserFragment.getProperty(Fragment.SIZES_PROPERTY_NAME)); + assertEquals("custom-value-0", checkUserFragment.getProperty("custom-0")); + assertNull(checkUserFragment.getProperty("custom-0", Fragment.USER_PROPERTY_SCOPE, null)); + assertNull(checkUserFragment.getProperty("custom-0", Fragment.USER_PROPERTY_SCOPE, "user")); + if (FragmentProperty.GROUP_AND_ROLE_PROPERTY_SCOPES_ENABLED) + { + assertEquals("custom-value-role-1", checkUserFragment.getProperty("custom-1")); + assertNotNull(checkUserFragment.getProperty("custom-1", Fragment.ROLE_PROPERTY_SCOPE, "role")); + } + else + { + assertEquals("custom-value-1", checkUserFragment.getProperty("custom-1")); + } + assertNull(checkUserFragment.getProperty("custom-1", Fragment.USER_PROPERTY_SCOPE, "user")); + if (FragmentProperty.GROUP_AND_ROLE_PROPERTY_SCOPES_ENABLED) + { + assertEquals("custom-value-group-2", checkUserFragment.getProperty("custom-2")); + assertNotNull(checkUserFragment.getProperty("custom-2", Fragment.GROUP_PROPERTY_SCOPE, "group")); + } + else + { + assertEquals("custom-value-2", checkUserFragment.getProperty("custom-2")); + } + assertNull(checkUserFragment.getProperty("custom-2", Fragment.USER_PROPERTY_SCOPE, "user")); + assertEquals("custom-value-user-3", checkUserFragment.getProperty("custom-3")); + assertNotNull(checkUserFragment.getProperty("custom-3", Fragment.USER_PROPERTY_SCOPE, null)); + assertNotNull(checkUserFragment.getProperty("custom-3", Fragment.USER_PROPERTY_SCOPE, "user")); + return null; + } + catch (Exception e) + { + return e; + } + finally + { + JSSubject.clearSubject(); + } + } + }, null); + if (userException != null) + { + throw userException; + } assertNotNull(checkRootFragment.getFragments()); assertEquals(3, checkRootFragment.getFragments().size()); BaseFragmentElement checkElement0 = (BaseFragmentElement)checkRootFragment.getFragments().get(0); @@ -1045,8 +1140,6 @@ Page page = pageManager.getPage("/default-page.psml"); assertEquals("/default-page.psml", page.getPath()); page.setTitle("UPDATED"); - /* - TODO: reenable once extended properties supported FragmentProperty removeProperty = null; Iterator propertyIter = page.getRootFragment().getProperties().iterator(); while (propertyIter.hasNext()) @@ -1058,7 +1151,6 @@ } } page.getRootFragment().getProperties().remove(removeProperty); - */ FragmentProperty property = pageManager.newFragmentProperty(); property.setName("UPDATED"); property.setValue("UPDATED"); @@ -1244,4 +1336,14 @@ assertEquals(0, pmel.updatedNodeCount); assertEquals(25, pmel.removedNodeCount); } + + private Subject constructUserSubject() + { + // setup test subject + Set principals = new PrincipalsSet(); + principals.add(new TestUser("user")); + principals.add(new TestGroup("group")); + principals.add(new TestRole("role")); + return new Subject(true, principals, new HashSet(), new HashSet()); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: jetspeed-dev-unsubscr...@portals.apache.org For additional commands, e-mail: jetspeed-dev-h...@portals.apache.org