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