diff --git a/source/java/org/alfresco/repo/exporter/ExporterComponent.java b/source/java/org/alfresco/repo/exporter/ExporterComponent.java index 136b3a34c9..4a1a9e99cb 100644 --- a/source/java/org/alfresco/repo/exporter/ExporterComponent.java +++ b/source/java/org/alfresco/repo/exporter/ExporterComponent.java @@ -270,50 +270,52 @@ public class ExporterComponent // Export Nodes // - // determine if root repository node - NodeRef nodeRef = context.getExportOf(); - if (parameters.isCrawlSelf()) + while (context.canRetrieve()) { - // export root node of specified export location - walkStartNamespaces(parameters, exporter); - boolean rootNode = nodeService.getRootNode(nodeRef.getStoreRef()).equals(nodeRef); - walkNode(nodeRef, parameters, exporter, rootNode); - walkEndNamespaces(parameters, exporter); - } - else if (parameters.isCrawlChildNodes()) - { - // export child nodes only - List childAssocs = nodeService.getChildAssocs(nodeRef); - for (ChildAssociationRef childAssoc : childAssocs) + // determine if root repository node + NodeRef nodeRef = context.getExportOf(); + if (parameters.isCrawlSelf()) { + // export root node of specified export location walkStartNamespaces(parameters, exporter); - walkNode(childAssoc.getChildRef(), parameters, exporter, false); + boolean rootNode = nodeService.getRootNode(nodeRef.getStoreRef()).equals(nodeRef); + walkNode(nodeRef, parameters, exporter, rootNode); walkEndNamespaces(parameters, exporter); } - } + else if (parameters.isCrawlChildNodes()) + { + // export child nodes only + List childAssocs = nodeService.getChildAssocs(nodeRef); + for (ChildAssociationRef childAssoc : childAssocs) + { + walkStartNamespaces(parameters, exporter); + walkNode(childAssoc.getChildRef(), parameters, exporter, false); + walkEndNamespaces(parameters, exporter); + } + } - // - // Export Secondary Links between Nodes - // - - for (NodeRef nodeWithAssociations : nodesWithSecondaryLinks.keySet()) - { - walkStartNamespaces(parameters, exporter); - walkNodeSecondaryLinks(nodeWithAssociations, parameters, exporter); - walkEndNamespaces(parameters, exporter); - } + // + // Export Secondary Links between Nodes + // + for (NodeRef nodeWithAssociations : nodesWithSecondaryLinks.keySet()) + { + walkStartNamespaces(parameters, exporter); + walkNodeSecondaryLinks(nodeWithAssociations, parameters, exporter); + walkEndNamespaces(parameters, exporter); + } - // - // Export Associations between Nodes - // + // + // Export Associations between Nodes + // + for (NodeRef nodeWithAssociations : nodesWithAssociations.keySet()) + { + walkStartNamespaces(parameters, exporter); + walkNodeAssociations(nodeWithAssociations, parameters, exporter); + walkEndNamespaces(parameters, exporter); + } - for (NodeRef nodeWithAssociations : nodesWithAssociations.keySet()) - { - walkStartNamespaces(parameters, exporter); - walkNodeAssociations(nodeWithAssociations, parameters, exporter); - walkEndNamespaces(parameters, exporter); + context.setNextValue(); } - exporter.end(); } @@ -807,27 +809,28 @@ public class ExporterComponent boolean isWithin = false; // Current strategy is to determine if node is a child of the root exported node - NodeRef exportRoot = context.getExportOf(); - if (nodeRef.equals(exportRoot) && parameters.isCrawlSelf() == true) + for (NodeRef exportRoot : context.getExportList()) { - // node to export is the root export node (and root is to be exported) - isWithin = true; - } - else - { - // locate export root in primary parent path of node - Path nodePath = nodeService.getPath(nodeRef); - for (int i = nodePath.size() -1; i >= 0; i--) + if (nodeRef.equals(exportRoot) && parameters.isCrawlSelf() == true) { - Path.ChildAssocElement pathElement = (Path.ChildAssocElement)nodePath.get(i); - if (pathElement.getRef().getChildRef().equals(exportRoot)) + // node to export is the root export node (and root is to be exported) + isWithin = true; + } + else + { + // locate export root in primary parent path of node + Path nodePath = nodeService.getPath(nodeRef); + for (int i = nodePath.size() -1; i >= 0; i--) { - isWithin = true; - break; + Path.ChildAssocElement pathElement = (Path.ChildAssocElement)nodePath.get(i); + if (pathElement.getRef().getChildRef().equals(exportRoot)) + { + isWithin = true; + break; + } } } } - return isWithin; } } @@ -838,12 +841,14 @@ public class ExporterComponent */ private class ExporterContextImpl implements ExporterContext { - private NodeRef exportOf; - private NodeRef parent; + private NodeRef[] exportList; + private NodeRef[] parentList; private String exportedBy; private Date exportedDate; private String exporterVersion; + private int index; + /** * Construct * @@ -851,23 +856,49 @@ public class ExporterComponent */ public ExporterContextImpl(ExporterCrawlerParameters parameters) { + index = 0; + // get current user performing export String currentUserName = authenticationService.getCurrentUserName(); exportedBy = (currentUserName == null) ? "unknown" : currentUserName; // get current date exportedDate = new Date(System.currentTimeMillis()); - - // get export of - exportOf = getNodeRef(parameters.getExportFrom()); - - // get export parent - parent = getParent(exportOf, parameters.isCrawlSelf()); + + // get list of exported nodes + exportList = (parameters.getExportFrom() == null) ? null : parameters.getExportFrom().getNodeRefs(); + if (exportList == null) + { + // multi-node export + exportList = new NodeRef[1]; + NodeRef exportOf = getNodeRef(parameters.getExportFrom()); + exportList[0] = exportOf; + } + parentList = new NodeRef[exportList.length]; + for (int i = 0; i < exportList.length; i++) + { + parentList[i] = getParent(exportList[i], parameters.isCrawlSelf()); + } // get exporter version exporterVersion = descriptorService.getServerDescriptor().getVersion(); } + public boolean canRetrieve() + { + return index < exportList.length; + } + + public int setNextValue() + { + return ++index; + } + + public void resetContext() + { + index = 0; + } + /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ExporterContext#getExportedBy() */ @@ -897,7 +928,11 @@ public class ExporterComponent */ public NodeRef getExportOf() { - return exportOf; + if (canRetrieve()) + { + return exportList[index]; + } + return null; } /* @@ -906,9 +941,32 @@ public class ExporterComponent */ public NodeRef getExportParent() { - return parent; + if (canRetrieve()) + { + return parentList[index]; + } + return null; } + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.view.ExporterContext#getExportList() + */ + public NodeRef[] getExportList() + { + return exportList; + } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.view.ExporterContext#getExportParentList() + */ + public NodeRef[] getExportParentList() + { + return parentList; + } + + /** * Get the Node Ref from the specified Location * diff --git a/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java b/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java index 0ae131a259..1dfa11eec8 100644 --- a/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java +++ b/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java @@ -45,6 +45,7 @@ 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.apache.commons.lang.ArrayUtils; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; @@ -212,10 +213,19 @@ import org.xml.sax.helpers.AttributesImpl; // export of contentHandler.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, EXPORTOF_LOCALNAME, EXPORTOF_QNAME.toPrefixString(), EMPTY_ATTRIBUTES); - String path = nodeService.getPath(context.getExportOf()).toPrefixString(namespaceService); - contentHandler.characters(path.toCharArray(), 0, path.length()); + NodeRef[] exportList = context.getExportList(); + int comma = 1; + for(int i=0;i < exportList.length; i++) + { + NodeRef nodeRef = exportList[i]; + String path = nodeService.getPath(nodeRef).toPrefixString(namespaceService); + if (i == exportList.length - 1) + { + comma = 0; + } + contentHandler.characters(ArrayUtils.addAll(path.toCharArray(), ",".toCharArray()), 0, path.length() + comma); + } contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, EXPORTOF_LOCALNAME, EXPORTOF_QNAME.toPrefixString()); - contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, METADATA_LOCALNAME, METADATA_QNAME.toPrefixString()); } catch (SAXException e) @@ -545,7 +555,7 @@ import org.xml.sax.helpers.AttributesImpl; NodeRef valueNodeRef = (NodeRef)value; if (nodeRef.getStoreRef().equals(valueNodeRef.getStoreRef())) { - Path nodeRefPath = createPath(context.getExportOf(), nodeRef, valueNodeRef); + Path nodeRefPath = createPath(context.getExportParent(), nodeRef, valueNodeRef); value = (nodeRefPath == null) ? null : nodeRefPath.toPrefixString(namespaceService); } } @@ -569,12 +579,11 @@ import org.xml.sax.helpers.AttributesImpl; String strValue = (String)DefaultTypeConverter.INSTANCE.convert(String.class, value); if (strValue != null) { - for (int i = 0; i < strValue.length(); i++) - { - char[] temp = new char[]{strValue.charAt(i)}; - contentHandler.characters(temp, 0, 1); - } - + for (int i = 0; i < strValue.length(); i++) + { + char[] temp = new char[]{strValue.charAt(i)}; + contentHandler.characters(temp, 0, 1); + } } // output value wrapper if property data type is any @@ -802,26 +811,33 @@ import org.xml.sax.helpers.AttributesImpl; if (i == rootPath.size()) { // Determine if to node is relative to export tree - i = 0; - while (i < rootPath.size() && i < toPath.size() && rootPath.get(i).equals(toPath.get(i))) + for (NodeRef nodeRef : context.getExportParentList()) { - i++; - } - if (i == rootPath.size()) - { - // build relative path between from and to - relativePath = new Path(); - for (int p = 0; p < fromPath.size() - i; p++) + int j = 0; + Path tryPath = createIndexedPath(nodeRef, nodeService.getPath(nodeRef)); + while (j < tryPath.size() && j < toPath.size() && tryPath.get(j).equals(toPath.get(j))) { - relativePath.append(new Path.ParentElement()); + j++; } - if (i < toPath.size()) + if (j == tryPath.size()) { - relativePath.append(toPath.subPath(i, toPath.size() -1)); + // build relative path between from and to + relativePath = new Path(); + for (int p = 0; p < fromPath.size() - i; p++) + { + relativePath.append(new Path.ParentElement()); + } + if (j < toPath.size()) + { + relativePath.append(toPath.subPath(j, toPath.size() - 1)); + } + + break; } } } } + if (relativePath == null) { diff --git a/source/java/org/alfresco/repo/importer/ImporterComponent.java b/source/java/org/alfresco/repo/importer/ImporterComponent.java index 684be617e7..4309b2386c 100644 --- a/source/java/org/alfresco/repo/importer/ImporterComponent.java +++ b/source/java/org/alfresco/repo/importer/ImporterComponent.java @@ -521,14 +521,17 @@ public class ImporterComponent public void importMetaData(Map properties) { // Determine if we're importing a complete repository - String path = properties.get(QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "exportOf")); - if (path != null && path.equals("/")) + String complexPath = properties.get(QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "exportOf")); + for (String path : complexPath.split(",")) { - // Only allow complete repository import into root - NodeRef storeRootRef = nodeService.getRootNode(rootRef.getStoreRef()); - if (!storeRootRef.equals(rootRef)) + if (path != null && path.equals("/")) { - throw new ImporterException("A complete repository package cannot be imported here"); + // Only allow complete repository import into root + NodeRef storeRootRef = nodeService.getRootNode(rootRef.getStoreRef()); + if (!storeRootRef.equals(rootRef)) + { + throw new ImporterException("A complete repository package cannot be imported here"); + } } } } diff --git a/source/java/org/alfresco/service/cmr/view/ExporterContext.java b/source/java/org/alfresco/service/cmr/view/ExporterContext.java index 046a5ef3dc..679d736f21 100644 --- a/source/java/org/alfresco/service/cmr/view/ExporterContext.java +++ b/source/java/org/alfresco/service/cmr/view/ExporterContext.java @@ -1,20 +1,102 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ package org.alfresco.service.cmr.view; import java.util.Date; import org.alfresco.service.cmr.repository.NodeRef; + public interface ExporterContext { - + /** + * Gets who initiated the export + * + * @return + */ public String getExportedBy(); + /** + * Gets date at which export occured + * + * @return + */ public Date getExportedDate(); + /** + * Gets version number of exporter + * + * @return + */ public String getExporterVersion(); + /** + * Gets active node for export + * + * @return NodeRef + */ public NodeRef getExportOf(); + /** + * Gets parent of exporting node + * + * @return NodeRef + */ public NodeRef getExportParent(); + /** + * Gets list of nodes for export + * + * @return NodeRef[] + */ + public NodeRef[] getExportList(); + + /** + * Gets list of parents for exporting nodes + * + * @return NodeRef[] + */ + public NodeRef[] getExportParentList(); + + /** + * Return true if there is active node for export + * + * @return + */ + public boolean canRetrieve(); + + /** + * Set next active node from list + * + * @return + */ + public int setNextValue(); + + /** + * Set first active node + */ + public void resetContext(); + } diff --git a/source/java/org/alfresco/service/cmr/view/Location.java b/source/java/org/alfresco/service/cmr/view/Location.java index 7eafc1ff72..720902fae2 100644 --- a/source/java/org/alfresco/service/cmr/view/Location.java +++ b/source/java/org/alfresco/service/cmr/view/Location.java @@ -38,6 +38,7 @@ public class Location { private StoreRef storeRef = null; private NodeRef nodeRef = null; + private NodeRef[] nodeRefs = null; private String path = null; private QName childAssocType = null; @@ -54,6 +55,19 @@ public class Location this.nodeRef = nodeRef; } + /** + * Construct + * + * @param nodeRefs + */ + public Location(NodeRef[] nodeRefs) + { + ParameterCheck.mandatory("Node Refs", nodeRefs); + this.storeRef = nodeRefs[0].getStoreRef(); + this.nodeRefs = nodeRefs; + } + + /** * Construct * @@ -81,6 +95,20 @@ public class Location return nodeRef; } + /** + * @return the node refs + */ + public NodeRef[] getNodeRefs() + { + return nodeRefs; + } + + public void setNodeRefs(NodeRef[] nodeRefs) + { + this.nodeRef = null; + this.nodeRefs = nodeRefs; + } + /** * Sets the location to the specified path *