From f75175cbd3cadb33d370e1ae1fa664b935ffb63f Mon Sep 17 00:00:00 2001 From: Jan Vonka Date: Wed, 1 Aug 2007 16:30:28 +0000 Subject: [PATCH] - add TenantService hooks to (Db)NodeService - add deleteStore to NodeService (not yet exposed via public API) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6391 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/node-services-context.xml | 3 + .../repo/domain/hibernate/Node.hbm.xml | 44 ++++++- .../repo/node/AbstractNodeServiceImpl.java | 11 +- .../repo/node/db/DbNodeServiceImpl.java | 117 +++++++++++++++--- .../alfresco/repo/node/db/NodeDaoService.java | 9 ++ .../HibernateNodeDaoServiceImpl.java | 76 +++++++++++- 6 files changed, 239 insertions(+), 21 deletions(-) diff --git a/config/alfresco/node-services-context.xml b/config/alfresco/node-services-context.xml index 542e20757f..34f64c7d1e 100644 --- a/config/alfresco/node-services-context.xml +++ b/config/alfresco/node-services-context.xml @@ -158,6 +158,9 @@ + + + diff --git a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml index 2a2ffe6d01..25983f85ce 100644 --- a/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml +++ b/source/java/org/alfresco/repo/domain/hibernate/Node.hbm.xml @@ -449,5 +449,47 @@ assoc.id ]]> - + + + select + status + from + org.alfresco.repo.domain.hibernate.NodeStatusImpl as status + where + status.key.protocol = :protocol and + status.key.identifier = :identifier + + + + select + assoc + from + org.alfresco.repo.domain.hibernate.ChildAssocImpl as assoc + where + assoc.parent.id in (select + node.id + from + org.alfresco.repo.domain.hibernate.NodeImpl node + where + node.store.key.protocol = :protocol and + node.store.key.identifier = :identifier) + + + + select + node + from + org.alfresco.repo.domain.hibernate.NodeImpl as node + where + node.store.key.protocol = :nodeProtocol and + node.store.key.identifier = :nodeIdentifier and + node.id != (select + rootNode.id + from + org.alfresco.repo.domain.hibernate.StoreImpl store + where + store.key.protocol = :storeProtocol and + store.key.identifier = :storeIdentifier) + + diff --git a/source/java/org/alfresco/repo/node/AbstractNodeServiceImpl.java b/source/java/org/alfresco/repo/node/AbstractNodeServiceImpl.java index 3e86e26d7a..482ad17b4f 100644 --- a/source/java/org/alfresco/repo/node/AbstractNodeServiceImpl.java +++ b/source/java/org/alfresco/repo/node/AbstractNodeServiceImpl.java @@ -533,7 +533,10 @@ public abstract class AbstractNodeServiceImpl implements NodeService try { Set aspectQNames = getAspects(nodeRef); - QName typeQName = getType(nodeRef); + + // special case, e.g. when onAuditAspect runs as System + QName typeQName = getTypeInternal(nodeRef); + qnames = new HashSet(aspectQNames.size() + 1); qnames.addAll(aspectQNames); qnames.add(typeQName); @@ -545,6 +548,12 @@ public abstract class AbstractNodeServiceImpl implements NodeService // done return qnames; } + + // default implementation, should be overridden to support MT + protected QName getTypeInternal(NodeRef nodeRef) + { + return getType(nodeRef); + } /** * Generates a GUID for the node using either the creation properties or just by diff --git a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java index 3581516798..05f2d3a15a 100644 --- a/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/DbNodeServiceImpl.java @@ -48,6 +48,7 @@ import org.alfresco.repo.domain.Store; import org.alfresco.repo.node.AbstractNodeServiceImpl; import org.alfresco.repo.node.StoreArchiveMap; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition; @@ -93,7 +94,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl private NodeDaoService nodeDaoService; private StoreArchiveMap storeArchiveMap; private NodeService avmNodeService; - + private TenantService tenantService; + public DbNodeServiceImpl() { storeArchiveMap = new StoreArchiveMap(); // in case it is not set @@ -114,6 +116,11 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl this.avmNodeService = avmNodeService; } + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + /** * Performs a null-safe get of the node * @@ -125,7 +132,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl { ParameterCheck.mandatory("nodeRef", nodeRef); - Node unchecked = nodeDaoService.getNode(nodeRef); + Node unchecked = nodeDaoService.getNode(tenantService.getName(nodeRef)); if (unchecked == null) { throw new InvalidNodeRefException("Node does not exist: " + nodeRef, nodeRef); @@ -143,7 +150,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl { ParameterCheck.mandatory("nodeRef", nodeRef); - NodeStatus nodeStatus = nodeDaoService.getNodeStatus(nodeRef, false); + NodeStatus nodeStatus = nodeDaoService.getNodeStatus(tenantService.getName(nodeRef), false); if (nodeStatus == null || nodeStatus.getNode() == null) { throw new InvalidNodeRefException("Node does not exist: " + nodeRef, nodeRef); @@ -153,6 +160,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl public boolean exists(StoreRef storeRef) { + storeRef = tenantService.getName(storeRef); Store store = nodeDaoService.getStore(storeRef.getProtocol(), storeRef.getIdentifier()); boolean exists = (store != null); // done @@ -163,6 +171,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl { ParameterCheck.mandatory("nodeRef", nodeRef); + nodeRef = tenantService.getName(nodeRef); Node node = nodeDaoService.getNode(nodeRef); boolean exists = (node != null); // done @@ -173,6 +182,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl { ParameterCheck.mandatory("nodeRef", nodeRef); + nodeRef = tenantService.getName(nodeRef); NodeStatus nodeStatus = nodeDaoService.getNodeStatus(nodeRef, false); if (nodeStatus == null) // node never existed { @@ -195,7 +205,21 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl List storeRefs = new ArrayList(stores.size()); for (Store store : stores) { - storeRefs.add(store.getStoreRef()); + StoreRef storeRef = store.getStoreRef(); + try + { + if (tenantService.isTenantUser()) + { + tenantService.checkDomain(storeRef.getIdentifier()); + storeRef = tenantService.getBaseName(storeRef); + } + + storeRefs.add(storeRef); + } + catch (RuntimeException re) + { + // deliberately ignore - stores in different domain will not be listed + } } // Now get the AVMStores. List avmStores = avmNodeService.getStores(); @@ -210,7 +234,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl */ public StoreRef createStore(String protocol, String identifier) { - StoreRef storeRef = new StoreRef(protocol, identifier); + StoreRef storeRef = tenantService.getName(new StoreRef(protocol, identifier)); + identifier = storeRef.getIdentifier(); // check that the store does not already exist Store store = nodeDaoService.getStore(protocol, identifier); if (store != null) @@ -238,11 +263,40 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl { throw new RuntimeException("Incorrect store reference"); } + storeRef = tenantService.getBaseName(storeRef); return storeRef; } + /** + * @see NodeDaoService#deleteStore(String, String) + */ + public void deleteStore(StoreRef storeRef) + { + storeRef = tenantService.getName(storeRef); + + String protocol = storeRef.getProtocol(); + String identifier = storeRef.getIdentifier(); + + // check that the store does exist + Store store = nodeDaoService.getStore(protocol, identifier); + if (store == null) + { + throw new InvalidStoreRefException("Unable to delete a store that does not exist: " + storeRef, storeRef); + } + + // TODO invoke policies - e.g. tell indexer to delete index + //invokeBeforeDeleteStore(ContentModel.TYPE_STOREROOT, storeRef); + + // (hard) delete store + nodeDaoService.deleteStore(protocol, identifier); + + // done + return; + } + public NodeRef getRootNode(StoreRef storeRef) throws InvalidStoreRefException { + storeRef = tenantService.getName(storeRef); Store store = nodeDaoService.getStore(storeRef.getProtocol(), storeRef.getIdentifier()); if (store == null) { @@ -255,6 +309,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl throw new InvalidStoreRefException("Store does not have a root node: " + storeRef, storeRef); } NodeRef nodeRef = node.getNodeRef(); + nodeRef = tenantService.getBaseName(nodeRef); // done return nodeRef; } @@ -286,6 +341,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl Assert.notNull(assocQName); // Get the parent node + parentRef = tenantService.getName(parentRef); Node parentNode = getNodeNotNull(parentRef); // null property map is allowed @@ -381,10 +437,11 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl Set nodeAspects = node.getAspects(); for (AspectDefinition defaultAspectDef : defaultAspectDefs) { - invokeBeforeAddAspect(nodeRef, defaultAspectDef.getName()); - nodeAspects.add(defaultAspectDef.getName()); + QName aspectTypeQName = defaultAspectDef.getName(); + invokeBeforeAddAspect(nodeRef, aspectTypeQName); + nodeAspects.add(aspectTypeQName); addDefaultPropertyValues(defaultAspectDef, properties); - invokeOnAddAspect(nodeRef, defaultAspectDef.getName()); + invokeOnAddAspect(nodeRef, aspectTypeQName); // Now add any default aspects for this aspect addDefaultAspects(defaultAspectDef, node, properties); @@ -510,6 +567,15 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl return node.getTypeQName(); } + @Override + protected QName getTypeInternal(NodeRef nodeRef) + { + Node node = getNodeNotNull(nodeRef); + + // special case, e.g. when onAuditAspect runs as System + return tenantService.getName(nodeRef, node.getTypeQName()); + } + /** * @see org.alfresco.service.cmr.repository.NodeService#setType(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName) */ @@ -547,6 +613,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl Map aspectProperties) throws InvalidNodeRefException, InvalidAspectException { + nodeRef = tenantService.getName(nodeRef); // check that the aspect is legal AspectDefinition aspectDef = dictionaryService.getAspect(aspectTypeQName); if (aspectDef == null) @@ -571,7 +638,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl // Set any default property values that appear on the aspect addDefaultPropertyValues(aspectDef, nodeProperties); - // Add any dependant aspect + // Add any dependent aspect addDefaultAspects(aspectDef, node, nodeProperties); // Set the property values back on the node @@ -690,6 +757,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl public void deleteNode(NodeRef nodeRef) { + nodeRef = tenantService.getName(nodeRef); // First get the node to ensure that it exists Node node = getNodeNotNull(nodeRef); @@ -715,6 +783,10 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl else { StoreRef storeRef = nodeRef.getStoreRef(); + + // remove tenant domain - to retrieve archive store from map + storeRef = tenantService.getBaseName(storeRef); + archiveStoreRef = storeArchiveMap.getArchiveMap().get(storeRef); // get the type and check if we need archiving TypeDefinition typeDef = dictionaryService.getType(node.getTypeQName()); @@ -733,6 +805,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl } else { + archiveStoreRef = tenantService.getName(archiveStoreRef); // archive it archiveNode(nodeRef, archiveStoreRef); // The archive performs a move, which will fire the appropriate OnDeleteNode @@ -884,9 +957,9 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl */ private void addIntrinsicProperties(Node node, Map properties) { - NodeRef nodeRef = node.getNodeRef(); + NodeRef nodeRef = tenantService.getBaseName(node.getNodeRef()); properties.put(ContentModel.PROP_STORE_PROTOCOL, nodeRef.getStoreRef().getProtocol()); - properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier()); + properties.put(ContentModel.PROP_STORE_IDENTIFIER, nodeRef.getStoreRef().getIdentifier()); properties.put(ContentModel.PROP_NODE_UUID, nodeRef.getId()); properties.put(ContentModel.PROP_NODE_DBID, node.getId()); // add the ID as the name, if required @@ -898,6 +971,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl public Map getProperties(NodeRef nodeRef) throws InvalidNodeRefException { + nodeRef = tenantService.getName(nodeRef); Node node = getNodeNotNull(nodeRef); return getPropertiesImpl(node); } @@ -1043,6 +1117,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl { Assert.notNull(qname); + nodeRef = tenantService.getName(nodeRef); // get the node Node node = getNodeNotNull(nodeRef); @@ -1096,6 +1171,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl throw new UnsupportedOperationException("The property " + qname + " may not be removed individually"); } + nodeRef = tenantService.getName(nodeRef); // Get the node Node node = getNodeNotNull(nodeRef); @@ -1128,8 +1204,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl for (ChildAssoc assoc : parentAssocs) { // get the parent - Node parentNode = assoc.getParent(); - results.add(parentNode.getNodeRef()); + results.add(tenantService.getBaseName(assoc.getParent().getNodeRef())); } // done return results; @@ -1158,7 +1233,14 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl // no match - ignore continue; } - results.add(assoc.getChildAssocRef()); + ChildAssociationRef childAssocRef = new ChildAssociationRef( + assoc.getChildAssocRef().getTypeQName(), + tenantService.getBaseName(assoc.getChildAssocRef().getParentRef()), + assoc.getChildAssocRef().getQName(), + tenantService.getBaseName(assoc.getChildAssocRef().getChildRef()), + assoc.getChildAssocRef().isPrimary(), + assoc.getChildAssocRef().getNthSibling()); + results.add(childAssocRef); } // done return results; @@ -1231,7 +1313,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl ChildAssoc childAssoc = nodeDaoService.getChildAssoc(node, assocTypeQName, childName); if (childAssoc != null) { - return childAssoc.getChild().getNodeRef(); + return tenantService.getBaseName(childAssoc.getChild().getNodeRef()); } else { @@ -1443,9 +1525,9 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl continue; } // build a path element - NodeRef parentRef = assoc.getParent().getNodeRef(); + NodeRef parentRef = tenantService.getBaseName(assoc.getParent().getNodeRef()); QName qname = assoc.getQname(); - NodeRef childRef = assoc.getChild().getNodeRef(); + NodeRef childRef = tenantService.getBaseName(assoc.getChild().getNodeRef()); boolean isPrimary = assoc.getIsPrimary(); // build a real association reference ChildAssociationRef assocRef = new ChildAssociationRef(assoc.getTypeQName(), parentRef, qname, childRef, isPrimary, -1); @@ -1789,6 +1871,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl public NodeRef getStoreArchiveNode(StoreRef storeRef) { + storeRef = tenantService.getBaseName(storeRef); StoreRef archiveStoreRef = storeArchiveMap.getArchiveMap().get(storeRef); if (archiveStoreRef == null) { diff --git a/source/java/org/alfresco/repo/node/db/NodeDaoService.java b/source/java/org/alfresco/repo/node/db/NodeDaoService.java index 278ee2d8ff..ba9a7aa214 100644 --- a/source/java/org/alfresco/repo/node/db/NodeDaoService.java +++ b/source/java/org/alfresco/repo/node/db/NodeDaoService.java @@ -76,6 +76,15 @@ public interface NodeDaoService */ public Store createStore(String protocol, String identifier); + + /** + * Deletes the unique store for the given protocol and identifier combination + * + * @param protocol a protocol, e.g. {@link org.alfresco.service.cmr.repository.StoreRef#PROTOCOL_WORKSPACE} + * @param identifier a protocol-specific identifier + */ + public void deleteStore(String protocol, String identifier); + /** * @param protocol the protocol that the store serves * @param identifier the protocol-specific identifer diff --git a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java index e958d68147..70a79a47e0 100644 --- a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java +++ b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java @@ -56,6 +56,7 @@ import org.alfresco.repo.domain.hibernate.ServerImpl; import org.alfresco.repo.domain.hibernate.StoreImpl; import org.alfresco.repo.domain.hibernate.TransactionImpl; import org.alfresco.repo.node.db.NodeDaoService; +import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.TransactionAwareSingleton; import org.alfresco.repo.transaction.TransactionalDao; @@ -105,6 +106,10 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements private static final String QUERY_GET_NODES_WITH_PROPERTY_VALUES_BY_ACTUAL_TYPE = "node.GetNodesWithPropertyValuesByActualType"; private static final String QUERY_GET_SERVER_BY_IPADDRESS = "server.getServerByIpAddress"; + private static final String QUERY_GET_NODE_STATUSES_FOR_STORE = "node.GetNodeStatusesForStore"; + private static final String QUERY_GET_CHILD_ASSOCS_FOR_STORE = "node.GetChildAssocsForStore"; + private static final String QUERY_GET_NODES_EXCEPT_ROOT_FOR_STORE = "node.GetNodesExceptRootForStore"; + private static Log logger = LogFactory.getLog(HibernateNodeDaoServiceImpl.class); /** Log to trace parent association caching: classname + .ParentAssocsCache */ private static Log loggerParentAssocsCache = LogFactory.getLog(HibernateNodeDaoServiceImpl.class.getName() + ".ParentAssocsCache"); @@ -122,6 +127,14 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements /** used for debugging */ private Set changeTxnIdSet; + + TenantService tenantService; + + public void setTenantService(TenantService tenantService) + { + this.tenantService = tenantService; + } + /** * @@ -347,6 +360,65 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements // done return store; } + + /** + * Delete store - this is a hard delete. + * + * @param protocol the store protocol + * @param identifier the store identifier + */ + public void deleteStore(final String protocol, final String identifier) + { + // ensure that the store exists + Store store = getStore(protocol, identifier); + if (store == null) + { + throw new RuntimeException("Store does not exist: \n" + + " protocol: " + protocol + "\n" + + " identifier: " + identifier); + } + + Node rootNode = store.getRootNode(); + + // TODO - convert queries to deletes ? + + // delete node status + Query query = getSession().getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_NODE_STATUSES_FOR_STORE); + + query.setParameter("protocol", protocol); + query.setParameter("identifier", identifier); + + List list = (List)query.list(); + getHibernateTemplate().deleteAll(list); + + // delete child assocs + query = getSession().getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_CHILD_ASSOCS_FOR_STORE); + + query.setParameter("protocol", protocol); + query.setParameter("identifier", identifier); + + list = (List)query.list(); + getHibernateTemplate().deleteAll(list); + + // delete nodes (except root node) + query = getSession().getNamedQuery(HibernateNodeDaoServiceImpl.QUERY_GET_NODES_EXCEPT_ROOT_FOR_STORE); + + query.setParameter("nodeProtocol", protocol); + query.setParameter("nodeIdentifier", identifier); + query.setParameter("storeProtocol", protocol); + query.setParameter("storeIdentifier", identifier); + + list = (List)query.list(); + getHibernateTemplate().deleteAll(list); + + // delete root node and store + getHibernateTemplate().delete(rootNode); + getHibernateTemplate().delete(store); + + // done + return; + } + public Store getStore(String protocol, String identifier) { @@ -796,13 +868,13 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements private Collection convertToChildAssocRefs(Node parentNode, List queryResults) { Collection refs = new ArrayList(queryResults.size()); - NodeRef parentNodeRef = parentNode.getNodeRef(); + NodeRef parentNodeRef = tenantService.getBaseName(parentNode.getNodeRef()); for (Object[] row : queryResults) { String childProtocol = (String) row[5]; String childIdentifier = (String) row[6]; String childUuid = (String) row[7]; - NodeRef childNodeRef = new NodeRef(new StoreRef(childProtocol, childIdentifier), childUuid); + NodeRef childNodeRef = tenantService.getBaseName(new NodeRef(new StoreRef(childProtocol, childIdentifier), childUuid)); QName assocTypeQName = (QName) row[0]; QName assocQName = (QName) row[1]; Boolean assocIsPrimary = (Boolean) row[2];