From 166de93b489db258d2c43ea78ec3772909211391 Mon Sep 17 00:00:00 2001 From: David Caruana Date: Wed, 5 Apr 2006 19:14:20 +0000 Subject: [PATCH] Fixes for supporting full repository export/import. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2625 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repo/content/RoutingContentService.java | 4 +- .../repo/exporter/ExporterComponent.java | 52 ++++++++++++++----- .../exporter/RepositoryExporterComponent.java | 5 +- .../repo/exporter/ViewXMLExporter.java | 50 ++++++++++++++++-- .../alfresco/repo/importer/ImportNode.java | 7 +-- .../repo/importer/ImporterComponent.java | 25 +++------ .../repo/importer/ImporterComponentTest.java | 1 + .../repo/importer/view/NodeContext.java | 23 +++++++- .../cmr/view/ExporterCrawlerParameters.java | 23 +++++++- .../service/cmr/view/ReferenceType.java | 29 +++++++++++ 10 files changed, 175 insertions(+), 44 deletions(-) create mode 100644 source/java/org/alfresco/service/cmr/view/ReferenceType.java diff --git a/source/java/org/alfresco/repo/content/RoutingContentService.java b/source/java/org/alfresco/repo/content/RoutingContentService.java index bb9af1060d..750a78e367 100644 --- a/source/java/org/alfresco/repo/content/RoutingContentService.java +++ b/source/java/org/alfresco/repo/content/RoutingContentService.java @@ -228,7 +228,7 @@ public class RoutingContentService implements ContentService // Fire the content update policy Set types = new HashSet(this.nodeService.getAspects(nodeRef)); types.add(this.nodeService.getType(nodeRef)); - OnContentUpdatePolicy policy = this.onContentUpdateDelegate.get(types); + OnContentUpdatePolicy policy = this.onContentUpdateDelegate.get(nodeRef, types); policy.onContentUpdate(nodeRef, newContent); } } @@ -294,7 +294,7 @@ public class RoutingContentService implements ContentService // Fire the content update policy Set types = new HashSet(this.nodeService.getAspects(nodeRef)); types.add(this.nodeService.getType(nodeRef)); - OnContentReadPolicy policy = this.onContentReadDelegate.get(types); + OnContentReadPolicy policy = this.onContentReadDelegate.get(nodeRef, types); policy.onContentRead(nodeRef); } diff --git a/source/java/org/alfresco/repo/exporter/ExporterComponent.java b/source/java/org/alfresco/repo/exporter/ExporterComponent.java index 90e7a75965..a4ff1bf048 100644 --- a/source/java/org/alfresco/repo/exporter/ExporterComponent.java +++ b/source/java/org/alfresco/repo/exporter/ExporterComponent.java @@ -53,6 +53,7 @@ import org.alfresco.service.cmr.view.ExporterException; import org.alfresco.service.cmr.view.ExporterService; import org.alfresco.service.cmr.view.ImporterException; import org.alfresco.service.cmr.view.Location; +import org.alfresco.service.cmr.view.ReferenceType; import org.alfresco.service.descriptor.DescriptorService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -158,7 +159,7 @@ public class ExporterComponent ParameterCheck.mandatory("View Writer", viewWriter); // Construct a basic XML Exporter - Exporter xmlExporter = createXMLExporter(viewWriter); + Exporter xmlExporter = createXMLExporter(viewWriter, parameters.getReferenceType()); // Export exportView(xmlExporter, parameters, progress); @@ -174,7 +175,7 @@ public class ExporterComponent // create exporter around export handler exportHandler.startExport(); OutputStream dataFile = exportHandler.createDataStream(); - Exporter xmlExporter = createXMLExporter(dataFile); + Exporter xmlExporter = createXMLExporter(dataFile, parameters.getReferenceType()); URLExporter urlExporter = new URLExporter(xmlExporter, exportHandler); // export @@ -201,9 +202,10 @@ public class ExporterComponent * output stream in xml format. * * @param viewWriter the output stream to write to + * @param referenceType the format of references to export * @return the xml exporter */ - private Exporter createXMLExporter(OutputStream viewWriter) + private Exporter createXMLExporter(OutputStream viewWriter, ReferenceType referenceType) { // Define output format OutputFormat format = OutputFormat.createPrettyPrint(); @@ -215,12 +217,18 @@ public class ExporterComponent try { XMLWriter writer = new XMLWriter(viewWriter, format); - return new ViewXMLExporter(namespaceService, nodeService, searchService, dictionaryService, permissionService, writer); + ViewXMLExporter exporter = new ViewXMLExporter(namespaceService, nodeService, searchService, dictionaryService, permissionService, writer); + exporter.setReferenceType(referenceType); + return exporter; } catch (UnsupportedEncodingException e) { throw new ExporterException("Failed to create XML Writer for export", e); } + catch (Exception e) + { + throw new ExporterException("Failed to create XML Writer for export", e); + } } @@ -254,12 +262,12 @@ public class ExporterComponent // determine if root repository node NodeRef nodeRef = context.getExportOf(); - boolean rootNode = nodeService.getRootNode(nodeRef.getStoreRef()).equals(nodeRef); - if (parameters.isCrawlSelf() && !rootNode) + if (parameters.isCrawlSelf()) { // export root node of specified export location walkStartNamespaces(parameters, exporter); - walkNode(nodeRef, parameters, exporter); + boolean rootNode = nodeService.getRootNode(nodeRef.getStoreRef()).equals(nodeRef); + walkNode(nodeRef, parameters, exporter, rootNode); walkEndNamespaces(parameters, exporter); } else if (parameters.isCrawlChildNodes()) @@ -269,7 +277,7 @@ public class ExporterComponent for (ChildAssociationRef childAssoc : childAssocs) { walkStartNamespaces(parameters, exporter); - walkNode(childAssoc.getChildRef(), parameters, exporter); + walkNode(childAssoc.getChildRef(), parameters, exporter, false); walkEndNamespaces(parameters, exporter); } } @@ -335,7 +343,7 @@ public class ExporterComponent * * @param nodeRef the node to navigate */ - private void walkNode(NodeRef nodeRef, ExporterCrawlerParameters parameters, Exporter exporter) + private void walkNode(NodeRef nodeRef, ExporterCrawlerParameters parameters, Exporter exporter, boolean exportAsRef) { // Export node (but only if it's not excluded from export) QName type = nodeService.getType(nodeRef); @@ -343,8 +351,16 @@ public class ExporterComponent { return; } - - exporter.startNode(nodeRef); + + // export node as reference to node, or as the actual node + if (exportAsRef) + { + exporter.startReference(nodeRef, null); + } + else + { + exporter.startNode(nodeRef); + } // Export node aspects exporter.startAspects(nodeRef); @@ -361,7 +377,7 @@ public class ExporterComponent // Export node permissions AccessStatus readPermission = permissionService.hasPermission(nodeRef, PermissionService.READ_PERMISSIONS); - if (readPermission.equals(AccessStatus.ALLOWED)) + if (authenticationService.isCurrentUserTheSystemUser() || readPermission.equals(AccessStatus.ALLOWED)) { Set permissions = permissionService.getAllSetPermissions(nodeRef); boolean inheritPermissions = permissionService.getInheritParentPermissions(nodeRef); @@ -442,7 +458,7 @@ public class ExporterComponent } if (!isExcludedURI(parameters.getExcludeNamespaceURIs(), childAssoc.getQName().getNamespaceURI())) { - walkNode(childAssoc.getChildRef(), parameters, exporter); + walkNode(childAssoc.getChildRef(), parameters, exporter, false); } if (i == childAssocs.size() - 1 || childAssocs.get(i + 1).getTypeQName().equals(childAssocType) == false) { @@ -463,7 +479,15 @@ public class ExporterComponent } // Signal end of node - exporter.endNode(nodeRef); + // export node as reference to node, or as the actual node + if (exportAsRef) + { + exporter.endReference(nodeRef); + } + else + { + exporter.endNode(nodeRef); + } } /** diff --git a/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java b/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java index 4e8e191bc5..ebbf004c60 100644 --- a/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java +++ b/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java @@ -43,6 +43,7 @@ import org.alfresco.service.cmr.view.ExporterCrawlerParameters; import org.alfresco.service.cmr.view.ExporterException; import org.alfresco.service.cmr.view.ExporterService; import org.alfresco.service.cmr.view.Location; +import org.alfresco.service.cmr.view.ReferenceType; import org.alfresco.service.cmr.view.RepositoryExporterService; import org.alfresco.service.namespace.QName; import org.alfresco.util.ParameterCheck; @@ -276,6 +277,7 @@ public class RepositoryExporterComponent implements RepositoryExporterService parameters.setCrawlAssociations(true); parameters.setCrawlNullProperties(true); parameters.setExcludeNamespaceURIs(new String[] {}); + parameters.setReferenceType(ReferenceType.NODEREF); return parameters; } @@ -294,7 +296,7 @@ public class RepositoryExporterComponent implements RepositoryExporterService public FileExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress) { // create a temporary file to hold the acp export - File tempFile = TempFileProvider.createTempFile("repoExp", "." + ACPExportPackageHandler.ACP_EXTENSION); + File tempFile = TempFileProvider.createTempFile("repoExp" + packageName, "." + ACPExportPackageHandler.ACP_EXTENSION); // create acp export handler around the temp file File dataFile = new File(packageName); @@ -383,6 +385,7 @@ public class RepositoryExporterComponent implements RepositoryExporterService * * @author davidc */ + @SuppressWarnings("unused") private class RepositoryFileExporter implements ExportStore { private TempFileExporter tempFileExporter = new TempFileExporter(); diff --git a/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java b/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java index b828ba3723..e7c7492ab1 100644 --- a/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java +++ b/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java @@ -34,6 +34,7 @@ import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.view.Exporter; import org.alfresco.service.cmr.view.ExporterContext; import org.alfresco.service.cmr.view.ExporterException; +import org.alfresco.service.cmr.view.ReferenceType; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.xml.sax.ContentHandler; @@ -72,6 +73,7 @@ import org.xml.sax.helpers.AttributesImpl; private static final String INHERITPERMISSIONS_LOCALNAME = "inherit"; private static final String REFERENCE_LOCALNAME = "reference"; private static final String PATHREF_LOCALNAME = "pathref"; + private static final String NODEREF_LOCALNAME = "noderef"; private static QName VIEW_QNAME; private static QName VALUES_QNAME; private static QName VALUE_QNAME; @@ -94,6 +96,7 @@ import org.xml.sax.helpers.AttributesImpl; private static QName INHERITPERMISSIONS_QNAME; private static QName REFERENCE_QNAME; private static QName PATHREF_QNAME; + private static QName NODEREF_QNAME; private static final AttributesImpl EMPTY_ATTRIBUTES = new AttributesImpl(); // Service dependencies @@ -107,6 +110,10 @@ import org.xml.sax.helpers.AttributesImpl; private ContentHandler contentHandler; private ExporterContext context; + // Configuration + private ReferenceType referenceType; + + /** * Construct @@ -147,6 +154,18 @@ import org.xml.sax.helpers.AttributesImpl; INHERITPERMISSIONS_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, INHERITPERMISSIONS_LOCALNAME, namespaceService); REFERENCE_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, REFERENCE_LOCALNAME, namespaceService); PATHREF_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, PATHREF_LOCALNAME, namespaceService); + NODEREF_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, NODEREF_LOCALNAME, namespaceService); + } + + + /** + * Set Reference Type to export with + * + * @param referenceType reference type to export + */ + public void setReferenceType(ReferenceType referenceType) + { + this.referenceType = referenceType; } @@ -518,7 +537,7 @@ import org.xml.sax.helpers.AttributesImpl; NodeRef valueNodeRef = (NodeRef)value; if (nodeRef.getStoreRef().equals(valueNodeRef.getStoreRef())) { - Path nodeRefPath = createRelativePath(context.getExportOf(), nodeRef, valueNodeRef); + Path nodeRefPath = createPath(context.getExportOf(), nodeRef, valueNodeRef); value = (nodeRefPath == null) ? null : nodeRefPath.toPrefixString(namespaceService); } } @@ -632,9 +651,24 @@ import org.xml.sax.helpers.AttributesImpl; { try { - Path path = createRelativePath(context.getExportParent(), context.getExportParent(), nodeRef); + // determine format of reference e.g. node or path based + ReferenceType referenceFormat = referenceType; + if (nodeRef.equals(nodeService.getRootNode(nodeRef.getStoreRef()))) + { + referenceFormat = ReferenceType.PATHREF; + } + + // output reference AttributesImpl attrs = new AttributesImpl(); - attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, PATHREF_LOCALNAME, PATHREF_QNAME.toPrefixString(), null, path.toPrefixString(namespaceService)); + if (referenceFormat.equals(ReferenceType.PATHREF)) + { + Path path = createPath(context.getExportParent(), context.getExportParent(), nodeRef); + attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, PATHREF_LOCALNAME, PATHREF_QNAME.toPrefixString(), null, path.toPrefixString(namespaceService)); + } + else + { + attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, NODEREF_LOCALNAME, NODEREF_QNAME.toPrefixString(), null, nodeRef.toString()); + } if (childName != null) { attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, CHILDNAME_LOCALNAME, CHILDNAME_QNAME.toPrefixString(), null, childName.toPrefixString(namespaceService)); @@ -704,7 +738,7 @@ import org.xml.sax.helpers.AttributesImpl; * @param toRef to reference * @return path */ - private Path createRelativePath(NodeRef rootRef, NodeRef fromRef, NodeRef toRef) + private Path createPath(NodeRef rootRef, NodeRef fromRef, NodeRef toRef) { // Check that item exists first if (!nodeService.exists(toRef)) @@ -713,6 +747,14 @@ import org.xml.sax.helpers.AttributesImpl; return null; } + // Check whether item is the root node of the store + // If so, always return absolute path + if (toRef.equals(nodeService.getRootNode(toRef.getStoreRef()))) + { + return nodeService.getPath(toRef); + } + + // construct relative path Path rootPath = createIndexedPath(rootRef, nodeService.getPath(rootRef)); Path fromPath = createIndexedPath(fromRef, nodeService.getPath(fromRef)); Path toPath = createIndexedPath(toRef, nodeService.getPath(toRef)); diff --git a/source/java/org/alfresco/repo/importer/ImportNode.java b/source/java/org/alfresco/repo/importer/ImportNode.java index 28975c559f..d9d72cb155 100644 --- a/source/java/org/alfresco/repo/importer/ImportNode.java +++ b/source/java/org/alfresco/repo/importer/ImportNode.java @@ -74,11 +74,12 @@ public interface ImportNode public Map getProperties(); /** - * Gets all property datatypes for the node + * Gets the property data type * - * @return the property datatypes + * @param propertyName name of property + * @return data type of named property */ - public Map getPropertyDatatypes(); + public DataTypeDefinition getPropertyDataType(QName propertyName); /** * @return the aspects of this node diff --git a/source/java/org/alfresco/repo/importer/ImporterComponent.java b/source/java/org/alfresco/repo/importer/ImporterComponent.java index ff6f384974..58fc891233 100644 --- a/source/java/org/alfresco/repo/importer/ImporterComponent.java +++ b/source/java/org/alfresco/repo/importer/ImporterComponent.java @@ -36,7 +36,6 @@ import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition; import org.alfresco.service.cmr.dictionary.ClassDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; @@ -548,8 +547,9 @@ public class ImporterComponent // import content, if applicable for (Map.Entry property : context.getProperties().entrySet()) { - PropertyDefinition propertyDef = dictionaryService.getProperty(property.getKey()); - if (propertyDef != null && propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) + // filter out content properties (they're imported later) + DataTypeDefinition valueDataType = context.getPropertyDataType(property.getKey()); + if (valueDataType != null && valueDataType.getName().equals(DataTypeDefinition.CONTENT)) { importContent(nodeRef, property.getKey(), (String)property.getValue()); } @@ -627,10 +627,10 @@ public class ImporterComponent private void importContent(NodeRef nodeRef, QName propertyName, String importContentData) { // bind import content data description - DataTypeDefinition dataTypeDef = dictionaryService.getDataType(DataTypeDefinition.CONTENT); importContentData = bindPlaceHolder(importContentData, binding); if (importContentData != null && importContentData.length() > 0) { + DataTypeDefinition dataTypeDef = dictionaryService.getDataType(DataTypeDefinition.CONTENT); ContentData contentData = (ContentData)DefaultTypeConverter.INSTANCE.convert(dataTypeDef, importContentData); String contentUrl = contentData.getContentUrl(); if (contentUrl != null && contentUrl.length() > 0) @@ -898,29 +898,20 @@ public class ImporterComponent private Map bindProperties(ImportNode context) { Map properties = context.getProperties(); - Map datatypes = context.getPropertyDatatypes(); Map boundProperties = new HashMap(properties.size()); for (QName property : properties.keySet()) { - // get property value - Serializable value = properties.get(property); - // get property datatype - DataTypeDefinition valueDataType = datatypes.get(property); - if (valueDataType == null) - { - PropertyDefinition propDef = dictionaryService.getProperty(property); - if (propDef != null) - { - valueDataType = propDef.getDataType(); - } - } + DataTypeDefinition valueDataType = context.getPropertyDataType(property); // filter out content properties (they're imported later) if (valueDataType != null && valueDataType.getName().equals(DataTypeDefinition.CONTENT)) { continue; } + + // get property value + Serializable value = properties.get(property); // bind property value to configuration and convert to appropriate type if (value instanceof Collection) diff --git a/source/java/org/alfresco/repo/importer/ImporterComponentTest.java b/source/java/org/alfresco/repo/importer/ImporterComponentTest.java index f967a46486..27cc0ef246 100644 --- a/source/java/org/alfresco/repo/importer/ImporterComponentTest.java +++ b/source/java/org/alfresco/repo/importer/ImporterComponentTest.java @@ -61,6 +61,7 @@ public class ImporterComponentTest extends BaseSpringTest super.onTearDownInTransaction(); } + public void testImport() throws Exception { diff --git a/source/java/org/alfresco/repo/importer/view/NodeContext.java b/source/java/org/alfresco/repo/importer/view/NodeContext.java index a4c49c1ac5..2e5dde49a4 100644 --- a/source/java/org/alfresco/repo/importer/view/NodeContext.java +++ b/source/java/org/alfresco/repo/importer/view/NodeContext.java @@ -246,7 +246,7 @@ public class NodeContext extends ElementContext PropertyDefinition propDef = getDictionaryService().getProperty(property); // Process Alfresco UUID - if (propDef != null && propDef.getName().equals(ContentModel.PROP_NODE_UUID)) + if (uuid == null && propDef != null && propDef.getName().equals(ContentModel.PROP_NODE_UUID)) { uuid = value; } @@ -311,6 +311,25 @@ public class NodeContext extends ElementContext return nodeProperties; } + /* + * (non-Javadoc) + * @see org.alfresco.repo.importer.ImportNode#getPropertyDataType(org.alfresco.service.namespace.QName) + */ + public DataTypeDefinition getPropertyDataType(QName propertyName) + { + // get property datatype + DataTypeDefinition valueDataType = propertyDatatypes.get(propertyName); + if (valueDataType == null) + { + PropertyDefinition propDef = getDictionaryService().getProperty(propertyName); + if (propDef != null) + { + valueDataType = propDef.getDataType(); + } + } + return valueDataType; + } + /** * Adds an aspect to the node * @@ -517,5 +536,5 @@ public class NodeContext extends ElementContext return null; } } - + } diff --git a/source/java/org/alfresco/service/cmr/view/ExporterCrawlerParameters.java b/source/java/org/alfresco/service/cmr/view/ExporterCrawlerParameters.java index e008b726da..e3b7f7692d 100644 --- a/source/java/org/alfresco/service/cmr/view/ExporterCrawlerParameters.java +++ b/source/java/org/alfresco/service/cmr/view/ExporterCrawlerParameters.java @@ -35,6 +35,7 @@ public class ExporterCrawlerParameters private boolean crawlAssociations = true; private boolean crawlContent = true; private boolean crawlNullProperties = true; + private ReferenceType referenceType = ReferenceType.PATHREF; private String[] excludeNamespaceURIs = new String[] { NamespaceService.REPOSITORY_VIEW_1_0_URI }; @@ -137,7 +138,7 @@ public class ExporterCrawlerParameters { this.crawlNullProperties = crawlNullProperties; } - + /** * Gets the list of namespace URIs to exlude from the Export * @@ -178,4 +179,24 @@ public class ExporterCrawlerParameters this.exportFrom = exportFrom; } + /** + * Gets the format of exported references + * + * @return reference type + */ + public ReferenceType getReferenceType() + { + return referenceType; + } + + /** + * Sets the format of exported references (child and association references) + * + * @param reference type + */ + public void setReferenceType(ReferenceType referenceType) + { + this.referenceType = referenceType; + } + } diff --git a/source/java/org/alfresco/service/cmr/view/ReferenceType.java b/source/java/org/alfresco/service/cmr/view/ReferenceType.java new file mode 100644 index 0000000000..367a1ba7b8 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/view/ReferenceType.java @@ -0,0 +1,29 @@ +/* + * 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.service.cmr.view; + + +/** + * Enumeration of various types of Reference + * + * @author davidc + */ +public enum ReferenceType +{ + NODEREF, + PATHREF +}