diff --git a/.externalToolBuilders/JibX.launch b/.externalToolBuilders/JibX.launch index e01ac9f62b..86f6480230 100644 --- a/.externalToolBuilders/JibX.launch +++ b/.externalToolBuilders/JibX.launch @@ -2,21 +2,21 @@ - + - - + + - + - + diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml index b8c14a0773..48c71437c9 100644 --- a/config/alfresco/action-services-context.xml +++ b/config/alfresco/action-services-context.xml @@ -321,6 +321,15 @@ - - + + + + + false + + + + + + diff --git a/config/alfresco/application-context.xml b/config/alfresco/application-context.xml index e61af3ca89..28052756d1 100644 --- a/config/alfresco/application-context.xml +++ b/config/alfresco/application-context.xml @@ -19,6 +19,7 @@ + diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index 576bb51e1e..e9a7ba5fff 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -53,6 +53,17 @@ + + + + + / + alfresco/bootstrap/lightWeightVersionStore.xml + + + + + @@ -91,11 +102,6 @@ - - diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml index 49cdb2b876..eec7adbff8 100644 --- a/config/alfresco/core-services-context.xml +++ b/config/alfresco/core-services-context.xml @@ -324,21 +324,6 @@ - - - - - - - - - - - - - - - @@ -618,171 +603,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${server.transaction.allow-writes} - - - - - - - ${alfresco_user_store.store} - - - - ${alfresco_user_store.system_container.childname} - ${alfresco_user_store.user_container.childname} - ${alfresco_user_store.authorities_container.childname} - - - - - - - ${system.store} - - - - ${spaces.store} - - - - - ${version.major} - ${version.minor} - ${version.revision} - ${version.label} - ${version.schema} - ${system.descriptor.childname} - ${system.descriptor.current.childname} - - - - - - - ${spaces.store} - - - - ${spaces.company_home.childname} - ${spaces.guest_home.childname} - ${system.system_container.childname} - ${system.people_container.childname} - ${spaces.dictionary.childname} - ${spaces.templates.childname} - ${spaces.templates.content.childname} - ${spaces.templates.email.childname} - ${spaces.savedsearches.childname} - - - - - - - workspace://lightWeightVersionStore - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config/alfresco/extension/restore-context.xml.sample b/config/alfresco/extension/restore-context.xml.sample new file mode 100644 index 0000000000..bdfae1b719 --- /dev/null +++ b/config/alfresco/extension/restore-context.xml.sample @@ -0,0 +1,54 @@ + + + + + + + + + + / + alfresco/extension/restore/export_users.acp + + + + true + + + + + + + / + alfresco/extension/restore/export_system.acp + + + + true + + + + + + + / + alfresco/extension/restore/export_versions.acp + + + + true + + + + + + + / + alfresco/extension/restore/export_spaces.acp + + + + true + + + diff --git a/config/alfresco/import-export-context.xml b/config/alfresco/import-export-context.xml new file mode 100644 index 0000000000..c5bc260b82 --- /dev/null +++ b/config/alfresco/import-export-context.xml @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system://system + system + + + ${alfresco_user_store.store} + users + + + ${spaces.store} + spaces + + + workspace://lightWeightVersionStore + versions + + + + + + + + + + + + + + + + + + + + + + + + + + ${server.transaction.allow-writes} + + + + + + + + + + + + ${alfresco_user_store.store} + + + + ${alfresco_user_store.system_container.childname} + ${alfresco_user_store.user_container.childname} + ${alfresco_user_store.authorities_container.childname} + + + + + + + ${system.store} + + + + ${spaces.store} + + + + + ${version.major} + ${version.minor} + ${version.revision} + ${version.label} + ${version.schema} + ${system.descriptor.childname} + ${system.descriptor.current.childname} + + + + + + + ${spaces.store} + + + + ${spaces.company_home.childname} + ${spaces.guest_home.childname} + ${system.system_container.childname} + ${system.people_container.childname} + ${spaces.dictionary.childname} + ${spaces.templates.childname} + ${spaces.templates.content.childname} + ${spaces.templates.email.childname} + ${spaces.savedsearches.childname} + + + + + + + workspace://lightWeightVersionStore + + + + diff --git a/config/alfresco/messages/action-config.properties b/config/alfresco/messages/action-config.properties index 38f04f8aca..33421691b5 100644 --- a/config/alfresco/messages/action-config.properties +++ b/config/alfresco/messages/action-config.properties @@ -69,5 +69,6 @@ export.title=Export a Space export.description=Exports a Space and optionally it's children to an Alfresco export package. export.package.description=Alfresco content package for Space ''{0}''. export.root.package.description=Alfresco content package for complete Repository. +export.store.package.description=Alfresco export of store ''{0}''. export.package.error=Failed to find temporary file for export diff --git a/source/java/org/alfresco/repo/action/executer/RepositoryExporterActionExecuter.java b/source/java/org/alfresco/repo/action/executer/RepositoryExporterActionExecuter.java new file mode 100644 index 0000000000..c6902c9e27 --- /dev/null +++ b/source/java/org/alfresco/repo/action/executer/RepositoryExporterActionExecuter.java @@ -0,0 +1,75 @@ +/* + * 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.action.executer; + +import java.util.List; + +import org.alfresco.repo.action.ParameterDefinitionImpl; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.view.RepositoryExporterService; + +/** + * Repository Exporter action executor + * + * @author davidc + */ +public class RepositoryExporterActionExecuter extends ActionExecuterAbstractBase +{ + public static final String NAME = "repository-export"; + public static final String PARAM_PACKAGE_NAME = "package-name"; + public static final String PARAM_DESTINATION_FOLDER = "destination"; + + /** + * The exporter service + */ + private RepositoryExporterService exporterService; + + /** + * Sets the ExporterService to use + * + * @param exporterService The ExporterService + */ + public void setRepositoryExporterService(RepositoryExporterService exporterService) + { + this.exporterService = exporterService; + } + + /** + * @see org.alfresco.repo.action.executer.ActionExecuter#execute(org.alfresco.repo.ref.NodeRef, org.alfresco.repo.ref.NodeRef) + */ + public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) + { + String packageName = (String)ruleAction.getParameterValue(PARAM_PACKAGE_NAME); + NodeRef repoDestination = (NodeRef)ruleAction.getParameterValue(PARAM_DESTINATION_FOLDER); + exporterService.export(repoDestination, packageName); + } + + /** + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List) + */ + protected void addParameterDefintions(List paramList) + { + paramList.add(new ParameterDefinitionImpl(PARAM_PACKAGE_NAME, DataTypeDefinition.TEXT, true, + getParamDisplayLabel(PARAM_PACKAGE_NAME))); + paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF, true, + getParamDisplayLabel(PARAM_DESTINATION_FOLDER))); + } + +} diff --git a/source/java/org/alfresco/repo/content/RoutingContentService.java b/source/java/org/alfresco/repo/content/RoutingContentService.java index 30b69f6352..bb9af1060d 100644 --- a/source/java/org/alfresco/repo/content/RoutingContentService.java +++ b/source/java/org/alfresco/repo/content/RoutingContentService.java @@ -17,6 +17,7 @@ package org.alfresco.repo.content; import java.io.Serializable; +import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -241,17 +242,28 @@ public class RoutingContentService implements ContentService { // get the property value ContentData contentData = null; + Serializable propValue = nodeService.getProperty(nodeRef, propertyQName); + if (propValue instanceof Collection) + { + Collection colPropValue = (Collection)propValue; + if (colPropValue.size() > 0) + { + propValue = (Serializable)colPropValue.iterator().next(); + } + } if (propValue instanceof ContentData) { contentData = (ContentData)propValue; } - // ensure that the node property is of type content if (contentData == null) { + // if no value or a value other content, and a property definition has been provided, ensure that it's CONTENT or ANY PropertyDefinition contentPropDef = dictionaryService.getProperty(propertyQName); - if (contentPropDef == null || !(contentPropDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))) + if (contentPropDef != null && + (!(contentPropDef.getDataType().getName().equals(DataTypeDefinition.CONTENT) || + contentPropDef.getDataType().getName().equals(DataTypeDefinition.ANY)))) { throw new InvalidTypeException("The node property must be of type content: \n" + " node: " + nodeRef + "\n" + diff --git a/source/java/org/alfresco/repo/exporter/ChainedExporter.java b/source/java/org/alfresco/repo/exporter/ChainedExporter.java index 9116a9c2a7..0be8ac7ecf 100644 --- a/source/java/org/alfresco/repo/exporter/ChainedExporter.java +++ b/source/java/org/alfresco/repo/exporter/ChainedExporter.java @@ -258,22 +258,22 @@ import org.alfresco.service.namespace.QName; /* (non-Javadoc) * @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable) */ - public void value(NodeRef nodeRef, QName property, Object value) + public void value(NodeRef nodeRef, QName property, Object value, int index) { for (Exporter exporter : exporters) { - exporter.value(nodeRef, property, value); + exporter.value(nodeRef, property, value, index); } } /* (non-Javadoc) * @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream) */ - public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData) + public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index) { for (Exporter exporter : exporters) { - exporter.content(nodeRef, property, content, contentData); + exporter.content(nodeRef, property, content, contentData, index); } } diff --git a/source/java/org/alfresco/repo/exporter/ExporterComponent.java b/source/java/org/alfresco/repo/exporter/ExporterComponent.java index af994ab364..90e7a75965 100644 --- a/source/java/org/alfresco/repo/exporter/ExporterComponent.java +++ b/source/java/org/alfresco/repo/exporter/ExporterComponent.java @@ -215,7 +215,7 @@ public class ExporterComponent try { XMLWriter writer = new XMLWriter(viewWriter, format); - return new ViewXMLExporter(namespaceService, nodeService, dictionaryService, permissionService, writer); + return new ViewXMLExporter(namespaceService, nodeService, searchService, dictionaryService, permissionService, writer); } catch (UnsupportedEncodingException e) { @@ -399,14 +399,18 @@ public class ExporterComponent if (value instanceof Collection) { + exporter.startValueCollection(nodeRef, property); + int index = 0; for (Object valueInCollection : (Collection)value) { - walkProperty(nodeRef, property, valueInCollection, parameters, exporter); + walkProperty(nodeRef, property, valueInCollection, index, parameters, exporter); + index++; } + exporter.endValueCollection(nodeRef, property); } else { - walkProperty(nodeRef, property, value, parameters, exporter); + walkProperty(nodeRef, property, value, -1, parameters, exporter); } // end export of property @@ -468,10 +472,11 @@ public class ExporterComponent * @param nodeRef * @param property * @param value + * @param index * @param parameters * @param exporter */ - private void walkProperty(NodeRef nodeRef, QName property, Object value, ExporterCrawlerParameters parameters, Exporter exporter) + private void walkProperty(NodeRef nodeRef, QName property, Object value, int index, ExporterCrawlerParameters parameters, Exporter exporter) { // determine data type of value PropertyDefinition propDef = dictionaryService.getProperty(property); @@ -495,12 +500,12 @@ public class ExporterComponent // Export non content data types try { - exporter.value(nodeRef, property, value); + exporter.value(nodeRef, property, value, index); } catch(TypeConversionException e) { exporter.warning("Value of property " + property + " could not be converted to xml string"); - exporter.value(nodeRef, property, value.toString()); + exporter.value(nodeRef, property, value.toString(), index); } } else @@ -512,7 +517,7 @@ public class ExporterComponent // export an empty url for the content ContentData contentData = (ContentData)value; ContentData noContentURL = new ContentData("", contentData.getMimetype(), contentData.getSize(), contentData.getEncoding()); - exporter.content(nodeRef, property, null, noContentURL); + exporter.content(nodeRef, property, null, noContentURL, index); exporter.warning("Skipped content for property " + property + " on node " + nodeRef); } else @@ -520,7 +525,7 @@ public class ExporterComponent InputStream inputStream = reader.getContentInputStream(); try { - exporter.content(nodeRef, property, inputStream, reader.getContentData()); + exporter.content(nodeRef, property, inputStream, reader.getContentData(), index); } finally { diff --git a/source/java/org/alfresco/repo/exporter/ExporterComponentTest.java b/source/java/org/alfresco/repo/exporter/ExporterComponentTest.java index c9fc188f1e..791e9aeb56 100644 --- a/source/java/org/alfresco/repo/exporter/ExporterComponentTest.java +++ b/source/java/org/alfresco/repo/exporter/ExporterComponentTest.java @@ -160,12 +160,12 @@ public class ExporterComponentTest extends BaseSpringTest // System.out.println("TestProgress: end value collection: node " + nodeRef + " , property " + property); } - public void value(NodeRef nodeRef, QName property, Object value) + public void value(NodeRef nodeRef, QName property, Object value, int index) { // System.out.println("TestProgress: single value " + value); } - public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData) + public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index) { // System.out.println("TestProgress: content stream "); } diff --git a/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java b/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java new file mode 100644 index 0000000000..4e8e191bc5 --- /dev/null +++ b/source/java/org/alfresco/repo/exporter/RepositoryExporterComponent.java @@ -0,0 +1,420 @@ +/* + * 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.exporter; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.alfresco.i18n.I18NUtil; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.service.cmr.model.FileExistsException; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.MimetypeService; +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.view.Exporter; +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.RepositoryExporterService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ParameterCheck; +import org.alfresco.util.TempFileProvider; + + +/** + * Full Repository Export Service + * + * @author davidc + */ +public class RepositoryExporterComponent implements RepositoryExporterService +{ + private static final String STOREREF_KEY = "storeRef"; + private static final String PACKAGENAME_KEY = "packageName"; + + // component dependencies + private ExporterService exporterService; + private MimetypeService mimetypeService; + private FileFolderService fileFolderService; + private NodeService nodeService; + private List exportStores; + + + public void setExporterService(ExporterService exporterService) + { + this.exporterService = exporterService; + } + + public void setMimetypeService(MimetypeService mimetypeService) + { + this.mimetypeService = mimetypeService; + } + + public void setFileFolderService(FileFolderService fileFolderService) + { + this.fileFolderService = fileFolderService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setStores(List exportStores) + { + this.exportStores = exportStores; + } + + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.view.RepositoryExporterService#export() + */ + public FileExportHandle[] export(String packageName) + { + List exportHandles = exportStores(exportStores, packageName, new TempFileExporter()); + return exportHandles.toArray(new FileExportHandle[exportHandles.size()]); + } + + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.view.RepositoryExporterService#export(java.io.File) + */ + public FileExportHandle[] export(File directoryDestination, String packageName) + { + ParameterCheck.mandatory("directoryDestination", directoryDestination); + if (!directoryDestination.isDirectory()) + { + throw new ExporterException("Export location " + directoryDestination.getAbsolutePath() + " is not a directory"); + } + + List exportHandles = exportStores(exportStores, packageName, new FileExporter(directoryDestination)); + return exportHandles.toArray(new FileExportHandle[exportHandles.size()]); + } + + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.view.RepositoryExporterService#export(org.alfresco.service.cmr.repository.NodeRef) + */ + public RepositoryExportHandle[] export(NodeRef repositoryDestination, String packageName) + { + ParameterCheck.mandatory("repositoryDestination", repositoryDestination); + FileInfo destInfo = fileFolderService.getFileInfo(repositoryDestination); + if (destInfo == null || !destInfo.isFolder()) + { + throw new ExporterException("Repository destination " + repositoryDestination + " is not a folder."); + } + + List exportHandles = exportStores(exportStores, packageName, new TempFileExporter()); + List repoExportHandles = new ArrayList(exportHandles.size()); + for (FileExportHandle exportHandle : exportHandles) + { + String description = I18NUtil.getMessage("export.store.package.description", new Object[] { exportHandle.storeRef.getIdentifier() }); + NodeRef repoExportFile = addExportFile(repositoryDestination, exportHandle.packageName, description, exportHandle.exportFile); + RepositoryExportHandle handle = new RepositoryExportHandle(); + handle.storeRef = exportHandle.storeRef; + handle.packageName = exportHandle.packageName; + handle.exportFile = repoExportFile; + repoExportHandles.add(handle); + } + + return repoExportHandles.toArray(new RepositoryExportHandle[repoExportHandles.size()]); + } + + + /** + * Add a file system based .acp file into the repository + * + * @param repoDestination location within repository to place .acp file + * @param packageName acp package name + * @param packageDescription acp package description + * @param exportFile the .acp file + * @return node reference to import .acp file + */ + private NodeRef addExportFile(NodeRef repoDestination, String packageName, String packageDescription, File exportFile) + { + // + // import temp file into repository + // + + // determine if file already exists + String fileName = packageName + "." + ACPExportPackageHandler.ACP_EXTENSION; + List paths = new ArrayList(); + paths.add(fileName); + try + { + FileInfo fileInfo = fileFolderService.resolveNamePath(repoDestination, paths); + // Note: file already exists - delete + fileFolderService.delete(fileInfo.getNodeRef()); + } + catch (org.alfresco.service.cmr.model.FileNotFoundException e) + { + // Note: file does not exist - no need to delete + } + + // create acp file in repository + NodeRef exportFileNodeRef = null; + try + { + FileInfo fileInfo = fileFolderService.create(repoDestination, fileName, ContentModel.TYPE_CONTENT); + ContentWriter writer = fileFolderService.getWriter(fileInfo.getNodeRef()); + writer.setMimetype(MimetypeMap.MIMETYPE_ACP); + writer.putContent(exportFile); + exportFileNodeRef = fileInfo.getNodeRef(); + + // add a title for Web Client viewing + Map titledProps = new HashMap(3, 1.0f); + titledProps.put(ContentModel.PROP_TITLE, packageName); + titledProps.put(ContentModel.PROP_DESCRIPTION, packageDescription); + nodeService.addAspect(exportFileNodeRef, ContentModel.ASPECT_TITLED, titledProps); + + } + catch (FileExistsException e) + { + // Note: shouldn't get here + } + + return exportFileNodeRef; + } + + + /** + * Contract for exporting a store + * + * @author davidc + * + * @param + */ + private interface ExportStore + { + public ExportHandleType exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress); + } + + + /** + * Enumerate list of pre-configured Stores and export one by one + * + * @param type of export file handle + * @param stores the list of stores to export + * @param exportStore the exporter call-back for handling the actual export + * @return the list export file handles + */ + private List exportStores(List stores, String packageName, ExportStore exportStore) + { + List exportHandles = new ArrayList(stores.size()); + for (Properties store : stores) + { + // retrieve store reference to export + String storeRefStr = (String)store.get(STOREREF_KEY); + if (storeRefStr == null || storeRefStr.length() == 0) + { + throw new ExporterException("Store Reference has not been provided."); + } + StoreRef storeRef = new StoreRef(storeRefStr); + + // retrieve package name to export into + String storePackageName = (String)store.get(PACKAGENAME_KEY); + if (storePackageName == null || storePackageName.length() == 0) + { + storePackageName = storeRef.getIdentifier(); + } + String completePackageName = (packageName == null) ? storePackageName : packageName + "_" + storePackageName; + + // now export + // NOTE: For now, do not provide exporter progress + ExporterCrawlerParameters exportParameters = getExportParameters(storeRef); + ExportHandleType exportHandle = exportStore.exportStore(exportParameters, completePackageName, null); + exportHandles.add(exportHandle); + } + + return exportHandles; + } + + + /** + * Get export parameters for exporting a complete store + * + * @param storeRef store reference to export + * @return the parameters for exporting the complete store + */ + private ExporterCrawlerParameters getExportParameters(StoreRef storeRef) + { + ExporterCrawlerParameters parameters = new ExporterCrawlerParameters(); + parameters.setExportFrom(new Location(storeRef)); + parameters.setCrawlSelf(true); + parameters.setCrawlChildNodes(true); + parameters.setCrawlContent(true); + parameters.setCrawlAssociations(true); + parameters.setCrawlNullProperties(true); + parameters.setExcludeNamespaceURIs(new String[] {}); + return parameters; + } + + + /** + * Export a Store to a temporary file + * + * @author davidc + */ + private class TempFileExporter implements ExportStore + { + /* + * (non-Javadoc) + * @see org.alfresco.repo.exporter.RepositoryExporterComponent.ExportStore#exportStore(org.alfresco.service.cmr.view.ExporterCrawlerParameters, java.lang.String, org.alfresco.service.cmr.view.Exporter) + */ + 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); + + // create acp export handler around the temp file + File dataFile = new File(packageName); + File contentDir = new File(packageName); + try + { + OutputStream outputStream = new FileOutputStream(tempFile); + ACPExportPackageHandler acpHandler = new ACPExportPackageHandler(outputStream, dataFile, contentDir, mimetypeService); + + // export the store + exporterService.exportView(acpHandler, exportParameters, progress); + } + catch(FileNotFoundException e) + { + tempFile.delete(); + throw new ExporterException("Failed to create temporary file for holding export of store " + exportParameters.getExportFrom().getStoreRef()); + } + + // return handle onto temp file + FileExportHandle handle = new FileExportHandle(); + handle.storeRef = exportParameters.getExportFrom().getStoreRef(); + handle.packageName = packageName; + handle.exportFile = tempFile; + return handle; + }; + }; + + + /** + * Export a Store to a file in a specified folder + * + * @author davidc + */ + private class FileExporter implements ExportStore + { + private File directoryDestination; + + /** + * Construct + * + * @param directoryDestination destination file system folder to create export file + */ + public FileExporter(File directoryDestination) + { + this.directoryDestination = directoryDestination; + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.exporter.RepositoryExporterComponent.ExportStore#exportStore(org.alfresco.service.cmr.view.ExporterCrawlerParameters, java.lang.String, org.alfresco.service.cmr.view.Exporter) + */ + public FileExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress) + { + // create a file to hold the acp export + File file = new File(directoryDestination, packageName + "." + ACPExportPackageHandler.ACP_EXTENSION); + + // create acp export handler around the temp file + File dataFile = new File(packageName); + File contentDir = new File(packageName); + try + { + OutputStream outputStream = new FileOutputStream(file); + ACPExportPackageHandler acpHandler = new ACPExportPackageHandler(outputStream, dataFile, contentDir, mimetypeService); + + // export the store + exporterService.exportView(acpHandler, exportParameters, progress); + } + catch(FileNotFoundException e) + { + file.delete(); + throw new ExporterException("Failed to create file " + file.getAbsolutePath() + " for holding the export of store " + exportParameters.getExportFrom().getStoreRef()); + } + + // return handle onto temp file + FileExportHandle handle = new FileExportHandle(); + handle.storeRef = exportParameters.getExportFrom().getStoreRef(); + handle.packageName = packageName; + handle.exportFile = file; + return handle; + }; + }; + + + /** + * Export a store to Repository File + * + * @author davidc + */ + private class RepositoryFileExporter implements ExportStore + { + private TempFileExporter tempFileExporter = new TempFileExporter(); + private NodeRef repoDestination; + + /** + * Construct + * + * @param repoDestination destination within repository to create export file + */ + public RepositoryFileExporter(NodeRef repoDestination) + { + this.repoDestination = repoDestination; + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.exporter.RepositoryExporterComponent.ExportStore#exportStore(org.alfresco.service.cmr.view.ExporterCrawlerParameters, java.lang.String, org.alfresco.service.cmr.view.Exporter) + */ + public RepositoryExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress) + { + // export acp to temporary file + FileExportHandle tempFile = tempFileExporter.exportStore(exportParameters, packageName, progress); + + String description = I18NUtil.getMessage("export.store.package.description", new Object[] { tempFile.storeRef.getIdentifier() }); + NodeRef repoExportFile = addExportFile(repoDestination, packageName, description, tempFile.exportFile); + RepositoryExportHandle handle = new RepositoryExportHandle(); + handle.storeRef = exportParameters.getExportFrom().getStoreRef(); + handle.packageName = packageName; + handle.exportFile = repoExportFile; + return handle; + } + }; + +} diff --git a/source/java/org/alfresco/repo/exporter/RepositoryExporterComponentTest.java b/source/java/org/alfresco/repo/exporter/RepositoryExporterComponentTest.java new file mode 100644 index 0000000000..1172051986 --- /dev/null +++ b/source/java/org/alfresco/repo/exporter/RepositoryExporterComponentTest.java @@ -0,0 +1,94 @@ +/* + * 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.exporter; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.model.FileFolderService; +import org.alfresco.service.cmr.model.FileInfo; +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.view.RepositoryExporterService; +import org.alfresco.service.cmr.view.RepositoryExporterService.FileExportHandle; +import org.alfresco.service.cmr.view.RepositoryExporterService.RepositoryExportHandle; +import org.alfresco.util.BaseSpringTest; + + +public class RepositoryExporterComponentTest extends BaseSpringTest +{ + private RepositoryExporterService repositoryService; + private AuthenticationComponent authenticationComponent; + private NodeService nodeService; + private FileFolderService fileFolderService; + + + @Override + protected void onSetUpInTransaction() throws Exception + { + this.nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName()); + this.fileFolderService = (FileFolderService)applicationContext.getBean(ServiceRegistry.FILE_FOLDER_SERVICE.getLocalName()); + this.repositoryService = (RepositoryExporterService)applicationContext.getBean("repositoryExporterComponent"); + this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent"); + this.authenticationComponent.setSystemUserAsCurrentUser(); + } + + @Override + protected void onTearDownInTransaction() throws Exception + { + authenticationComponent.clearCurrentSecurityContext(); + super.onTearDownInTransaction(); + } + + + public void testDummy() + { + } + + public void xtestTempFileExport() + throws Exception + { + FileExportHandle[] handles = repositoryService.export("test"); + assertNotNull(handles); + assertEquals(4, handles.length); + for (FileExportHandle tempFile : handles) + { + assertTrue(tempFile.exportFile.exists()); + } + } + + public void xtestRepositoryExport() + throws Exception + { + // Create a temp store to hold exports + StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis()); + NodeRef rootNode = nodeService.getRootNode(storeRef); + FileInfo container = fileFolderService.create(rootNode, "export", ContentModel.TYPE_FOLDER); + + // Export stores + RepositoryExportHandle[] handles = repositoryService.export(container.getNodeRef(), "test"); + assertNotNull(handles); + assertEquals(4, handles.length); + for (RepositoryExportHandle handle : handles) + { + assertTrue(nodeService.exists(handle.exportFile)); + } + + setComplete(); + } + +} diff --git a/source/java/org/alfresco/repo/exporter/URLExporter.java b/source/java/org/alfresco/repo/exporter/URLExporter.java index 644483ed92..afa1349c88 100644 --- a/source/java/org/alfresco/repo/exporter/URLExporter.java +++ b/source/java/org/alfresco/repo/exporter/URLExporter.java @@ -204,19 +204,19 @@ import org.alfresco.util.ParameterCheck; /* (non-Javadoc) * @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable) */ - public void value(NodeRef nodeRef, QName property, Object value) + public void value(NodeRef nodeRef, QName property, Object value, int index) { - exporter.value(nodeRef, property, value); + exporter.value(nodeRef, property, value, index); } /* (non-Javadoc) * @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream) */ - public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData) + public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index) { // Handle the stream by converting it to a URL and export the URL ContentData exportedContentData = streamHandler.exportContent(content, contentData); - value(nodeRef, property, exportedContentData); + value(nodeRef, property, exportedContentData, index); } /* (non-Javadoc) diff --git a/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java b/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java index d6674f3bee..b828ba3723 100644 --- a/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java +++ b/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java @@ -17,7 +17,7 @@ package org.alfresco.repo.exporter; import java.io.InputStream; -import java.util.Collection; +import java.util.List; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; @@ -28,6 +28,7 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.view.Exporter; @@ -98,6 +99,7 @@ import org.xml.sax.helpers.AttributesImpl; // Service dependencies private NamespaceService namespaceService; private NodeService nodeService; + private SearchService searchService; private DictionaryService dictionaryService; private PermissionService permissionService; @@ -113,11 +115,12 @@ import org.xml.sax.helpers.AttributesImpl; * @param nodeService node service * @param contentHandler content handler */ - ViewXMLExporter(NamespaceService namespaceService, NodeService nodeService, + ViewXMLExporter(NamespaceService namespaceService, NodeService nodeService, SearchService searchService, DictionaryService dictionaryService, PermissionService permissionService, ContentHandler contentHandler) { this.namespaceService = namespaceService; this.nodeService = nodeService; + this.searchService = searchService; this.dictionaryService = dictionaryService; this.permissionService = permissionService; this.contentHandler = contentHandler; @@ -492,7 +495,7 @@ import org.xml.sax.helpers.AttributesImpl; /* (non-Javadoc) * @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable) */ - public void value(NodeRef nodeRef, QName property, Object value) + public void value(NodeRef nodeRef, QName property, Object value, int index) { try { @@ -512,12 +515,16 @@ import org.xml.sax.helpers.AttributesImpl; // convert node references to paths if (value instanceof NodeRef) { - Path nodeRefPath = createRelativePath(context.getExportOf(), nodeRef, (NodeRef)value); - value = (nodeRefPath == null) ? null : nodeRefPath.toPrefixString(namespaceService); + NodeRef valueNodeRef = (NodeRef)value; + if (nodeRef.getStoreRef().equals(valueNodeRef.getStoreRef())) + { + Path nodeRefPath = createRelativePath(context.getExportOf(), nodeRef, valueNodeRef); + value = (nodeRefPath == null) ? null : nodeRefPath.toPrefixString(namespaceService); + } } - // output value wrapper if value is null or property data type is ANY - if (value == null || valueDataType != null) + // output value wrapper if value is null or property data type is ANY or value is part of collection + if (value == null || valueDataType != null || index != -1) { AttributesImpl attrs = new AttributesImpl(); if (value == null) @@ -539,7 +546,7 @@ import org.xml.sax.helpers.AttributesImpl; } // output value wrapper if property data type is any - if (value == null || valueDataType != null) + if (value == null || valueDataType != null || index != -1) { contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME)); } @@ -550,74 +557,10 @@ import org.xml.sax.helpers.AttributesImpl; } } - /* (non-Javadoc) - * @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.util.Collection) - */ - public void value(NodeRef nodeRef, QName property, Collection values) - { - try - { - PropertyDefinition propDef = dictionaryService.getProperty(property); - DataTypeDefinition dataTypeDef = (propDef == null) ? null : propDef.getDataType(); - - // start collection - contentHandler.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUES_LOCALNAME, toPrefixString(VALUES_QNAME), EMPTY_ATTRIBUTES); - - for (Object value : values) - { - // determine data type of value - QName valueDataType = null; - if (dataTypeDef == null || dataTypeDef.getName().equals(DataTypeDefinition.ANY)) - { - dataTypeDef = (value == null) ? null : dictionaryService.getDataType(value.getClass()); - if (dataTypeDef != null) - { - valueDataType = dataTypeDef.getName(); - } - } - - // output value wrapper with datatype - AttributesImpl attrs = new AttributesImpl(); - if (value == null) - { - attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_PREFIX, ISNULL_LOCALNAME, ISNULL_QNAME.toPrefixString(), null, "true"); - } - if (valueDataType != null) - { - attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_PREFIX, DATATYPE_LOCALNAME, DATATYPE_QNAME.toPrefixString(), null, toPrefixString(valueDataType)); - } - contentHandler.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME), attrs); - - // convert node references to paths - if (value instanceof NodeRef) - { - value = createRelativePath(context.getExportOf(), nodeRef, (NodeRef)value).toPrefixString(namespaceService); - } - - // output value - String strValue = (String)DefaultTypeConverter.INSTANCE.convert(String.class, value); - if (strValue != null) - { - contentHandler.characters(strValue.toCharArray(), 0, strValue.length()); - } - - // output value wrapper if property data type is any - contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME)); - } - - // end collection - contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUES_LOCALNAME, toPrefixString(VALUES_QNAME)); - } - catch (SAXException e) - { - throw new ExporterException("Failed to process multi-value event - nodeRef " + nodeRef + "; property " + toPrefixString(property), e); - } - } - /* (non-Javadoc) * @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream) */ - public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData) + public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index) { // TODO: Base64 encode content and send out via Content Handler } @@ -770,9 +713,9 @@ import org.xml.sax.helpers.AttributesImpl; return null; } - Path rootPath = nodeService.getPath(rootRef); - Path fromPath = nodeService.getPath(fromRef); - Path toPath = nodeService.getPath(toRef); + Path rootPath = createIndexedPath(rootRef, nodeService.getPath(rootRef)); + Path fromPath = createIndexedPath(fromRef, nodeService.getPath(fromRef)); + Path toPath = createIndexedPath(toRef, nodeService.getPath(toRef)); Path relativePath = null; try @@ -840,4 +783,43 @@ import org.xml.sax.helpers.AttributesImpl; return relativePath; } + + /** + * Helper to convert a path into an indexed path which uniquely identifies a node + * + * @param nodeRef + * @param path + * @return + */ + private Path createIndexedPath(NodeRef nodeRef, Path path) + { + // Add indexes for same name siblings + // TODO: Look at more efficient approach + for (int i = path.size() - 1; i >= 0; i--) + { + Path.Element pathElement = path.get(i); + if (i > 0 && pathElement instanceof Path.ChildAssocElement) + { + int index = 1; // for xpath index compatibility + String searchPath = path.subPath(i).toPrefixString(namespaceService); + List siblings = searchService.selectNodes(nodeRef, searchPath, null, namespaceService, false); + if (siblings.size() > 1) + { + ChildAssociationRef childAssoc = ((Path.ChildAssocElement)pathElement).getRef(); + NodeRef childRef = childAssoc.getChildRef(); + for (NodeRef sibling : siblings) + { + if (sibling.equals(childRef)) + { + childAssoc.setNthSibling(index); + break; + } + index++; + } + } + } + } + + return path; + } } diff --git a/source/java/org/alfresco/repo/importer/ExportSourceImporter.java b/source/java/org/alfresco/repo/importer/ExportSourceImporter.java index 95aef73326..836694320c 100644 --- a/source/java/org/alfresco/repo/importer/ExportSourceImporter.java +++ b/source/java/org/alfresco/repo/importer/ExportSourceImporter.java @@ -39,6 +39,7 @@ import org.alfresco.service.cmr.view.ImporterBinding; import org.alfresco.service.cmr.view.ImporterService; import org.alfresco.service.cmr.view.Location; import org.alfresco.service.namespace.NamespacePrefixResolver; +import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.TempFileProvider; import org.dom4j.io.OutputFormat; @@ -202,6 +203,11 @@ public class ExportSourceImporter implements ImporterJobSPI return false; } + public QName[] getExcludedClasses() + { + return null; + } + }; } diff --git a/source/java/org/alfresco/repo/importer/Importer.java b/source/java/org/alfresco/repo/importer/Importer.java index cb737a1eb6..76ffe69f8e 100644 --- a/source/java/org/alfresco/repo/importer/Importer.java +++ b/source/java/org/alfresco/repo/importer/Importer.java @@ -75,6 +75,14 @@ public interface Importer */ public NodeRef resolvePath(String path); + /** + * Is excluded Content Model Class? + * + * @param QName the class name to test + * @return true => the provided class is excluded from import + */ + public boolean isExcludedClass(QName className); + /** * Signal completion of node import * diff --git a/source/java/org/alfresco/repo/importer/ImporterBootstrap.java b/source/java/org/alfresco/repo/importer/ImporterBootstrap.java index e03b9b512b..8968db71dd 100644 --- a/source/java/org/alfresco/repo/importer/ImporterBootstrap.java +++ b/source/java/org/alfresco/repo/importer/ImporterBootstrap.java @@ -313,7 +313,7 @@ public class ImporterBootstrap implements ApplicationListener } UserTransaction userTransaction = transactionService.getUserTransaction(); - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); + authenticationComponent.setSystemUserAsCurrentUser(); try { @@ -550,7 +550,7 @@ public class ImporterBootstrap implements ApplicationListener public UUID_BINDING getUUIDBinding() { // always use create new strategy for bootstrap import - return UUID_BINDING.CREATE_NEW; + return UUID_BINDING.CREATE_NEW_WITH_UUID; } /* @@ -561,6 +561,16 @@ public class ImporterBootstrap implements ApplicationListener { return true; } + + /* + * (non-Javadoc) + * @see org.alfresco.service.cmr.view.ImporterBinding#getExcludedClasses() + */ + public QName[] getExcludedClasses() + { + // Note: Do not exclude any classes, we want to import all + return new QName[] {}; + } } /** diff --git a/source/java/org/alfresco/repo/importer/ImporterComponent.java b/source/java/org/alfresco/repo/importer/ImporterComponent.java index 7241cb61b9..ff6f384974 100644 --- a/source/java/org/alfresco/repo/importer/ImporterComponent.java +++ b/source/java/org/alfresco/repo/importer/ImporterComponent.java @@ -401,6 +401,7 @@ public class ImporterComponent private ImportPackageHandler streamHandler; private NodeImporterStrategy importStrategy; private UpdateExistingNodeImporterStrategy updateStrategy; + private QName[] excludedClasses; // Import tracking private List nodeRefs = new ArrayList(); @@ -422,6 +423,16 @@ public class ImporterComponent this.streamHandler = streamHandler; this.importStrategy = createNodeImporterStrategy(binding == null ? null : binding.getUUIDBinding()); this.updateStrategy = new UpdateExistingNodeImporterStrategy(); + + // initialise list of content models to exclude from import + if (binding == null || binding.getExcludedClasses() == null) + { + this.excludedClasses = new QName[] { ContentModel.ASPECT_REFERENCEABLE, ContentModel.ASPECT_VERSIONABLE }; + } + else + { + this.excludedClasses = binding.getExcludedClasses(); + } } /** @@ -440,6 +451,10 @@ public class ImporterComponent { return new CreateNewNodeImporterStrategy(true); } + else if (uuidBinding.equals(UUID_BINDING.CREATE_NEW_WITH_UUID)) + { + return new CreateNewNodeImporterStrategy(false); + } else if (uuidBinding.equals(UUID_BINDING.REMOVE_EXISTING)) { return new RemoveExistingNodeImporterStrategy(); @@ -652,6 +667,22 @@ public class ImporterComponent } return referencedRef; } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.importer.Importer#isExcludedClass(org.alfresco.service.namespace.QName) + */ + public boolean isExcludedClass(QName className) + { + for (QName excludedClass : excludedClasses) + { + if (excludedClass.equals(className)) + { + return true; + } + } + return false; + } /* (non-Javadoc) * @see org.alfresco.repo.importer.Importer#end() @@ -670,13 +701,16 @@ public class ImporterComponent List resolvedRefs = new ArrayList(unresolvedRefs.size()); for (String unresolvedRef : unresolvedRefs) { - NodeRef nodeRef = resolveImportedNodeRef(importedRef.context.getNodeRef(), unresolvedRef); - if (nodeRef == null) + if (unresolvedRef != null) { - // TODO: Probably need an alternative mechanism here e.g. report warning - throw new ImporterException("Failed to find item referenced (in property " + importedRef.property + ") as " + importedRef.value); + NodeRef nodeRef = resolveImportedNodeRef(importedRef.context.getNodeRef(), unresolvedRef); + if (nodeRef == null) + { + // TODO: Probably need an alternative mechanism here e.g. report warning + throw new ImporterException("Failed to find item referenced (in property " + importedRef.property + ") as " + importedRef.value); + } + resolvedRefs.add(nodeRef); } - resolvedRefs.add(nodeRef); } refProperty = (Serializable)resolvedRefs; } @@ -998,19 +1032,11 @@ public class ImporterComponent } catch(XPathException e) { - // attempt to resolve as a node reference - try - { - NodeRef directRef = new NodeRef(importedRef); - if (nodeService.exists(directRef)) - { - nodeRef = directRef; - } - } - catch(AlfrescoRuntimeException e1) - { - // Note: Invalid reference format - } + nodeRef = new NodeRef(importedRef); + } + catch(AlfrescoRuntimeException e1) + { + // Note: Invalid reference format - try path search instead } } diff --git a/source/java/org/alfresco/repo/importer/view/NodeContext.java b/source/java/org/alfresco/repo/importer/view/NodeContext.java index 3df16a381d..a4c49c1ac5 100644 --- a/source/java/org/alfresco/repo/importer/view/NodeContext.java +++ b/source/java/org/alfresco/repo/importer/view/NodeContext.java @@ -459,8 +459,7 @@ public class NodeContext extends ElementContext */ private boolean isImportableClass(QName className) { - return !(className.equals(ContentModel.ASPECT_REFERENCEABLE) || - className.equals(ContentModel.ASPECT_VERSIONABLE)); + return !getImporter().isExcludedClass(className); } /* (non-Javadoc) diff --git a/source/java/org/alfresco/repo/service/StoreRedirectorProxyFactory.java b/source/java/org/alfresco/repo/service/StoreRedirectorProxyFactory.java index 94f7c18434..7273002c3e 100644 --- a/source/java/org/alfresco/repo/service/StoreRedirectorProxyFactory.java +++ b/source/java/org/alfresco/repo/service/StoreRedirectorProxyFactory.java @@ -178,7 +178,7 @@ public class StoreRedirectorProxyFactory implements FactoryBean, Initializing // Otherwise, determine the apropriate implementation to invoke for // the service interface method Object binding = null; - StoreRef storeRef = getStoreRef(args); + StoreRef storeRef = getStoreRef(method.getParameterTypes(), args); if (storeRef == null) { binding = StoreRedirectorProxyFactory.this.defaultBinding; @@ -224,7 +224,7 @@ public class StoreRedirectorProxyFactory implements FactoryBean, Initializing * @param args the method arguments * @return the store type (or null, if one is not specified) */ - private StoreRef getStoreRef(Object[] args) + private StoreRef getStoreRef(Class[] argTypes, Object[] args) { StoreRef storeRef = null; @@ -233,17 +233,17 @@ public class StoreRedirectorProxyFactory implements FactoryBean, Initializing return null; } - for (Object arg : args) + for (int i = 0; i < argTypes.length; i++) { // Extract store type from argument, if store type provided StoreRef argStoreRef = null; - if (arg instanceof NodeRef) + if (argTypes[i].equals(NodeRef.class)) { - argStoreRef = ((NodeRef) arg).getStoreRef(); + argStoreRef = ((NodeRef) args[i]).getStoreRef(); } - else if (arg instanceof StoreRef) + else if (argTypes[i].equals(StoreRef.class)) { - argStoreRef = ((StoreRef) arg); + argStoreRef = ((StoreRef) args[i]); } // Only allow one store type diff --git a/source/java/org/alfresco/repo/version/VersionBootstrap.java b/source/java/org/alfresco/repo/version/VersionBootstrap.java deleted file mode 100644 index 46226e5e23..0000000000 --- a/source/java/org/alfresco/repo/version/VersionBootstrap.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.version; - -import javax.transaction.UserTransaction; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.security.authentication.AuthenticationComponent; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.transaction.TransactionService; - -/** - * Bootstrap Version Store - * - * @author David Caruana - */ -public class VersionBootstrap -{ - private TransactionService transactionService; - private NodeService nodeService; - private AuthenticationComponent authenticationComponent; - private PermissionService permissionService; - - - /** - * Sets the Transaction Service - * - * @param userTransaction the user transaction - */ - public void setTransactionService(TransactionService transactionService) - { - this.transactionService = transactionService; - } - - /** - * Sets the Node Service - * - * @param nodeService the node service - */ - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - public void setAuthenticationComponent(AuthenticationComponent authenticationComponent) - { - this.authenticationComponent = authenticationComponent; - } - - - - public void setPermissionService(PermissionService permissionService) - { - this.permissionService = permissionService; - } - - /** - * Bootstrap the Version Store - */ - public void bootstrap() - { - UserTransaction userTransaction = transactionService.getUserTransaction(); - authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); - - try - { - userTransaction.begin(); - - // Ensure that the version store has been created - if (this.nodeService.exists(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID)) == true) - { - userTransaction.rollback(); - } - else - { - StoreRef vStore = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID); - // TODO: For now there are no permissions on version access - permissionService.setPermission(nodeService.getRootNode(vStore), permissionService.getAllAuthorities(), permissionService.getAllPermission(), true); - userTransaction.commit(); - } - } - catch(Throwable e) - { - // rollback the transaction - try { if (userTransaction != null) {userTransaction.rollback();} } catch (Exception ex) {} - try {authenticationComponent.clearCurrentSecurityContext(); } catch (Exception ex) {} - throw new AlfrescoRuntimeException("Bootstrap failed", e); - } - finally - { - authenticationComponent.clearCurrentSecurityContext(); - } - } - -} diff --git a/source/java/org/alfresco/service/cmr/view/Exporter.java b/source/java/org/alfresco/service/cmr/view/Exporter.java index a9da31d6b2..bb7858ebdf 100644 --- a/source/java/org/alfresco/service/cmr/view/Exporter.java +++ b/source/java/org/alfresco/service/cmr/view/Exporter.java @@ -171,14 +171,26 @@ public interface Exporter public void startValueCollection(NodeRef nodeRef, QName property); /** - * Export single valued property + * Export property value * * @param nodeRef the node reference * @param property the property name * @param value the value + * @param index value index (or -1, if not part of multi-valued collection) */ - public void value(NodeRef nodeRef, QName property, Object value); + public void value(NodeRef nodeRef, QName property, Object value, int index); + /** + * Export content stream property value + * + * @param nodeRef the node reference + * @param property the property name + * @param content the content stream + * @param contentData content descriptor + * @param index value index (or -1, if not part of multi-valued collection) + */ + public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index); + /** * Export end of value collection * @@ -187,16 +199,6 @@ public interface Exporter */ public void endValueCollection(NodeRef nodeRef, QName property); - /** - * Export content stream property - * - * @param nodeRef the node reference - * @param property the property name - * @param content the content stream - * @param contentData content descriptor - */ - public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData); - /** * Start export of associations * diff --git a/source/java/org/alfresco/service/cmr/view/ImporterBinding.java b/source/java/org/alfresco/service/cmr/view/ImporterBinding.java index 603bf6ce3f..d19b89cced 100644 --- a/source/java/org/alfresco/service/cmr/view/ImporterBinding.java +++ b/source/java/org/alfresco/service/cmr/view/ImporterBinding.java @@ -16,6 +16,8 @@ */ package org.alfresco.service.cmr.view; +import org.alfresco.service.namespace.QName; + /** * Encapsulation of Import binding parameters @@ -30,7 +32,7 @@ public interface ImporterBinding */ public enum UUID_BINDING { - CREATE_NEW, REMOVE_EXISTING, REPLACE_EXISTING, UPDATE_EXISTING, THROW_ON_COLLISION + CREATE_NEW, CREATE_NEW_WITH_UUID, REMOVE_EXISTING, REPLACE_EXISTING, UPDATE_EXISTING, THROW_ON_COLLISION } /** @@ -56,4 +58,11 @@ public interface ImporterBinding */ public String getValue(String key); + /** + * Gets the list of content model classes to exclude from import + * + * @return list of model class qnames to exclude (return null to indicate use of default list) + */ + public QName[] getExcludedClasses(); + } diff --git a/source/java/org/alfresco/service/cmr/view/RepositoryExporterService.java b/source/java/org/alfresco/service/cmr/view/RepositoryExporterService.java new file mode 100644 index 0000000000..29d8bfad6c --- /dev/null +++ b/source/java/org/alfresco/service/cmr/view/RepositoryExporterService.java @@ -0,0 +1,95 @@ +/* + * 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; + +import java.io.File; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; + + +/** + * Repository Export Service + * + * @author davidc + */ +public interface RepositoryExporterService +{ + + /** + * Export complete Repository. + * + * Each store is exported to its own temporary .acp file + * + * @param packageName package name prefix for export .acp files + * @return list of temporary export files + */ + public FileExportHandle[] export(String packageName); + + /** + * Export complete Repository. + * + * Each store is exported to a file held in the Repository. + * + * @param repositoryDestination location within Repository to hold .acp files + * @param packageName package name prefix for export .acp files + * @return list of repository held export files + */ + public RepositoryExportHandle[] export(NodeRef repositoryDestination, String packageName); + + /** + * Export complete Repository. + * + * @param directoryDestination location within File System to hold .acp files + * @param packageName package name prefix for export .acp files + * @return list of export files + */ + public FileExportHandle[] export(File directoryDestination, String packageName); + + + /** + * General Export Handle + * + * @author davidc + */ + public class ExportHandle + { + public StoreRef storeRef; + public String packageName; + } + + /** + * File Exort Handle + * + * @author davidc + */ + public class FileExportHandle extends ExportHandle + { + public File exportFile; + } + + /** + * Repository File Export Handle + * + * @author davidc + */ + public class RepositoryExportHandle extends ExportHandle + { + public NodeRef exportFile; + } + +} diff --git a/source/java/org/alfresco/tools/Export.java b/source/java/org/alfresco/tools/Export.java index 721c3a699b..25e737a355 100644 --- a/source/java/org/alfresco/tools/Export.java +++ b/source/java/org/alfresco/tools/Export.java @@ -568,14 +568,14 @@ public final class Export extends Tool /* (non-Javadoc) * @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable) */ - public void value(NodeRef nodeRef, QName property, Object value) + public void value(NodeRef nodeRef, QName property, Object value, int index) { } /* (non-Javadoc) * @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream) */ - public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData) + public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index) { }