You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by rw...@apache.org on 2005/11/11 23:40:23 UTC

svn commit: r332661 [1/2] - in /portals/jetspeed-2/trunk/components: cm/src/java/org/apache/jetspeed/components/test/ page-manager/ page-manager/src/java/JETSPEED-INF/ojb/ page-manager/src/java/org/apache/jetspeed/om/folder/impl/ page-manager/src/java/...

Author: rwatler
Date: Fri Nov 11 14:40:15 2005
New Revision: 332661

URL: http://svn.apache.org/viewcvs?rev=332661&view=rev
Log:
- implement OJB class level cache for DatabasePageManager
- implement security constraints and permissions checking for DatabasePageManager
- add security constraints test for page-manager component
- fragment level security constraints permissions checking is not complete for DB and is not yet implemented for Castor/PSML


Added:
    portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManagerCache.java   (with props)
    portals/jetspeed-2/trunk/components/page-manager/src/test/org/apache/jetspeed/page/TestSecureDatabasePageManager.java   (with props)
    portals/jetspeed-2/trunk/components/page-manager/src/test/secure-database-page-manager.xml   (with props)
Modified:
    portals/jetspeed-2/trunk/components/cm/src/java/org/apache/jetspeed/components/test/AbstractSpringTestCase.java
    portals/jetspeed-2/trunk/components/page-manager/maven.xml
    portals/jetspeed-2/trunk/components/page-manager/src/java/JETSPEED-INF/ojb/page-manager-repository.xml
    portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/folder/impl/FolderImpl.java
    portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/BaseElementImpl.java
    portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/FragmentImpl.java
    portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/PageImpl.java
    portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/SecurityConstraintsImpl.java
    portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeImpl.java
    portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeSetImpl.java
    portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManager.java
    portals/jetspeed-2/trunk/components/page-manager/src/test/database-page-manager.xml
    portals/jetspeed-2/trunk/components/page-manager/src/test/org/apache/jetspeed/page/TestDatabasePageManager.java

Modified: portals/jetspeed-2/trunk/components/cm/src/java/org/apache/jetspeed/components/test/AbstractSpringTestCase.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/cm/src/java/org/apache/jetspeed/components/test/AbstractSpringTestCase.java?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/cm/src/java/org/apache/jetspeed/components/test/AbstractSpringTestCase.java (original)
+++ portals/jetspeed-2/trunk/components/cm/src/java/org/apache/jetspeed/components/test/AbstractSpringTestCase.java Fri Nov 11 14:40:15 2005
@@ -38,22 +38,25 @@
      * Provides access to the Spring ApplicationContext.
      */
     protected ClassPathXmlApplicationContext ctx;
-    
+
     /**
      * setup Spring context as part of test setup
      */
     protected void setUp() throws Exception
     {        
         super.setUp();
-        String [] bootConfigurations = getBootConfigurations();
-        if (bootConfigurations != null)
+        if (ctx == null)
         {
-            ApplicationContext bootContext = new ClassPathXmlApplicationContext(bootConfigurations, true);
-            ctx = new ClassPathXmlApplicationContext(getConfigurations(), true, bootContext);
-        }
-        else
-        {
-            ctx = new ClassPathXmlApplicationContext(getConfigurations(), true);
+            String [] bootConfigurations = getBootConfigurations();
+            if (bootConfigurations != null)
+            {
+                ApplicationContext bootContext = new ClassPathXmlApplicationContext(bootConfigurations, true);
+                ctx = new ClassPathXmlApplicationContext(getConfigurations(), true, bootContext);
+            }
+            else
+            {
+                ctx = new ClassPathXmlApplicationContext(getConfigurations(), true);
+            }
         }
     }
 

Modified: portals/jetspeed-2/trunk/components/page-manager/maven.xml
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/maven.xml?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/maven.xml (original)
+++ portals/jetspeed-2/trunk/components/page-manager/maven.xml Fri Nov 11 14:40:15 2005
@@ -16,7 +16,8 @@
 -->
 <project default="java:jar" xmlns:j="jelly:core" xmlns:define="jelly:define">
 
-    <property name='testcase' value='org.apache.jetspeed.page.TestDatabasePageManager' />  
+    <property name='testcase' value='org.apache.jetspeed.page.TestSecureDatabasePageManager' />  
+<!--    <property name='testcase' value='org.apache.jetspeed.page.TestDatabasePageManager' />  -->
 <!--    <property name='testcase' value='org.apache.jetspeed.page.TestCastorXmlPageManager' />  -->
     
 

Modified: portals/jetspeed-2/trunk/components/page-manager/src/java/JETSPEED-INF/ojb/page-manager-repository.xml
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/JETSPEED-INF/ojb/page-manager-repository.xml?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/JETSPEED-INF/ojb/page-manager-repository.xml (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/JETSPEED-INF/ojb/page-manager-repository.xml Fri Nov 11 14:40:15 2005
@@ -22,6 +22,8 @@
       class="org.apache.jetspeed.om.folder.impl.FolderImpl"
       table="FOLDER"
    >
+      <object-cache class="org.apache.jetspeed.page.impl.DatabasePageManagerCache"/>
+
       <field-descriptor
          name="id"
          column="FOLDER_ID"
@@ -339,6 +341,8 @@
       class="org.apache.jetspeed.om.page.impl.PageImpl"
       table="PAGE"
    >
+      <object-cache class="org.apache.jetspeed.page.impl.DatabasePageManagerCache"/>
+
       <field-descriptor
          name="id"
          column="PAGE_ID"
@@ -889,6 +893,8 @@
       class="org.apache.jetspeed.om.page.impl.PageSecurityImpl"
       table="PAGE_SECURITY"
    >
+      <object-cache class="org.apache.jetspeed.page.impl.DatabasePageManagerCache"/>
+
       <field-descriptor
          name="id"
          column="PAGE_SECURITY_ID"

Modified: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/folder/impl/FolderImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/folder/impl/FolderImpl.java?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/folder/impl/FolderImpl.java (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/folder/impl/FolderImpl.java Fri Nov 11 14:40:15 2005
@@ -15,11 +15,13 @@
  */
 package org.apache.jetspeed.om.folder.impl;
 
+import java.security.AccessController;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.jetspeed.om.common.SecuredResource;
 import org.apache.jetspeed.om.folder.Folder;
 import org.apache.jetspeed.om.folder.FolderNotFoundException;
 import org.apache.jetspeed.om.page.Link;
@@ -36,6 +38,8 @@
 import org.apache.jetspeed.page.document.NodeSet;
 import org.apache.jetspeed.page.document.impl.NodeImpl;
 import org.apache.jetspeed.page.document.impl.NodeSetImpl;
+import org.apache.jetspeed.security.FolderPermission;
+import org.apache.ojb.broker.core.proxy.ProxyHelper;
 
 /**
  * FolderImpl
@@ -48,7 +52,7 @@
     private String defaultPage;
     private List folders;
     private List pages;
-    private Collection pageSecurity;
+    private List pageSecurity;
 
     private NodeSet allNodeSet;
     private NodeSet foldersNodeSet;
@@ -144,9 +148,9 @@
     /**
      * setPageSecurity
      *
-     * Sets the page security singleton in the persistent collection and resets cached node sets.
+     * Sets the single page security in the persistent collection and resets cached node sets.
      *
-     * @param pageSecurity new page security impl
+     * @param newPageSecurity new page security impl
      */
     public void setPageSecurity(PageSecurityImpl newPageSecurity)
     {
@@ -183,6 +187,52 @@
     }
     
     /* (non-Javadoc)
+     * @see org.apache.jetspeed.om.page.impl.BaseElementImpl#getEffectivePageSecurity()
+     */
+    public PageSecurity getEffectivePageSecurity()
+    {
+        // return single page security if available
+        PageSecurity pageSecurity = getSinglePageSecurity();
+        if (pageSecurity != null)
+        {
+            return pageSecurity;
+        }
+
+        // delegate to real parent folder implementation
+        FolderImpl parentFolderImpl = (FolderImpl)ProxyHelper.getRealObject(getParent());
+        if (parentFolderImpl != null)
+        {
+            return parentFolderImpl.getEffectivePageSecurity();
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.om.page.impl.BaseElementImpl#checkPermissions(java.lang.String, java.lang.String, boolean, boolean)
+     */
+    public void checkPermissions(String path, String actions, boolean checkNodeOnly, boolean checkParentsOnly) throws SecurityException
+    {
+        // check granted folder permissions unless the check is
+        // to be skipped due to explicity granted access
+        if (!checkParentsOnly)
+        {
+            FolderPermission permission = new FolderPermission(path, actions);
+            AccessController.checkPermission(permission);
+        }
+
+        // if not checking node only, recursively check
+        // all parent permissions in hierarchy
+        if (!checkNodeOnly)
+        {
+            FolderImpl parentFolderImpl = (FolderImpl)ProxyHelper.getRealObject(getParent());
+            if (parentFolderImpl != null)
+            {
+                parentFolderImpl.checkPermissions(actions, false, false);
+            }
+        }
+    }
+
+    /* (non-Javadoc)
      * @see org.apache.jetspeed.om.folder.Folder#getDocumentOrder()
      */
     public List getDocumentOrder()
@@ -219,18 +269,8 @@
      */
     public NodeSet getFolders() throws FolderNotFoundException, DocumentException
     {
-        if (foldersNodeSet != null)
-        {
-            if (folders != null)
-            {
-                foldersNodeSet = new NodeSetImpl(folders);
-            }
-            else
-            {
-                foldersNodeSet = new NodeSetImpl();
-            }
-        }
-        return foldersNodeSet;
+        // return nodes with view access
+        return filterNodeSetByAccess(getFoldersNodeSet());
     }
     
     /* (non-Javadoc)
@@ -238,11 +278,16 @@
      */
     public Folder getFolder(String name) throws FolderNotFoundException, DocumentException
     {
-        Folder folder = (Folder)getFolders().get(name);
+        // select folder by name
+        Folder folder = (Folder)getFoldersNodeSet().get(name);
         if (folder == null)
         {
             throw new FolderNotFoundException("Folder not found: " + name);
         }
+
+        // check for view access on folder
+        folder.checkAccess(SecuredResource.VIEW_ACTION);
+
         return folder;
     }
     
@@ -251,18 +296,8 @@
      */
     public NodeSet getPages() throws NodeException
     {
-        if (pagesNodeSet != null)
-        {
-            if (pages != null)
-            {
-                pagesNodeSet = new NodeSetImpl(pages);
-            }
-            else
-            {
-                pagesNodeSet = new NodeSetImpl();
-            }
-        }
-        return pagesNodeSet;
+        // return nodes with view access
+        return filterNodeSetByAccess(getPagesNodeSet());
     }
     
     /* (non-Javadoc)
@@ -270,11 +305,16 @@
      */
     public Page getPage(String name) throws PageNotFoundException, NodeException
     {
-        Page page = (Page)getPages().get(name);
+        // select page by name
+        Page page = (Page)getPagesNodeSet().get(name);
         if (page == null)
         {
             throw new PageNotFoundException("Page not found: " + name);
         }
+
+        // check for view access on page
+        page.checkAccess(SecuredResource.VIEW_ACTION);
+
         return page;
     }
     
@@ -299,12 +339,17 @@
      */
     public PageSecurity getPageSecurity() throws DocumentNotFoundException, NodeException
     {
-        // get singleton page security
-        if ((pageSecurity != null) && !pageSecurity.isEmpty())
+        // get single page security
+        PageSecurity pageSecurity = getSinglePageSecurity();
+        if (pageSecurity == null)
         {
-            return (PageSecurity)pageSecurity.iterator().next();
+            throw new DocumentNotFoundException("Page security document not found");
         }
-        return null;
+
+        // check for view access on document
+        pageSecurity.checkAccess(SecuredResource.VIEW_ACTION);
+
+        return pageSecurity;
     }
     
     /* (non-Javadoc)
@@ -312,31 +357,8 @@
      */
     public NodeSet getAll() throws FolderNotFoundException, DocumentException
     {
-        if (allNodeSet == null)
-        {
-            List all = new ArrayList();
-            if (folders != null)
-            {
-                all.addAll(folders);
-            }
-            if (pages != null)
-            {
-                all.addAll(pages);
-            }
-            if (pageSecurity != null)
-            {
-                all.addAll(pageSecurity);
-            }
-            if (!all.isEmpty())
-            {
-                allNodeSet = new NodeSetImpl(all);
-            }
-            else
-            {
-                allNodeSet = new NodeSetImpl();
-            }
-        }
-        return allNodeSet;
+        // return nodes with view access
+        return filterNodeSetByAccess(getAllNodeSet());
     }
     
     /* (non-Javadoc)
@@ -379,5 +401,167 @@
     public String getType()
     {
         return FOLDER_TYPE;
-}
+    }
+
+    /**
+     * getFoldersNodeSet
+     *
+     * Latently create and access folders node set.
+     *
+     * @return folders node set
+     */
+    private NodeSet getFoldersNodeSet()
+    {
+        if (foldersNodeSet == null)
+        {
+            if (folders != null)
+            {
+                foldersNodeSet = new NodeSetImpl(folders);
+            }
+            else
+            {
+                foldersNodeSet = new NodeSetImpl();
+            }
+        }
+        return foldersNodeSet;
+    }
+    
+    /**
+     * getPagesNodeSet
+     *
+     * Latently create and access pages node set.
+     *
+     * @return folders node set
+     */
+    private NodeSet getPagesNodeSet() throws NodeException
+    {
+        if (pagesNodeSet == null)
+        {
+            if (pages != null)
+            {
+                pagesNodeSet = new NodeSetImpl(pages);
+            }
+            else
+            {
+                pagesNodeSet = new NodeSetImpl();
+            }
+        }
+        return pagesNodeSet;
+    }
+    
+    /**
+     * getAllNodeSet
+     *
+     * Latently create and access all nodes node set.
+     *
+     * @return all nodes node set
+     */
+    private NodeSet getAllNodeSet()
+    {
+        if (allNodeSet == null)
+        {
+            List all = new ArrayList();
+            if (folders != null)
+            {
+                all.addAll(folders);
+            }
+            if (pages != null)
+            {
+                all.addAll(pages);
+            }
+            if (pageSecurity != null)
+            {
+                all.addAll(pageSecurity);
+            }
+            if (!all.isEmpty())
+            {
+                allNodeSet = new NodeSetImpl(all);
+            }
+            else
+            {
+                allNodeSet = new NodeSetImpl();
+            }
+        }
+        return allNodeSet;
+    }
+
+    /**
+     * getSinglePageSecurity
+     *
+     * Extract single page security from persistent list.
+     *
+     * @return single page security
+     */
+    private PageSecurity getSinglePageSecurity()
+    {
+        if ((pageSecurity != null) && !pageSecurity.isEmpty())
+        {
+            return (PageSecurity)pageSecurity.iterator().next();
+        }
+        return null;
+    }
+
+    /**
+     * filterNodeSetByAccess
+     *
+     * Filter node set elements for view access.
+     *
+     * @param nodes node set containing nodes to check
+     * @return checked subset of nodes
+     */
+    private static NodeSet filterNodeSetByAccess(NodeSet nodes)
+    {
+        if ((nodes != null) && !nodes.isEmpty())
+        {
+            // check permissions and constraints, filter nodes as required
+            NodeSetImpl filteredNodes = null;
+            Iterator checkAccessIter = nodes.iterator();
+            while (checkAccessIter.hasNext())
+            {
+                Node node = (Node)checkAccessIter.next();
+                try
+                {
+                    // check access
+                    node.checkAccess(SecuredResource.VIEW_ACTION);
+
+                    // add to filteredNodes nodes if copying
+                    if (filteredNodes != null)
+                    {
+                        // permitted, add to filteredNodes nodes
+                        filteredNodes.add(node);
+                    }
+                }
+                catch (SecurityException se)
+                {
+                    // create filteredNodes nodes if not already copying
+                    if (filteredNodes == null)
+                    {
+                        // not permitted, copy previously permitted nodes
+                        // to new filteredNodes node set with same comparator
+                        filteredNodes = new NodeSetImpl();
+                        Iterator copyIter = nodes.iterator();
+                        while (copyIter.hasNext())
+                        {
+                            Node copyNode = (Node)copyIter.next();
+                            if (copyNode != node)
+                            {
+                                filteredNodes.add(copyNode);
+                            }
+                            else
+                            {
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+
+            // return filteredNodes nodes if generated
+            if (filteredNodes != null)
+            {
+                return filteredNodes;
+            }
+        }
+        return nodes;
+    }
 }

Modified: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/BaseElementImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/BaseElementImpl.java?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/BaseElementImpl.java (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/BaseElementImpl.java Fri Nov 11 14:40:15 2005
@@ -15,8 +15,25 @@
  */
 package org.apache.jetspeed.om.page.impl;
 
+import java.security.AccessController;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.security.auth.Subject;
+
+import org.apache.jetspeed.om.common.SecuredResource;
 import org.apache.jetspeed.om.common.SecurityConstraints;
 import org.apache.jetspeed.om.page.BaseElement;
+import org.apache.jetspeed.om.page.PageSecurity;
+import org.apache.jetspeed.om.page.SecurityConstraintImpl;
+import org.apache.jetspeed.security.FolderPermission;
+import org.apache.jetspeed.security.GroupPrincipal;
+import org.apache.jetspeed.security.PagePermission;
+import org.apache.jetspeed.security.RolePrincipal;
+import org.apache.jetspeed.security.UserPrincipal;
 import org.apache.ojb.broker.PersistenceBroker;
 import org.apache.ojb.broker.PersistenceBrokerAware;
 import org.apache.ojb.broker.PersistenceBrokerException;
@@ -35,6 +52,9 @@
     private String shortTitle;
     private SecurityConstraintsImpl constraints;
 
+    private boolean constraintsEnabled;
+    private boolean permissionsEnabled;
+
     protected BaseElementImpl(SecurityConstraintsImpl constraints)
     {
         this.constraints = constraints;
@@ -60,12 +80,160 @@
         this.name = name;
     }
 
+    /**
+     * setConstraintsEnabled
+     *
+     * @param enabled enable/disable security constraints checks
+     */
+    public void setConstraintsEnabled(boolean enabled)
+    {
+        constraintsEnabled = enabled;
+    }
+    
+    /**
+     * setPermissionsEnabled
+     *
+     * @param enabled enable/disable security permissions checks
+     */
+    public void setPermissionsEnabled(boolean enabled)
+    {
+        permissionsEnabled = enabled;
+    }
+
+    /**
+     * grantViewActionAccess
+     *
+     * @return granted access for view action
+     */
+    public boolean grantViewActionAccess()
+    {
+        // by default, access must be checked
+        return false;
+    }
+
+    /**
+     * getEffectivePageSecurity
+     *
+     * @return effective page security object
+     */
+    public PageSecurity getEffectivePageSecurity()
+    {
+        // no page security available by default
+        return null;
+    }
+
+    /**
+     * checkConstraints
+     *
+     * Check fully parameterized principal against specified security constraint scope.
+     *
+     * @param actions actions to check
+     * @param userPrincipals principal users list
+     * @param rolePrincipals principal roles list
+     * @param groupPrincipals principal group list
+     * @param checkNodeOnly check node scope only
+     * @param checkParentsOnly check parent folder scope only
+     * @throws SecurityException
+     */
+    public void checkConstraints(List actions, List userPrincipals, List rolePrincipals, List groupPrincipals, boolean checkNodeOnly, boolean checkParentsOnly) throws SecurityException
+    {
+        // check node constraints if available
+        SecurityConstraints constraints = getSecurityConstraints();
+        if (constraints != null)
+        {
+            ((SecurityConstraintsImpl)constraints).checkConstraints(actions, userPrincipals, rolePrincipals, groupPrincipals, getEffectivePageSecurity());
+        }
+    }
+
+    /**
+     * getLogicalPermissionPath
+     *
+     * @return path used for permissions checks
+     */
+    public String getLogicalPermissionPath()
+    {
+        // same as physical path by default
+        return getPhysicalPermissionPath();
+    }
+
+    /**
+     * getPhysicalPermissionPath
+     *
+     * @return path used for permissions checks
+     */
+    public String getPhysicalPermissionPath()
+    {
+        // no permissions path available by default
+        return null;
+    }
+
+    /**
+     * checkPermissions
+     *
+     * @param actions actions to check
+     * @param checkNodeOnly check node scope only
+     * @param checkParentsOnly check parent folder scope only
+     * @throws SecurityException
+     */
+    public void checkPermissions(String actions, boolean checkNodeOnly, boolean checkParentsOnly) throws SecurityException
+    {
+        // check page and folder permissions
+        String physicalPermissionPath = getPhysicalPermissionPath();
+        if (physicalPermissionPath != null)
+        {
+            // check permissions using physical path
+            try
+            {
+                checkPermissions(physicalPermissionPath, actions, checkNodeOnly, checkParentsOnly);
+            }
+            catch (SecurityException physicalSE)
+            {
+                // fallback check using logical path if available and different
+                String logicalPermissionPath = getLogicalPermissionPath();
+                if ((logicalPermissionPath != null) && !logicalPermissionPath.equals(physicalPermissionPath))
+                {
+                    checkPermissions(logicalPermissionPath, actions, checkNodeOnly, checkParentsOnly);
+                }
+                else
+                {
+                    throw physicalSE;
+                }
+            }
+        }
+    }
+
+    /**
+     * checkPermissions
+     *
+     * @param path permissions path to check
+     * @param actions actions to check
+     * @param checkNodeOnly check node scope only
+     * @param checkParentsOnly check parent folder scope only
+     * @throws SecurityException
+     */
+    public void checkPermissions(String path, String actions, boolean checkNodeOnly, boolean checkParentsOnly) throws SecurityException
+    {
+        // check actions permissions
+        try
+        {
+            // check for granted page permissions
+            PagePermission permission = new PagePermission(path, actions);
+            AccessController.checkPermission(permission);
+        }
+        catch (SecurityException se)
+        {
+            // fallback check for granted folder permissions
+            FolderPermission permission = new FolderPermission(path, actions);
+            AccessController.checkPermission(permission);
+        }
+    }
+
     /* (non-Javadoc)
      * @see org.apache.jetspeed.om.common.SecuredResource#getConstraintsEnabled()
      */
     public boolean getConstraintsEnabled()
     {
-        return false; // NYI
+        return constraintsEnabled;
     }
     
     /* (non-Javadoc)
@@ -95,7 +263,91 @@
      */
     public void checkConstraints(String actions) throws SecurityException
     {
-        // NYI
+        // skip checks if not enabled
+        if (!getConstraintsEnabled())
+        {
+            return;
+        }
+
+        // validate specified actions
+        if (actions == null)
+        {
+            throw new SecurityException("BaseElementImpl.checkConstraints(): No actions specified.");
+        }
+
+        // get action names lists; separate view and other
+        // actions to mimic file system permissions logic
+        List viewActionList = SecurityConstraintImpl.parseCSVList(actions);
+        List otherActionsList = null;
+        if (viewActionList.size() == 1)
+        {
+            if (!viewActionList.contains(SecuredResource.VIEW_ACTION))
+            {
+                otherActionsList = viewActionList;
+                viewActionList = null;
+            }
+        }
+        else
+        {
+            otherActionsList = viewActionList;
+            viewActionList = null;
+            if (otherActionsList.remove(SecuredResource.VIEW_ACTION))
+            {
+                viewActionList = new ArrayList(1);
+                viewActionList.add(SecuredResource.VIEW_ACTION);
+            }
+        }
+
+        // get current request context subject
+        Subject subject = Subject.getSubject(AccessController.getContext());
+        if (subject == null)
+        {
+            throw new SecurityException("BaseElementImpl.checkConstraints(): Missing Subject.");
+        }
+
+        // get user/group/role principal names
+        List userPrincipals = null;
+        List rolePrincipals = null;
+        List groupPrincipals = null;
+        Iterator principals = subject.getPrincipals().iterator();
+        while (principals.hasNext())
+        {
+            Principal principal = (Principal) principals.next();
+            if (principal instanceof UserPrincipal)
+            {
+                if (userPrincipals == null)
+                {
+                    userPrincipals = new LinkedList();
+                }
+                userPrincipals.add(principal.getName());
+            }
+            else if (principal instanceof RolePrincipal)
+            {
+                if (rolePrincipals == null)
+                {
+                    rolePrincipals = new LinkedList();
+                }
+                rolePrincipals.add(principal.getName());
+            }
+            else if (principal instanceof GroupPrincipal)
+            {
+                if (groupPrincipals == null)
+                {
+                    groupPrincipals = new LinkedList();
+                }
+                groupPrincipals.add(principal.getName());
+            }
+        }
+
+        // check constraints using parsed action and access lists
+        if (viewActionList != null)
+        {
+            checkConstraints(viewActionList, userPrincipals, rolePrincipals, groupPrincipals, false, grantViewActionAccess());
+        }
+        if (otherActionsList != null)
+        {
+            checkConstraints(otherActionsList, userPrincipals, rolePrincipals, groupPrincipals, true, false);
+        }
     }
 
     /* (non-Javadoc)
@@ -103,7 +355,7 @@
      */
     public boolean getPermissionsEnabled()
     {
-        return false; // NYI
+        return permissionsEnabled;
     }
     
     /* (non-Javadoc)
@@ -111,7 +363,50 @@
      */
     public void checkPermissions(String actions) throws SecurityException
     {
-        // NYI
+        // skip checks if not enabled
+        if (getPermissionsEnabled())
+        {
+            return;
+        }
+
+        // separate view and other actions to mimic file system permissions logic
+        boolean viewAction = false;
+        String otherActions = actions.trim();
+        int viewActionIndex = otherActions.indexOf(SecuredResource.VIEW_ACTION);
+        if (viewActionIndex != -1)
+        {
+            viewAction = true;
+            if (viewActionIndex == 0)
+            {
+                if (otherActions.length() > SecuredResource.VIEW_ACTION.length())
+                {
+                    // remove view action from other actions
+                    int nextDelimIndex = otherActions.indexOf(',', viewActionIndex + SecuredResource.VIEW_ACTION.length());
+                    otherActions = otherActions.substring(nextDelimIndex + 1);
+                }
+                else
+                {
+                    // no other actions
+                    otherActions = null;
+                }
+            }
+            else
+            {
+                // remove view action from other actions
+                int prevDelimIndex = otherActions.lastIndexOf(',', viewActionIndex);
+                otherActions = otherActions.substring(0, prevDelimIndex) + otherActions.substring(viewActionIndex + SecuredResource.VIEW_ACTION.length());
+            }
+        }
+
+        // check permissions using parsed actions
+        if (viewAction)
+        {
+            checkPermissions(SecuredResource.VIEW_ACTION, false, grantViewActionAccess());
+        }
+        if (otherActions != null)
+        {
+            checkPermissions(otherActions, true, false);
+        }
     }
 
     /* (non-Javadoc)
@@ -119,7 +414,15 @@
      */
     public void checkAccess(String actions) throws SecurityException
     {
-        // NYI
+        // check access permissions and constraints as enabled
+        if (getPermissionsEnabled())
+        {
+            checkPermissions(actions);
+        }
+        if (getConstraintsEnabled())
+        {
+            checkConstraints(actions);
+        }
     }
 
     /* (non-Javadoc)

Modified: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/FragmentImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/FragmentImpl.java?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/FragmentImpl.java (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/FragmentImpl.java Fri Nov 11 14:40:15 2005
@@ -21,6 +21,7 @@
 import java.util.List;
 import java.util.Map;
 
+import org.apache.jetspeed.om.common.SecuredResource;
 import org.apache.jetspeed.om.page.Fragment;
 import org.apache.ojb.broker.PersistenceBroker;
 import org.apache.ojb.broker.PersistenceBrokerException;
@@ -54,6 +55,16 @@
     }
 
     /* (non-Javadoc)
+     * @see org.apache.jetspeed.om.common.SecuredResource#getPermissionsEnabled()
+     */
+    public boolean getPermissionsEnabled()
+    {
+        // permission support disabled since path addressing
+        // not supported yet at the fragment level within pages
+        return false;
+    }
+    
+    /* (non-Javadoc)
      * @see org.apache.jetspeed.om.page.Fragment#getType()
      */
     public String getType()
@@ -122,12 +133,16 @@
      */
     public List getFragments()
     {
-        // fragments collection must be defined
+        // mutable fragments collection must be defined... note
+        // that this collection is only mutable if user has full
+        // access rights to all fragments; otherwise, a copy of
+        // the list will be returned and any modifications to the
+        // set of fragments in the collection will not be preserved
         if (fragments == null)
         {
             fragments = new ArrayList();
         }
-        return fragments;
+        return filterFragmentsByAccess(fragments);
     }
     
     /* (non-Javadoc)
@@ -138,7 +153,7 @@
         if (properties != null)
         {
             return (String)properties.get(propName);
-    }
+        }
         return null;
     }
     
@@ -352,5 +367,69 @@
         {
             getProperties().put(extendedPropertyName2, extendedPropertyValue2);
         }
+    }
+
+    /**
+     * filterFragmentsByAccess
+     *
+     * Filter fragments list for view access.
+     *
+     * @param nodes list containing fragments to check
+     * @return checked subset of nodes
+     */
+    private static List filterFragmentsByAccess(List fragments)
+    {
+        if ((fragments != null) && !fragments.isEmpty())
+        {
+            // check permissions and constraints, filter fragments as required
+            List filteredFragments = null;
+            Iterator checkAccessIter = fragments.iterator();
+            while (checkAccessIter.hasNext())
+            {
+                Fragment fragment = (Fragment)checkAccessIter.next();
+                try
+                {
+                    // check access
+                    fragment.checkAccess(SecuredResource.VIEW_ACTION);
+
+                    // add to filteredFragments fragments if copying
+                    if (filteredFragments != null)
+                    {
+                        // permitted, add to filteredFragments fragments
+                        filteredFragments.add(fragment);
+                    }
+                }
+                catch (SecurityException se)
+                {
+                    // create filteredFragments fragments if not already copying
+                    if (filteredFragments == null)
+                    {
+                        // not permitted, copy previously permitted fragments
+                        // to new filteredFragments node set with same comparator
+                        filteredFragments = new ArrayList(fragments.size());
+                        Iterator copyIter = fragments.iterator();
+                        while (copyIter.hasNext())
+                        {
+                            Fragment copyFragment = (Fragment)copyIter.next();
+                            if (copyFragment != fragment)
+                            {
+                                filteredFragments.add(copyFragment);
+                            }
+                            else
+                            {
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+
+            // return filteredFragments fragments if generated
+            if (filteredFragments != null)
+            {
+                return filteredFragments;
+            }
+        }
+        return fragments;
     }
 }

Modified: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/PageImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/PageImpl.java?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/PageImpl.java (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/PageImpl.java Fri Nov 11 14:40:15 2005
@@ -114,7 +114,8 @@
      */
     public Fragment getRootFragment()
     {
-        // get singleton fragment
+        // get singleton fragment; no access checks to
+        // be made for root fragment
         if ((fragment != null) && !fragment.isEmpty())
         {
             return (Fragment)fragment.iterator().next();
@@ -155,7 +156,8 @@
         Fragment fragment = getRootFragment();
         while ((fragment != null) && !fragment.getId().equals(id))
         {
-            // push any fragment fragments onto the local stack
+            // push any fragment fragments onto the local stack;
+            // note that this set is already filtered for access
             List fragments = fragment.getFragments();
             if (!fragments.isEmpty())
             {

Modified: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/SecurityConstraintsImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/SecurityConstraintsImpl.java?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/SecurityConstraintsImpl.java (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/om/page/impl/SecurityConstraintsImpl.java Fri Nov 11 14:40:15 2005
@@ -21,7 +21,9 @@
 
 import org.apache.jetspeed.om.common.SecurityConstraint;
 import org.apache.jetspeed.om.common.SecurityConstraints;
+import org.apache.jetspeed.om.page.PageSecurity;
 import org.apache.jetspeed.om.page.SecurityConstraintImpl;
+import org.apache.jetspeed.om.page.SecurityConstraintsDef;
 
 /**
  * SecurityConstraintsImpl
@@ -37,6 +39,7 @@
 
     private List securityConstraints;
     private List securityConstraintsRefs;
+    private List allConstraints;
 
     /**
      * beforeUpdate
@@ -207,6 +210,167 @@
     {
         // transient by default
         return null;
+    }
+
+    /**
+     * checkConstraints
+     *
+     * @param actions actions to check
+     * @param userPrincipals principal users list
+     * @param rolePrincipals principal roles list
+     * @param groupPrincipals principal group list
+     * @param pageSecurity page security definitions
+     * @throws SecurityException
+     */
+    public void checkConstraints(List actions, List userPrincipals, List rolePrincipals, List groupPrincipals, PageSecurity pageSecurity) throws SecurityException
+    {
+        // if owner defined, override all constraints and allow all access
+        if ((owner != null) && (userPrincipals != null) && userPrincipals.contains(owner))
+        {
+            return;
+        }
+
+        // skip missing or empty constraints: permit all access
+        List checkConstraints = getAllSecurityConstraints(pageSecurity);
+        if ((checkConstraints != null) && !checkConstraints.isEmpty())
+        {
+            // test each action, constraints check passes only
+            // if all actions are permitted for principals
+            Iterator actionsIter = actions.iterator();
+            while (actionsIter.hasNext())
+            {
+                // check each action:
+                // - if any actions explicity permitted, assume no permissions
+                //   are permitted by default
+                // - if all constraints do not specify a permission, assume
+                //   access is permitted by default
+                String action = (String)actionsIter.next();
+                boolean actionPermitted = false;
+                boolean actionNotPermitted = false;
+                boolean anyActionsPermitted = false;
+                
+                // check against constraints
+                Iterator checkConstraintsIter = checkConstraints.iterator();
+                while (checkConstraintsIter.hasNext())
+                {
+                    SecurityConstraintImpl constraint = (SecurityConstraintImpl)checkConstraintsIter.next();
+                    
+                    // if permissions specified, attempt to match constraint
+                    if (constraint.getPermissions() != null)
+                    {
+                        // explicit actions permitted
+                        anyActionsPermitted = true;
+
+                        // test action permission match and user/role/group principal match
+                        if (constraint.actionMatch(action) &&
+                            constraint.principalsMatch(userPrincipals, rolePrincipals, groupPrincipals, true))
+                        {
+                            actionPermitted = true;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        // permissions not specified: not permitted if any principal matched
+                        if (constraint.principalsMatch(userPrincipals, rolePrincipals, groupPrincipals, false))
+                        {
+                            actionNotPermitted = true;
+                            break;
+                        }
+                    }
+                }
+                
+                // fail if any action not permitted
+                if ((!actionPermitted && anyActionsPermitted) || actionNotPermitted)
+                {
+                    throw new SecurityException("SecurityConstraintsImpl.checkConstraints(): Access for " + action + " not permitted.");
+                }
+            }
+        }
+    }
+
+    /**
+     * getAllSecurityConstraints
+     *
+     * @param pageSecurity page security definitions
+     * @return all security constraints
+     */
+    private List getAllSecurityConstraints(PageSecurity pageSecurity)
+    {
+        // return previously cached security constraints; note that
+        // cache is assumed valid until owning document is evicted
+        if (allConstraints != null)
+        {
+            return allConstraints;
+        }
+
+        // construct new ordered security constraints list
+        allConstraints = new ArrayList(8);
+
+        // add any defined security constraints
+        if ((securityConstraints != null) && !securityConstraints.isEmpty())
+        {
+            allConstraints.addAll(securityConstraints);
+        }
+
+        // add any security constraints references
+        if ((securityConstraintsRefs != null) && !securityConstraintsRefs.isEmpty())
+        {
+            List referencedConstraints = dereferenceSecurityConstraintsRefs(securityConstraintsRefs, pageSecurity);
+            if (referencedConstraints != null)
+            {
+                allConstraints.addAll(referencedConstraints);
+            }
+        }
+        
+        // add any global decurity constraints references
+        if (pageSecurity != null)
+        {
+            List globalConstraintsRefs = pageSecurity.getGlobalSecurityConstraintsRefs();
+            if ((globalConstraintsRefs != null) && !globalConstraintsRefs.isEmpty())
+            {
+                List referencedConstraints = dereferenceSecurityConstraintsRefs(globalConstraintsRefs, pageSecurity);
+                if (referencedConstraints != null)
+                {
+                    allConstraints.addAll(referencedConstraints);
+                }
+            }
+        }
+        
+        return allConstraints;
+    }
+
+    /**
+     * <p>
+     * dereferenceSecurityConstraintsRefs
+     * </p>
+     *
+     * @param constraintsRefs contstraints references to be dereferenced
+     * @param pageSecurity page security definitions
+     * @return security constraints
+     */
+    private List dereferenceSecurityConstraintsRefs(List constraintsRefs, PageSecurity pageSecurity)
+    {
+        List constraints = null;
+        if (pageSecurity != null)
+        {   
+            // dereference each security constraints definition
+            Iterator constraintsRefsIter = constraintsRefs.iterator();
+            while (constraintsRefsIter.hasNext())
+            {
+                String constraintsRef = (String)constraintsRefsIter.next();
+                SecurityConstraintsDef securityConstraintsDef = pageSecurity.getSecurityConstraintsDef(constraintsRef);
+                if ((securityConstraintsDef != null) && (securityConstraintsDef.getSecurityConstraints() != null))
+                {
+                    if (constraints == null)
+                    {
+                        constraints = new ArrayList(constraintsRefs.size());
+                    }
+                    constraints.addAll(securityConstraintsDef.getSecurityConstraints());
+                }
+            }
+        }
+        return constraints;
     }
 
     /* (non-Javadoc)

Modified: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeImpl.java?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeImpl.java (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeImpl.java Fri Nov 11 14:40:15 2005
@@ -17,15 +17,18 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.Locale;
 import java.util.StringTokenizer;
 
 import org.apache.jetspeed.om.common.GenericMetadata;
 import org.apache.jetspeed.om.folder.Folder;
 import org.apache.jetspeed.om.page.PageMetadataImpl;
+import org.apache.jetspeed.om.page.PageSecurity;
 import org.apache.jetspeed.om.page.impl.BaseElementImpl;
 import org.apache.jetspeed.om.page.impl.SecurityConstraintsImpl;
 import org.apache.jetspeed.page.document.Node;
+import org.apache.ojb.broker.core.proxy.ProxyHelper;
 
 /**
  * NodeImpl
@@ -164,6 +167,108 @@
     }
 
     /* (non-Javadoc)
+     * @see org.apache.jetspeed.om.page.impl.BaseElementImpl#getEffectivePageSecurity()
+     */
+    public PageSecurity getEffectivePageSecurity()
+    {
+        // by default, delegate to real parent node implementation
+        NodeImpl parentNodeImpl = (NodeImpl)ProxyHelper.getRealObject(parent);
+        if (parentNodeImpl != null)
+        {
+            return parentNodeImpl.getEffectivePageSecurity();
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.om.page.impl.BaseElementImpl#checkConstraints(java.util.List, java.util.List, java.util.List, java.util.List, boolean, boolean)
+     */
+    public void checkConstraints(List actions, List userPrincipals, List rolePrincipals, List groupPrincipals, boolean checkNodeOnly, boolean checkParentsOnly) throws SecurityException
+    {
+        // check constraints in node hierarchy
+        if (checkNodeOnly)
+        {
+            // check node constraints if available; otherwise,
+            // recursively check parent constraints until
+            // default constraints for node are checked
+            SecurityConstraintsImpl constraintsImpl = (SecurityConstraintsImpl)getSecurityConstraints();
+            if (constraintsImpl != null)
+            {
+                constraintsImpl.checkConstraints(actions, userPrincipals, rolePrincipals, groupPrincipals, getEffectivePageSecurity());
+            }
+            else
+            {
+                NodeImpl parentNodeImpl = (NodeImpl)ProxyHelper.getRealObject(parent);
+                if (parentNodeImpl != null)
+                {
+                    parentNodeImpl.checkConstraints(actions, userPrincipals, rolePrincipals, groupPrincipals, checkNodeOnly, false);
+                }
+            }
+        }
+        else
+        {
+            // check node constraints if available and not
+            // to be skipped due to explicity granted access
+            if (!checkParentsOnly)
+            {
+                SecurityConstraintsImpl constraintsImpl = (SecurityConstraintsImpl)getSecurityConstraints();
+                if (constraintsImpl != null)
+                {
+                    constraintsImpl.checkConstraints(actions, userPrincipals, rolePrincipals, groupPrincipals, getEffectivePageSecurity());
+                }
+            }
+
+            // recursively check all parent constraints in hierarchy
+            NodeImpl parentNodeImpl = (NodeImpl)ProxyHelper.getRealObject(parent);
+            if (parentNodeImpl != null)
+            {
+                parentNodeImpl.checkConstraints(actions, userPrincipals, rolePrincipals, groupPrincipals, false, false);
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.om.page.impl.BaseElementImpl#checkPermissions(java.lang.String, java.lang.String, boolean, boolean)
+     */
+    public void checkPermissions(String path, String actions, boolean checkNodeOnly, boolean checkParentsOnly) throws SecurityException
+    {
+        // check granted node permissions unless the check is
+        // to be skipped due to explicity granted access
+        if (!checkParentsOnly)
+        {
+            super.checkPermissions(path, actions, true, false);
+        }
+        
+        // if not checking node only, recursively check
+        // all parent permissions in hierarchy
+        if (!checkNodeOnly)
+        {
+            NodeImpl parentNodeImpl = (NodeImpl)ProxyHelper.getRealObject(parent);
+            if (parentNodeImpl != null)
+            {
+                parentNodeImpl.checkPermissions(actions, false, false);
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.om.page.impl.BaseElementImpl#getLogicalPermissionPath()
+     */
+    public String getLogicalPermissionPath()
+    {
+        // NYI
+        return super.getLogicalPermissionPath();
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.om.page.impl.BaseElementImpl#getPhysicalPermissionPath()
+     */
+    public String getPhysicalPermissionPath()
+    {
+        return path;
+    }
+
+    /* (non-Javadoc)
      * @see org.apache.jetspeed.page.document.Node#getParent()
      */
     public Node getParent()
@@ -176,8 +281,8 @@
      */
     public void setParent(Node parent)
     {
-        // cast to check type
-        this.parent = (NodeImpl)parent;
+        // set node parent
+        this.parent = parent;
 
         // update path if required
         if (parent != null)

Modified: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeSetImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeSetImpl.java?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeSetImpl.java (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/document/impl/NodeSetImpl.java Fri Nov 11 14:40:15 2005
@@ -59,7 +59,7 @@
      */
     public void add(Node node)
     {
-        if (nodes != null)
+        if (nodes == null)
         {
             nodes = new ArrayList(8);
             nodesByName = new HashMap(5);

Modified: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManager.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManager.java?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManager.java (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManager.java Fri Nov 11 14:40:15 2005
@@ -16,12 +16,11 @@
 package org.apache.jetspeed.page.impl;
 
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
-import org.apache.commons.collections.map.LRUMap;
 import org.apache.jetspeed.components.dao.InitablePersistenceBrokerDaoSupport;
 import org.apache.jetspeed.exception.JetspeedException;
+import org.apache.jetspeed.om.common.SecuredResource;
 import org.apache.jetspeed.om.common.SecurityConstraint;
 import org.apache.jetspeed.om.common.SecurityConstraints;
 import org.apache.jetspeed.om.folder.Folder;
@@ -34,6 +33,7 @@
 import org.apache.jetspeed.om.folder.MenuSeparatorDefinition;
 import org.apache.jetspeed.om.folder.impl.FolderImpl;
 import org.apache.jetspeed.om.page.ContentPage;
+import org.apache.jetspeed.om.page.ContentPageImpl;
 import org.apache.jetspeed.om.page.Fragment;
 import org.apache.jetspeed.om.page.Link;
 import org.apache.jetspeed.om.page.Page;
@@ -74,9 +74,10 @@
  * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
  * @version $Id: $
  */
-
 public class DatabasePageManager extends InitablePersistenceBrokerDaoSupport implements PageManager
 {
+    private static final int DEFAULT_CACHE_SIZE = 128;
+
     private static Map modelClasses = new HashMap();
     static
     {
@@ -97,13 +98,26 @@
 
     private DelegatingPageManager delegator;
     
-    private LRUMap databaseNodeCache;
+    private int cacheSize;
+
+    private DatabasePageManagerCache cache;
 
     public DatabasePageManager(String repositoryPath, int cacheSize, boolean isPermissionsSecurity, boolean isConstraintsSecurity)
     {
         super(repositoryPath);
         delegator = new DelegatingPageManager(isPermissionsSecurity, isConstraintsSecurity, modelClasses);
-        databaseNodeCache = new LRUMap(cacheSize);
+        this.cacheSize = Math.max(cacheSize, DEFAULT_CACHE_SIZE);
+        DatabasePageManagerCache.cacheInit(this);
+    }
+
+    /**
+     * getCacheSize
+     *
+     * @return configured cache size
+     */
+    public int getCacheSize()
+    {
+        return cacheSize;
     }
 
     /* (non-Javadoc)
@@ -255,9 +269,8 @@
         // propagate to delegator
         delegator.reset();
 
-        // clean database node cache to force subsequent
-        // refreshs from persistent store
-        databaseNodeCache.clear();
+        // clear cache to force subsequent refreshs from persistent store
+        DatabasePageManagerCache.cacheClear();
     }
 
     /* (non-Javadoc)
@@ -268,18 +281,16 @@
         // construct page attributes from path
         path = NodeImpl.getCanonicalNodePath(path);
 
-        // test cache with canonical path if available
-        if (databaseNodeCache.containsKey(path))
+        // optimized retrieval from cache by path if available
+        NodeImpl cachedNode = DatabasePageManagerCache.cacheLookup(path);
+        if (cachedNode instanceof Page)
         {
-            // return cached page or throw exception if cached as null
-            Page page = (Page) databaseNodeCache.get(path);
-            if (page == null)
-            {
-                throw new PageNotFoundException("Page " + path + " not found.");
-            }
-            return page;
+            // check for view access on page
+            cachedNode.checkAccess(SecuredResource.VIEW_ACTION);
+
+            return (Page)cachedNode;
         }
-        
+
         // retrieve page from database
         try
         {
@@ -288,20 +299,25 @@
             QueryByCriteria query = QueryFactory.newQuery(PageImpl.class, filter);
             Page page = (Page) getPersistenceBrokerTemplate().getObjectByQuery(query);
             
-            // add to or delete entry in document cache
-            databaseNodeCache.put(path, page);
-            
             // return page or throw exception
             if (page == null)
             {
                 throw new PageNotFoundException("Page " + path + " not found.");
             }
+
+            // check for view access on page
+            page.checkAccess(SecuredResource.VIEW_ACTION);
+
             return page;
         }
         catch (PageNotFoundException pnfe)
         {
             throw pnfe;
         }
+        catch (SecurityException se)
+        {
+            throw se;
+        }
         catch (Exception e)
         {
             throw new PageNotFoundException("Page " + path + " not found.", e);
@@ -313,8 +329,8 @@
      */
     public ContentPage getContentPage(String path) throws PageNotFoundException, NodeException
     {
-        // TODO Auto-generated method stub
-        return null;
+        // return proxied page
+        return new ContentPageImpl(getPage(path));
     }
 
     /* (non-Javadoc)
@@ -334,18 +350,16 @@
         // construct document attributes from path
         String path = Folder.PATH_SEPARATOR + PageSecurity.DOCUMENT_TYPE;
 
-        // test cache with canonical path if available
-        if (databaseNodeCache.containsKey(path))
+        // optimized retrieval from cache by path if available
+        NodeImpl cachedNode = DatabasePageManagerCache.cacheLookup(path);
+        if (cachedNode instanceof PageSecurity)
         {
-            // return cached document or throw exception if cached as null
-            PageSecurity document = (PageSecurity) databaseNodeCache.get(path);
-            if (document == null)
-            {
-                throw new DocumentNotFoundException("Document " + path + " not found.");
-            }
-            return document;
+            // check for view access on document
+            cachedNode.checkAccess(SecuredResource.VIEW_ACTION);
+
+            return (PageSecurity)cachedNode;
         }
-        
+
         // retrieve document from database
         try
         {
@@ -354,20 +368,25 @@
             QueryByCriteria query = QueryFactory.newQuery(PageSecurityImpl.class, filter);
             PageSecurity document = (PageSecurity) getPersistenceBrokerTemplate().getObjectByQuery(query);
             
-            // add to or delete entry in document cache
-            databaseNodeCache.put(path, document);
-            
             // return page or throw exception
             if (document == null)
             {
                 throw new DocumentNotFoundException("Document " + path + " not found.");
             }
+
+            // check for view access on document
+            document.checkAccess(SecuredResource.VIEW_ACTION);
+
             return document;
         }
         catch (DocumentNotFoundException dnfe)
         {
             throw dnfe;
         }
+        catch (SecurityException se)
+        {
+            throw se;
+        }
         catch (Exception e)
         {
             throw new DocumentNotFoundException("Document " + path + " not found.", e);
@@ -382,16 +401,14 @@
         // construct folder attributes from path
         folderPath = NodeImpl.getCanonicalNodePath(folderPath);
 
-        // test cache with canonical path if available
-        if (databaseNodeCache.containsKey(folderPath))
+        // optimized retrieval from cache by path if available
+        NodeImpl cachedNode = DatabasePageManagerCache.cacheLookup(folderPath);
+        if (cachedNode instanceof Folder)
         {
-            // return cached folder or throw exception if cached as null
-            Folder folder = (Folder) databaseNodeCache.get(folderPath);
-            if (folder == null)
-            {
-                throw new FolderNotFoundException("Folder " + folderPath + " not found.");
-            }
-            return folder;
+            // check for view access on folder
+            cachedNode.checkAccess(SecuredResource.VIEW_ACTION);
+
+            return (Folder)cachedNode;
         }
 
         // retrieve folder from database
@@ -402,20 +419,25 @@
             QueryByCriteria query = QueryFactory.newQuery(FolderImpl.class, filter);
             Folder folder = (Folder) getPersistenceBrokerTemplate().getObjectByQuery(query);
             
-            // add to or delete entry in folder cache
-            databaseNodeCache.put(folderPath, folder);
-            
             // return folder or throw exception
             if (folder == null)
             {
                 throw new FolderNotFoundException("Folder " + folderPath + " not found.");
             }
+
+            // check for view access on folder
+            folder.checkAccess(SecuredResource.VIEW_ACTION);
+
             return folder;
         }
         catch (FolderNotFoundException fnfe)
         {
             throw fnfe;
         }
+        catch (SecurityException se)
+        {
+            throw se;
+        }
         catch (Exception e)
         {
             throw new FolderNotFoundException("Folder " + folderPath + " not found.", e);
@@ -430,6 +452,10 @@
         try
         {
             // dereference page in case proxy is supplied
+            if (page instanceof ContentPageImpl)
+            {
+                page = ((ContentPageImpl)page).getPage();
+            }
             page = (Page)ProxyHelper.getRealObject(page);
 
             // look up and set parent folder if necessary
@@ -452,6 +478,10 @@
                     throw new PageNotUpdatedException("Missing parent folder: " + parentPath);
                 }
                 
+                // check for edit access on parent folder; page
+                // access not checked on create
+                parent.checkAccess(SecuredResource.EDIT_ACTION);
+
                 try
                 {
                     // update parent folder with added page
@@ -465,23 +495,24 @@
                     parent.removePage((PageImpl)page);
                     throw e;
                 }
-                
-                // update document cache
-                databaseNodeCache.put(pagePath, page);
             }
             else
             {
+                // check for edit access on page and parent folder
+                page.checkAccess(SecuredResource.EDIT_ACTION);
+
                 // update page
                 getPersistenceBrokerTemplate().store(page);
-                
-                // update document cache
-                databaseNodeCache.put(page.getPath(), page);
             }
         }
         catch (PageNotUpdatedException pnue)
         {
             throw pnue;
         }
+        catch (SecurityException se)
+        {
+            throw se;
+        }
         catch (Exception e)
         {
             throw new PageNotUpdatedException("Page " + page.getPath() + " not updated.", e);
@@ -496,8 +527,15 @@
         try
         {
             // dereference page in case proxy is supplied
+            if (page instanceof ContentPageImpl)
+            {
+                page = ((ContentPageImpl)page).getPage();
+            }
             page = (Page)ProxyHelper.getRealObject(page);
 
+            // check for edit access on page and parent folder
+            page.checkAccess(SecuredResource.EDIT_ACTION);
+
             // look up and update parent folder if necessary
             if (page.getParent() != null)
             {
@@ -511,9 +549,10 @@
                 // delete page
                 getPersistenceBrokerTemplate().delete(page);
             }
-            
-            // delete document cache entry
-            databaseNodeCache.put(page.getPath(), null);
+        }
+        catch (SecurityException se)
+        {
+            throw se;
         }
         catch (Exception e)
         {
@@ -551,15 +590,16 @@
                     throw new FolderNotUpdatedException("Missing parent folder: " + parentPath);
                 }
                 
+                // check for edit access on parent folder; folder
+                // access not checked on create
+                parent.checkAccess(SecuredResource.EDIT_ACTION);
+
                 try
                 {
                     // update parent folder with added folder
                     parent.addFolder((FolderImpl)folder);
                     folder.setParent(parent);
                     getPersistenceBrokerTemplate().store(parent);
-                    
-                    // update folder cache
-                    databaseNodeCache.put(folderPath, folder);
                 }
                 catch (Exception e)
                 {
@@ -570,17 +610,21 @@
             }
             else
             {
+                // check for edit access on folder and parent folder
+                folder.checkAccess(SecuredResource.EDIT_ACTION);
+
                 // update folder
                 getPersistenceBrokerTemplate().store(folder);
-                
-                // update folder cache
-                databaseNodeCache.put(folder.getPath(), folder);
             }
         }
         catch (FolderNotUpdatedException fnue)
         {
             throw fnue;
         }
+        catch (SecurityException se)
+        {
+            throw se;
+        }
         catch (Exception e)
         {
             throw new FolderNotUpdatedException("Folder " + folder.getPath() + " not updated.", e);
@@ -597,6 +641,9 @@
             // dereference folder in case proxy is supplied
             folder = (Folder)ProxyHelper.getRealObject(folder);
 
+            // check for edit access on folder and parent folder
+            folder.checkAccess(SecuredResource.EDIT_ACTION);
+
             // look up and update parent folder if necessary
             if (folder.getParent() != null)
             {
@@ -610,18 +657,10 @@
                 // deep delete folder
                 getPersistenceBrokerTemplate().delete(folder);
             }
-            
-            // delete folder and document cache entries
-            String folderPath = folder.getPath();
-            Iterator cacheIter = databaseNodeCache.entrySet().iterator();
-            while (cacheIter.hasNext())
-            {
-                Map.Entry cacheEntry = (Map.Entry)cacheIter.next();
-                if (((String)cacheEntry.getKey()).startsWith(folderPath))
-                {
-                    cacheEntry.setValue(null);
-                }
-            }
+        }
+        catch (SecurityException se)
+        {
+            throw se;
         }
         catch (Exception e)
         {
@@ -677,36 +716,55 @@
                     throw new FailedToUpdateDocumentException("Missing parent folder: " + parentPath);
                 }
 
+                // do not replace existing page security documents
                 try
                 {
-                    // update parent folder with added document
-                    parent.setPageSecurity((PageSecurityImpl)pageSecurity);
-                    pageSecurity.setParent(parent);
-                    getPersistenceBrokerTemplate().store(parent);
+                    // test for page security document
+                    parent.getPageSecurity();
+                    throw new FailedToUpdateDocumentException("Parent folder page security exists: " + parentPath);
+                }
+                catch (DocumentNotFoundException dnfe)
+                {
+                    // check for edit access on parent folder; document
+                    // access not checked on create
+                    parent.checkAccess(SecuredResource.EDIT_ACTION);
+                    
+                    try
+                    {
+                        // update parent folder with added document
+                        parent.setPageSecurity((PageSecurityImpl)pageSecurity);
+                        pageSecurity.setParent(parent);
+                        getPersistenceBrokerTemplate().store(parent);
+                    }
+                    catch (Exception e)
+                    {
+                        // clear document on error
+                        parent.setPageSecurity(null);
+                        throw e;
+                    }
                 }
                 catch (Exception e)
                 {
-                    // cleanup parent folder on error
-                    parent.setPageSecurity(null);
-                    throw e;
+                    throw new FailedToUpdateDocumentException("Parent folder page security exists: " + parentPath);
                 }
-                
-                // update document cache
-                databaseNodeCache.put(pageSecurityPath, pageSecurity);
             }
             else
             {
+                // check for edit access on document and parent folder
+                pageSecurity.checkAccess(SecuredResource.EDIT_ACTION);
+
                 // update document
                 getPersistenceBrokerTemplate().store(pageSecurity);
-                
-                // update document cache
-                databaseNodeCache.put(pageSecurity.getPath(), pageSecurity);
             }
         }
         catch (FailedToUpdateDocumentException fude)
         {
             throw fude;
         }
+        catch (SecurityException se)
+        {
+            throw se;
+        }
         catch (Exception e)
         {
             throw new FailedToUpdateDocumentException("Document " + pageSecurity.getPath() + " not updated.", e);
@@ -723,6 +781,9 @@
             // dereference document in case proxy is supplied
             pageSecurity = (PageSecurity)ProxyHelper.getRealObject(pageSecurity);
 
+            // check for edit access on document and parent folder
+            pageSecurity.checkAccess(SecuredResource.EDIT_ACTION);
+
             // look up and update parent folder if necessary
             if (pageSecurity.getParent() != null)
             {
@@ -736,9 +797,10 @@
                 // delete document
                 getPersistenceBrokerTemplate().delete(pageSecurity);
             }
-            
-            // delete document cache entry
-            databaseNodeCache.put(pageSecurity.getPath(), null);
+        }
+        catch (SecurityException se)
+        {
+            throw se;
         }
         catch (Exception e)
         {

Added: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManagerCache.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManagerCache.java?rev=332661&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManagerCache.java (added)
+++ portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManagerCache.java Fri Nov 11 14:40:15 2005
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jetspeed.page.impl;
+
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.Map;
+
+import org.apache.commons.collections.map.LRUMap;
+import org.apache.jetspeed.page.document.impl.NodeImpl;
+import org.apache.ojb.broker.Identity;
+import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.cache.ObjectCache;
+
+/**
+ * DatabasePageManagerCache
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id: $
+ */
+public class DatabasePageManagerCache implements ObjectCache
+{
+    private static LRUMap cacheByOID;
+    private static LRUMap cacheByPath;
+    private static boolean constraintsEnabled;
+    private static boolean permissionsEnabled;
+
+    /**
+     * cacheInit
+     *
+     * Initialize cache using page manager configuration.
+     *
+     * @param manager configured page manager
+     */
+    public synchronized static void cacheInit(DatabasePageManager pageManager)
+    {
+        if (cacheByOID == null)
+        {
+            cacheByOID = new LRUMap(pageManager.getCacheSize());
+            cacheByPath = new LRUMap(pageManager.getCacheSize());
+            constraintsEnabled = pageManager.getConstraintsEnabled();
+            permissionsEnabled = pageManager.getPermissionsEnabled();
+        }
+    }
+
+    /**
+     * cacheLookup
+     *
+     * Lookup node instances by unique path.
+     *
+     * @param path node unique path
+     * @return cached node
+     */
+    public synchronized static NodeImpl cacheLookup(String path)
+    {
+        Identity oid = (Identity)cacheByPath.get(path);
+        NodeImpl node = (NodeImpl)cacheByOID.get(oid);
+        return node;
+    }
+
+    /**
+     * cacheAdd
+     *
+     * Add object to cache and cache node instances by unique path;
+     * infuse nodes loaded by OJB with page manager configuration.
+     *
+     * @param oid object/node indentity
+     * @param obj object/node to cache
+     */
+    public synchronized static void cacheAdd(Identity oid, Object obj)
+    {
+        cacheByOID.put(oid, obj);
+        if (obj instanceof NodeImpl)
+        {
+            NodeImpl node = (NodeImpl)obj;
+            node.setConstraintsEnabled(constraintsEnabled);
+            node.setPermissionsEnabled(permissionsEnabled);
+            cacheByPath.put(node.getPath(), oid);
+        }
+    }
+
+    /**
+     * cacheClear
+     *
+     * Clear object and node caches.
+     */
+    public synchronized static void cacheClear()
+    {
+        cacheByOID.clear();
+        cacheByPath.clear();
+    }
+
+    /**
+     * cacheLookup
+     *
+     * Lookup objects by identity.
+     *
+     * @param oid object identity
+     * @return cached object
+     */
+    public synchronized static Object cacheLookup(Identity oid)
+    {
+        return cacheByOID.get(oid);
+    }
+
+    /**
+     * cacheRemove
+     *
+     * Remove identified object from object and node caches.
+     *
+     * @param oid object identity
+     */
+    public synchronized static void cacheRemove(Identity oid)
+    {
+        Object obj = cacheByOID.remove(oid);
+        if (obj instanceof NodeImpl)
+        {
+            NodeImpl node = (NodeImpl)obj;
+            cacheByPath.remove(node.getPath());
+        }
+    }
+
+    /**
+     * DatabasePageManagerCache
+     *
+     * Construct a cache instance using OJB compliant signatures.
+     *
+     * @param broker broker that is to own cache
+     * @param props attribute properties passed to cache
+     */
+    public DatabasePageManagerCache(PersistenceBroker broker, Properties props)
+    {
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.ojb.broker.cache.ObjectCache#cache(org.apache.ojb.broker.Identity, java.lang.Object)
+     */
+    public void cache(Identity oid, Object obj)
+    {
+        cacheAdd(oid, obj);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.ojb.broker.cache.ObjectCache#clear()
+     */
+    public void clear()
+    {
+        cacheClear();
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.ojb.broker.cache.ObjectCache#lookup(org.apache.ojb.broker.Identity)
+     */
+    public Object lookup(Identity oid)
+    {
+        return cacheLookup(oid);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.ojb.broker.cache.ObjectCache#remove(org.apache.ojb.broker.Identity)
+     */
+    public void remove(Identity oid)
+    {
+        cacheRemove(oid);
+    }
+}

Propchange: portals/jetspeed-2/trunk/components/page-manager/src/java/org/apache/jetspeed/page/impl/DatabasePageManagerCache.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: portals/jetspeed-2/trunk/components/page-manager/src/test/database-page-manager.xml
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/page-manager/src/test/database-page-manager.xml?rev=332661&r1=332660&r2=332661&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/page-manager/src/test/database-page-manager.xml (original)
+++ portals/jetspeed-2/trunk/components/page-manager/src/test/database-page-manager.xml Fri Nov 11 14:40:15 2005
@@ -17,21 +17,22 @@
 -->
 <beans>
 
-  <bean id="org.apache.jetspeed.page.PageManagerImpl" 
-        name="pageManagerImpl"
-        init-method="init"
-        class="org.apache.jetspeed.page.impl.DatabasePageManager">
-      <!-- OJB configuration file resource path -->
-      <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg>       
-      <!-- folder/page/link cache size, default=128 -->
-      <constructor-arg index="1"><value>128</value></constructor-arg>
-      <!-- permissions security enabled flag, default=false -->
-      <constructor-arg index="2"><value>false</value></constructor-arg>
-      <!-- constraints security enabled flag, default=true -->
-      <constructor-arg index="3"><value>false</value></constructor-arg>
-  </bean>
+    <!-- Page Manager -->
+    <bean id="org.apache.jetspeed.page.PageManagerImpl" 
+          name="pageManagerImpl"
+          init-method="init"
+          class="org.apache.jetspeed.page.impl.DatabasePageManager">
+        <!-- OJB configuration file resource path -->
+        <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg>       
+        <!-- folder/page/link cache size -->
+        <constructor-arg index="1"><value>128</value></constructor-arg>
+        <!-- permissions security enabled flag -->
+        <constructor-arg index="2"><value>false</value></constructor-arg>
+        <!-- constraints security enabled flag -->
+        <constructor-arg index="3"><value>false</value></constructor-arg>
+    </bean>
 
-    <!-- Proxying -->
+    <!-- Transaction Proxying -->
     <bean id="org.apache.jetspeed.page.PageManager" name="pageManager" parent="baseTransactionProxy">
         <property name="proxyInterfaces">
             <value>org.apache.jetspeed.page.PageManager</value>
@@ -42,8 +43,9 @@
         <property name="transactionAttributes">
             <props>
                 <prop key="*">PROPAGATION_SUPPORTS</prop>
-                <prop key="update*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.PageNotUpdatedException</prop>                                
-                <prop key="remove*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.PageNotRemovedException</prop>                                                
+                <prop key="get*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop>
+                <prop key="update*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop>
+                <prop key="remove*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop>
             </props>
         </property>
     </bean>



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org