Merged up to HEAD.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3129 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park
2006-06-16 19:18:30 +00:00
parent 936f6d7021
commit 7f79a2a498
118 changed files with 14354 additions and 843 deletions

View File

@@ -517,6 +517,7 @@ public abstract class AbstractNodeServiceImpl implements NodeService
properties.remove(ContentModel.PROP_STORE_PROTOCOL);
properties.remove(ContentModel.PROP_STORE_IDENTIFIER);
properties.remove(ContentModel.PROP_NODE_UUID);
properties.remove(ContentModel.PROP_NODE_DBID);
}
/**
@@ -530,13 +531,15 @@ public abstract class AbstractNodeServiceImpl implements NodeService
* is always present as a property on a node.
*
* @param nodeRef the node reference containing the values required
* @param nodeDbId the database-assigned ID
* @param properties the node properties
*/
protected void addReferencableProperties(NodeRef nodeRef, Map<QName, Serializable> properties)
protected void addReferencableProperties(NodeRef nodeRef, Long nodeDbId, Map<QName, Serializable> properties)
{
properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol());
properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier());
properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId());
properties.put(ContentModel.PROP_NODE_DBID, nodeDbId);
// add the ID as the name, if required
if (properties.get(ContentModel.PROP_NAME) == null)
{

View File

@@ -41,7 +41,6 @@ import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.InvalidAspectException;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.AssociationExistsException;
import org.alfresco.service.cmr.repository.AssociationRef;
@@ -621,17 +620,6 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
// check that the titled aspect is present
assertTrue("Titled aspect not present",
nodeService.hasAspect(nodeRef, ASPECT_QNAME_TEST_TITLED));
// attempt to remove the aspect
try
{
nodeService.removeAspect(nodeRef, ASPECT_QNAME_TEST_TITLED);
fail("Failed to prevent removal of type-required aspect");
}
catch (InvalidAspectException e)
{
// expected
}
}
public static class BadOnDeleteNodePolicy implements
@@ -1040,10 +1028,12 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
Serializable wsProtocol = nodeService.getProperty(rootNodeRef, ContentModel.PROP_STORE_PROTOCOL);
Serializable wsIdentifier = nodeService.getProperty(rootNodeRef, ContentModel.PROP_STORE_IDENTIFIER);
Serializable nodeUuid = nodeService.getProperty(rootNodeRef, ContentModel.PROP_NODE_UUID);
Serializable nodeDbId = nodeService.getProperty(rootNodeRef, ContentModel.PROP_NODE_DBID);
assertNotNull("Workspace Protocol property not present", wsProtocol);
assertNotNull("Workspace Identifier property not present", wsIdentifier);
assertNotNull("Node UUID property not present", nodeUuid);
assertNotNull("Node DB ID property not present", nodeDbId);
assertEquals("Workspace Protocol property incorrect", rootNodeRef.getStoreRef().getProtocol(), wsProtocol);
assertEquals("Workspace Identifier property incorrect", rootNodeRef.getStoreRef().getIdentifier(), wsIdentifier);
@@ -1054,6 +1044,7 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
assertTrue("Workspace Protocol property not present in map", properties.containsKey(ContentModel.PROP_STORE_PROTOCOL));
assertTrue("Workspace Identifier property not present in map", properties.containsKey(ContentModel.PROP_STORE_IDENTIFIER));
assertTrue("Node UUID property not present in map", properties.containsKey(ContentModel.PROP_NODE_UUID));
assertTrue("Node DB ID property not present in map", properties.containsKey(ContentModel.PROP_NODE_DBID));
}
public void testGetParentAssocs() throws Exception

View File

@@ -37,7 +37,9 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
@@ -70,6 +72,7 @@ public class ArchiveAndRestoreTest extends TestCase
private PermissionService permissionService;
private AuthenticationComponent authenticationComponent;
private AuthenticationService authenticationService;
private OwnableService ownableService;
private TransactionService transactionService;
private UserTransaction txn;
@@ -104,6 +107,7 @@ public class ArchiveAndRestoreTest extends TestCase
permissionService = serviceRegistry.getPermissionService();
authenticationService = serviceRegistry.getAuthenticationService();
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
ownableService = (OwnableService) ctx.getBean("ownableService");
transactionService = serviceRegistry.getTransactionService();
// Start a transaction
@@ -138,12 +142,6 @@ public class ArchiveAndRestoreTest extends TestCase
PermissionService.ALL_PERMISSIONS,
true);
// grant everyone rights to the archive store
permissionService.setPermission(
archiveStoreRootNodeRef,
PermissionService.ALL_AUTHORITIES,
PermissionService.ALL_PERMISSIONS,
true);
}
finally
{
@@ -322,6 +320,17 @@ public class ArchiveAndRestoreTest extends TestCase
assertEquals("Mapping of archived store is not correct", archiveStoreRootNodeRef, archiveNodeRef);
}
public void testArchivedAspect() throws Exception
{
// delete 'a'
nodeService.deleteNode(a);
// check that it has the aspect and that the properties are correct
assertTrue("Archived aspect not present", nodeService.hasAspect(a_, ContentModel.ASPECT_ARCHIVED));
Map<QName, Serializable> properties = nodeService.getProperties(a_);
assertNotNull("Original owner property not present", properties.get(ContentModel.PROP_ARCHIVED_ORIGINAL_OWNER));
assertEquals("Original owner property is incorrect", USER_A, properties.get(ContentModel.PROP_ARCHIVED_ORIGINAL_OWNER));
}
public void testArchiveAndRestoreNodeBB() throws Exception
{
// delete a child
@@ -568,6 +577,10 @@ public class ArchiveAndRestoreTest extends TestCase
nodeService.deleteNode(b);
commitAndBeginNewTransaction();
// check that archived nodes are visible
verifyNodeExistence(a_, true);
verifyNodeExistence(b_, true);
nodeArchiveService.purgeAllArchivedNodes(workStoreRef);
commitAndBeginNewTransaction();
@@ -581,35 +594,51 @@ public class ArchiveAndRestoreTest extends TestCase
verifyNodeExistence(aa_, false);
verifyNodeExistence(bb_, false);
}
//
// public void testPermissionsForRestore() throws Exception
// {
// // user A deletes 'a'
// authenticationService.authenticate(USER_A, USER_A.toCharArray());
// nodeService.deleteNode(a);
// // user B deletes 'b'
// authenticationService.authenticate(USER_B, USER_B.toCharArray());
// nodeService.deleteNode(b);
//
// // user B can't see archived 'a'
// List<RestoreNodeReport> restoredByB = nodeArchiveService.restoreAllArchivedNodes(workStoreRef);
// assertEquals("User B should not have seen A's delete", 1, restoredByB.size());
// }
//
// /**
// * Deny the current user the rights to write to the destination location
// * and ensure that the use-case is handled properly.
// */
// public void testPermissionsLackingOnDestination() throws Exception
// {
// // remove 'b', deny permissions to workspace root and attempt a restore
// nodeService.deleteNode(b);
// permissionService.setPermission(workStoreRootNodeRef, USER_B, PermissionService.ADD_CHILDREN, false);
// commitAndBeginNewTransaction();
//
// // the restore of b should fail for user B
// authenticationService.authenticate(USER_B, USER_B.toCharArray());
// RestoreNodeReport report = nodeArchiveService.restoreArchivedNode(b_);
// assertEquals("Expected permission denied status", RestoreStatus.FAILURE_PERMISSION, report.getStatus());
// }
public void testDeletedOwnership() throws Exception
{
// check that A is the current owner of 'b'
String bOwner = ownableService.getOwner(b);
assertEquals("User A must own 'b'", USER_A, bOwner);
// user B deletes 'b'
authenticationService.authenticate(USER_B, USER_B.toCharArray());
nodeService.deleteNode(b);
// check that B is the owner of 'b_'
String b_Owner = ownableService.getOwner(b_);
assertEquals("User B must own 'b_'", USER_B, b_Owner);
}
/**
* Check that node ownership changes correctly
*/
public void testPermissionsForRestore() throws Exception
{
// user A deletes 'a'
authenticationService.authenticate(USER_A, USER_A.toCharArray());
nodeService.deleteNode(a);
// user B deletes 'b'
authenticationService.authenticate(USER_B, USER_B.toCharArray());
nodeService.deleteNode(b);
// user B can't see archived 'a'
List<RestoreNodeReport> restoredByB = nodeArchiveService.restoreAllArchivedNodes(workStoreRef);
assertEquals("User B should be able to see only B's delete", 1, restoredByB.size());
}
/**
* Deny the current user the rights to write to the destination location
* and ensure that the use-case is handled properly.
*/
public void testPermissionsLackingOnDestination() throws Exception
{
// remove 'b', deny permissions to workspace root and attempt a restore
nodeService.deleteNode(b);
permissionService.setPermission(workStoreRootNodeRef, USER_B, PermissionService.ADD_CHILDREN, false);
commitAndBeginNewTransaction();
// the restore of b should fail for user B
authenticationService.authenticate(USER_B, USER_B.toCharArray());
RestoreNodeReport report = nodeArchiveService.restoreArchivedNode(b_);
assertEquals("Expected permission denied status", RestoreStatus.FAILURE_PERMISSION, report.getStatus());
}
}

View File

@@ -40,6 +40,15 @@ public interface NodeArchiveService
*/
public NodeRef getStoreArchiveNode(StoreRef originalStoreRef);
/**
* Get the likely node reference for the original node. There is no
* guarantee that the node exists in the archive store.
*
* @param originalNodeRef the original node reference
* @return Returns the node ref of the node if it was archived.
*/
public NodeRef getArchivedNode(NodeRef originalNodeRef);
/**
* Attempt to restore the given archived node into its original location.
* <p>

View File

@@ -72,6 +72,17 @@ public class NodeArchiveServiceImpl implements NodeArchiveService
return nodeService.getStoreArchiveNode(originalStoreRef);
}
public NodeRef getArchivedNode(NodeRef originalNodeRef)
{
StoreRef orginalStoreRef = originalNodeRef.getStoreRef();
NodeRef archiveRootNodeRef = nodeService.getStoreArchiveNode(orginalStoreRef);
// create the likely location of the archived node
NodeRef archivedNodeRef = new NodeRef(
archiveRootNodeRef.getStoreRef(),
originalNodeRef.getId());
return archivedNodeRef;
}
/**
* Get all the nodes that were archived <b>from</b> the given store.
*/

View File

@@ -595,20 +595,6 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
// get the node
Node node = getNodeNotNull(nodeRef);
// check that the aspect may be removed
TypeDefinition nodeTypeDef = dictionaryService.getType(node.getTypeQName());
if (nodeTypeDef == null)
{
throw new InvalidNodeRefException("The node type is no longer valid: " + nodeRef, nodeRef);
}
List<AspectDefinition> defaultAspects = nodeTypeDef.getDefaultAspects();
if (defaultAspects.contains(aspectDef))
{
throw new InvalidAspectException(
"The aspect is a default for the node's type and cannot be removed: " + aspectTypeQName,
aspectTypeQName);
}
// remove the aspect, if present
boolean removed = node.getAspects().remove(aspectTypeQName);
// if the aspect was present, remove the associated properties
@@ -784,7 +770,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
ret.put(propertyQName, value);
}
// spoof referencable properties
addReferencableProperties(nodeRef, ret);
addReferencableProperties(nodeRef, node.getId(), ret);
// done
return ret;
}
@@ -807,6 +793,12 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
// get the property from the node
Node node = getNodeNotNull(nodeRef);
if (qname.equals(ContentModel.PROP_NODE_DBID))
{
return node.getId();
}
Map<QName, PropertyValue> properties = node.getProperties();
PropertyValue propertyValue = properties.get(qname);
@@ -1310,7 +1302,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
ChildAssoc primaryParentAssoc = nodeDaoService.getPrimaryParentAssoc(node);
// add the aspect
node.getAspects().add(ContentModel.ASPECT_ARCHIVED);
Set<QName> aspects = node.getAspects();
aspects.add(ContentModel.ASPECT_ARCHIVED);
Map<QName, PropertyValue> properties = node.getProperties();
PropertyValue archivedByProperty = makePropertyValue(
dictionaryService.getProperty(ContentModel.PROP_ARCHIVED_BY),
@@ -1324,6 +1317,21 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
dictionaryService.getProperty(ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC),
primaryParentAssoc.getChildAssocRef());
properties.put(ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC, archivedPrimaryParentNodeRefProperty);
PropertyValue originalOwnerProperty = properties.get(ContentModel.PROP_OWNER);
PropertyValue originalCreatorProperty = properties.get(ContentModel.PROP_CREATOR);
if (originalOwnerProperty != null || originalCreatorProperty != null)
{
properties.put(
ContentModel.PROP_ARCHIVED_ORIGINAL_OWNER,
originalOwnerProperty != null ? originalOwnerProperty : originalCreatorProperty);
}
// change the node ownership
aspects.add(ContentModel.ASPECT_OWNABLE);
PropertyValue newOwnerProperty = makePropertyValue(
dictionaryService.getProperty(ContentModel.PROP_ARCHIVED_ORIGINAL_OWNER),
AuthenticationUtil.getCurrentUserName());
properties.put(ContentModel.PROP_OWNER, newOwnerProperty);
// move the node
NodeRef archiveStoreRootNodeRef = getRootNode(archiveStoreRef);
@@ -1557,11 +1565,20 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
ChildAssociationRef originalPrimaryParentAssocRef = (ChildAssociationRef) makeSerializableValue(
dictionaryService.getProperty(ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC),
properties.get(ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC));
PropertyValue originalOwnerProperty = properties.get(ContentModel.PROP_ARCHIVED_ORIGINAL_OWNER);
// remove the aspect archived aspect
aspects.remove(ContentModel.ASPECT_ARCHIVED);
properties.remove(ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC);
properties.remove(ContentModel.PROP_ARCHIVED_BY);
properties.remove(ContentModel.PROP_ARCHIVED_DATE);
properties.remove(ContentModel.PROP_ARCHIVED_ORIGINAL_OWNER);
// restore the original ownership
if (originalOwnerProperty != null)
{
aspects.add(ContentModel.ASPECT_OWNABLE);
properties.put(ContentModel.PROP_OWNER, originalOwnerProperty);
}
if (destinationParentNodeRef == null)
{

View File

@@ -35,6 +35,7 @@ import org.alfresco.repo.domain.hibernate.NodeStatusImpl;
import org.alfresco.repo.domain.hibernate.StoreImpl;
import org.alfresco.repo.node.db.NodeDaoService;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionalDao;
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -54,7 +55,7 @@ import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
*
* @author Derek Hulley
*/
public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements NodeDaoService
public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements NodeDaoService, TransactionalDao
{
private static final String QUERY_GET_ALL_STORES = "store.GetAllStores";
private static final String QUERY_GET_CONTENT_DATA_STRINGS = "node.GetContentDataStrings";

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.node.integrity;
import java.util.List;
import java.util.Set;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Event raised to check nodes' aspects
*
* @author Derek Hulley
*/
public class AspectsIntegrityEvent extends AbstractIntegrityEvent
{
private static Log logger = LogFactory.getLog(AspectsIntegrityEvent.class);
protected AspectsIntegrityEvent(
NodeService nodeService,
DictionaryService dictionaryService,
NodeRef nodeRef)
{
super(nodeService, dictionaryService, nodeRef, null, null);
}
public void checkIntegrity(List<IntegrityRecord> eventResults)
{
NodeRef nodeRef = getNodeRef();
if (!nodeService.exists(nodeRef))
{
// node has gone
if (logger.isDebugEnabled())
{
logger.debug("Event ignored - node gone: " + this);
}
eventResults.clear();
return;
}
else
{
checkMandatoryAspects(getNodeRef(), eventResults);
}
}
/**
* Checks that the node has the required mandatory aspects applied
*/
private void checkMandatoryAspects(NodeRef nodeRef, List<IntegrityRecord> eventResults)
{
Set<QName> aspects = nodeService.getAspects(nodeRef);
// get the node type
QName nodeTypeQName = nodeService.getType(nodeRef);
// get the aspects that should exist
TypeDefinition typeDef = dictionaryService.getType(nodeTypeQName);
List<AspectDefinition> mandatoryAspectDefs = typeDef.getDefaultAspects();
// check
for (AspectDefinition aspect : mandatoryAspectDefs)
{
if (aspects.contains(aspect.getName()))
{
// it's fine
continue;
}
IntegrityRecord result = new IntegrityRecord(
"Mandatory aspect not set: \n" +
" Node: " + nodeRef + "\n" +
" Type: " + nodeTypeQName + "\n" +
" Aspect: " + aspect.getName());
eventResults.add(result);
// next one
continue;
}
// done
}
}

View File

@@ -278,25 +278,23 @@ public class IntegrityChecker
*/
public void onCreateNode(ChildAssociationRef childAssocRef)
{
NodeRef childRef = childAssocRef.getChildRef();
IntegrityEvent event = null;
// check properties on child node
event = new PropertiesIntegrityEvent(
nodeService,
dictionaryService,
childAssocRef.getChildRef());
childRef);
save(event);
// check target role
event = new AssocTargetRoleIntegrityEvent(
nodeService,
dictionaryService,
childAssocRef.getParentRef(),
childAssocRef.getTypeQName(),
childAssocRef.getQName());
// check that the multiplicity and other properties of the new association are allowed
onCreateChildAssociation(childAssocRef);
// check mandatory aspects
event = new AspectsIntegrityEvent(nodeService, dictionaryService, childRef);
save(event);
// check for associations defined on the new node (child)
NodeRef childRef = childAssocRef.getChildRef();
QName childNodeTypeQName = nodeService.getType(childRef);
ClassDefinition nodeTypeDef = dictionaryService.getClass(childNodeTypeQName);
if (nodeTypeDef == null)
@@ -376,10 +374,15 @@ public class IntegrityChecker
}
/**
* No checking performed: The property changes will be handled
* @see AspectsIntegrityEvent
*/
public void onRemoveAspect(NodeRef nodeRef, QName aspectTypeQName)
{
IntegrityEvent event = null;
// check mandatory aspects
event = new AspectsIntegrityEvent(nodeService, dictionaryService, nodeRef);
save(event);
}
/**

View File

@@ -135,8 +135,22 @@ public class IntegrityTest extends TestCase
public void tearDown() throws Exception
{
authenticationComponent.clearCurrentSecurityContext();
txn.rollback();
try
{
authenticationComponent.clearCurrentSecurityContext();
}
catch (Throwable e)
{
e.printStackTrace();
}
try
{
txn.rollback();
}
catch (Throwable e)
{
e.printStackTrace();
}
}
/**
@@ -220,6 +234,15 @@ public class IntegrityTest extends TestCase
checkIntegrityNoFailure();
}
public void testRemoveMandatoryAspect() throws Exception
{
NodeRef nodeRef = createNode("abc", TEST_TYPE_WITH_ASPECT, allProperties);
// just remove the aspect
nodeService.removeAspect(nodeRef, TEST_ASPECT_WITH_PROPERTIES);
checkIntegrityExpectFailure("Failed to removal of mandatory aspect", 1);
}
public void testCreateTargetOfAssocsWithMandatorySourcesPresent() throws Exception
{
// this is the target of 3 assoc types where the source cardinality is 1..1