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

Reply via email to