Java tutorial
/* * #%L * Alfresco Repository * %% * Copyright (C) 2005 - 2016 Alfresco Software Limited * %% * This file is part of the Alfresco software. * If the software was purchased under a paid Alfresco license, the terms of * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * #L% */ package org.alfresco.repo.exporter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import org.alfresco.model.ContentModel; import org.alfresco.repo.node.MLPropertyInterceptor; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.cmr.dictionary.AssociationDefinition; 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.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.MLText; 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.TypeConversionException; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.view.ExportPackageHandler; import org.alfresco.service.cmr.view.Exporter; import org.alfresco.service.cmr.view.ExporterContext; 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.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; import org.alfresco.service.namespace.RegexQNamePattern; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.springframework.extensions.surf.util.ParameterCheck; /** * Default implementation of the Exporter Service. * * @author David Caruana */ public class ExporterComponent implements ExporterService { // Supporting services private NamespaceService namespaceService; private DictionaryService dictionaryService; private NodeService nodeService; private SearchService searchService; private ContentService contentService; private DescriptorService descriptorService; private AuthenticationService authenticationService; private PermissionService permissionService; /** Indent Size */ private int indentSize = 2; private boolean exportSecondaryNodes = false; /** * @param nodeService the node service */ public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } /** * @param searchService the service to perform path searches */ public void setSearchService(SearchService searchService) { this.searchService = searchService; } /** * @param contentService the content service */ public void setContentService(ContentService contentService) { this.contentService = contentService; } /** * @param dictionaryService the dictionary service */ public void setDictionaryService(DictionaryService dictionaryService) { this.dictionaryService = dictionaryService; } /** * @param namespaceService the namespace service */ public void setNamespaceService(NamespaceService namespaceService) { this.namespaceService = namespaceService; } /** * @param descriptorService the descriptor service */ public void setDescriptorService(DescriptorService descriptorService) { this.descriptorService = descriptorService; } /** * @param authenticationService the authentication service */ public void setAuthenticationService(AuthenticationService authenticationService) { this.authenticationService = authenticationService; } /** * @param permissionService the permission service */ public void setPermissionService(PermissionService permissionService) { this.permissionService = permissionService; } /** * @param exportSecondaryNodes whether children that do dot have a primary association with their parent are exported as nodes * If false, these nodes will be exported as secondary links. */ public void setExportSecondaryNodes(boolean exportSecondaryNodes) { this.exportSecondaryNodes = exportSecondaryNodes; } /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ExporterService#exportView(java.io.OutputStream, org.alfresco.service.cmr.view.ExporterCrawlerParameters, org.alfresco.service.cmr.view.Exporter) */ public void exportView(OutputStream viewWriter, ExporterCrawlerParameters parameters, Exporter progress) { ParameterCheck.mandatory("View Writer", viewWriter); // Construct a basic XML Exporter Exporter xmlExporter = createXMLExporter(viewWriter, parameters.getReferenceType()); // Export exportView(xmlExporter, parameters, progress); } /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ExporterService#exportView(org.alfresco.service.cmr.view.ExportPackageHandler, org.alfresco.service.cmr.view.ExporterCrawlerParameters, org.alfresco.service.cmr.view.Exporter) */ public void exportView(ExportPackageHandler exportHandler, ExporterCrawlerParameters parameters, Exporter progress) { ParameterCheck.mandatory("Stream Handler", exportHandler); // create exporter around export handler exportHandler.startExport(); OutputStream dataFile = exportHandler.createDataStream(); Exporter xmlExporter = createXMLExporter(dataFile, parameters.getReferenceType()); URLExporter urlExporter = new URLExporter(xmlExporter, exportHandler); // export exportView(urlExporter, parameters, progress); // end export exportHandler.endExport(); } /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ExporterService#exportView(org.alfresco.service.cmr.view.Exporter, org.alfresco.service.cmr.view.ExporterCrawler, org.alfresco.service.cmr.view.Exporter) */ public void exportView(Exporter exporter, ExporterCrawlerParameters parameters, Exporter progress) { ParameterCheck.mandatory("Exporter", exporter); ChainedExporter chainedExporter = new ChainedExporter(new Exporter[] { exporter, progress }); DefaultCrawler crawler = new DefaultCrawler(); crawler.export(parameters, chainedExporter); } /** * Create an XML Exporter that exports repository information to the specified * 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, ReferenceType referenceType) { // Define output format OutputFormat format = OutputFormat.createPrettyPrint(); format.setNewLineAfterDeclaration(false); format.setIndentSize(indentSize); format.setEncoding("UTF-8"); // Construct an XML Exporter try { XMLWriter writer = new XMLWriter(viewWriter, format); 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); } } /** * Responsible for navigating the Repository from specified location and invoking * the provided exporter call-back for the actual export implementation. * * @author David Caruana */ private class DefaultCrawler implements ExporterCrawler { private ExporterContextImpl context; /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ExporterCrawler#export(org.alfresco.service.cmr.view.Exporter) */ public void export(ExporterCrawlerParameters parameters, Exporter exporter) { // Initialise Crawler context = new ExporterContextImpl(parameters); exporter.start(context); // // Export Nodes // while (context.canRetrieve()) { // determine if root repository node NodeRef nodeRef = context.getExportOf(); if (parameters.isCrawlSelf()) { // 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<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(nodeRef); for (ChildAssociationRef childAssoc : childAssocs) { walkStartNamespaces(parameters, exporter); walkNode(childAssoc.getChildRef(), parameters, exporter, false); walkEndNamespaces(parameters, exporter); } } context.setNextValue(); } // // Export associations between nodes // context.resetContext(); while (context.canRetrieve()) { Set<NodeRef> nodesWithSecondaryLinks = context.getNodesWithSecondaryLinks(); if (nodesWithSecondaryLinks != null) { // // Export Secondary Links between Nodes // for (NodeRef nodeWithAssociations : nodesWithSecondaryLinks) { walkStartNamespaces(parameters, exporter); walkNodeSecondaryLinks(nodeWithAssociations, parameters, exporter); walkEndNamespaces(parameters, exporter); } } Set<NodeRef> nodesWithAssociations = context.getNodesWithAssociations(); if (nodesWithAssociations != null) { // // Export Associations between Nodes // for (NodeRef nodeWithAssociations : nodesWithAssociations) { walkStartNamespaces(parameters, exporter); walkNodeAssociations(nodeWithAssociations, parameters, exporter); walkEndNamespaces(parameters, exporter); } } context.setNextValue(); } exporter.end(); } /** * Call-backs for start of Namespace scope */ private void walkStartNamespaces(ExporterCrawlerParameters parameters, Exporter exporter) { Collection<String> prefixes = namespaceService.getPrefixes(); for (String prefix : prefixes) { if (!prefix.equals("xml")) { String uri = namespaceService.getNamespaceURI(prefix); exporter.startNamespace(prefix, uri); } } } /** * Call-backs for end of Namespace scope */ private void walkEndNamespaces(ExporterCrawlerParameters parameters, Exporter exporter) { Collection<String> prefixes = namespaceService.getPrefixes(); for (String prefix : prefixes) { if (!prefix.equals("xml")) { exporter.endNamespace(prefix); } } } /** * Navigate a Node. * * @param nodeRef the node to navigate */ 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); if (isExcludedURI(parameters.getExcludeNamespaceURIs(), type.getNamespaceURI())) { return; } // explicitly included ? if (parameters.getIncludedPaths() != null) { String nodePathPrefixString = nodeService.getPath(nodeRef).toPrefixString(namespaceService); if (!(isIncludedPath(parameters.getIncludedPaths(), nodePathPrefixString))) { return; } } // 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); Set<QName> aspects = nodeService.getAspects(nodeRef); for (QName aspect : aspects) { if (isExcludedURI(parameters.getExcludeNamespaceURIs(), aspect.getNamespaceURI())) { continue; } else if (isExcludedAspect(parameters.getExcludeAspects(), aspect)) { continue; } else { exporter.startAspect(nodeRef, aspect); exporter.endAspect(nodeRef, aspect); } } exporter.endAspects(nodeRef); // Export node permissions AccessStatus readPermission = permissionService.hasPermission(nodeRef, PermissionService.READ_PERMISSIONS); if (authenticationService.isCurrentUserTheSystemUser() || readPermission.equals(AccessStatus.ALLOWED)) { Set<AccessPermission> permissions = permissionService.getAllSetPermissions(nodeRef); boolean inheritPermissions = permissionService.getInheritParentPermissions(nodeRef); if (permissions.size() > 0 || !inheritPermissions) { exporter.startACL(nodeRef); for (AccessPermission permission : permissions) { if (permission.isSetDirectly()) { exporter.permission(nodeRef, permission); } } exporter.endACL(nodeRef); } } // Export node properties exporter.startProperties(nodeRef); boolean aware = MLPropertyInterceptor.setMLAware(true); Map<QName, Serializable> properties = nodeService.getProperties(nodeRef); MLPropertyInterceptor.setMLAware(aware); for (QName property : properties.keySet()) { // filter out properties whose namespace is excluded if (isExcludedURI(parameters.getExcludeNamespaceURIs(), property.getNamespaceURI())) { continue; } if (isExcludedAspectProperty(parameters.getExcludeAspects(), property)) { continue; } // filter out properties whose value is null, if not required Object value = properties.get(property); if (!parameters.isCrawlNullProperties() && value == null) { continue; } // start export of property exporter.startProperty(nodeRef, property); if (value instanceof Collection) { exporter.startValueCollection(nodeRef, property); int index = 0; for (Object valueInCollection : (Collection) value) { walkProperty(nodeRef, property, valueInCollection, index, parameters, exporter); index++; } exporter.endValueCollection(nodeRef, property); } else { if (value instanceof MLText) { MLText valueMLT = (MLText) value; Set<Locale> locales = valueMLT.getLocales(); for (Locale locale : locales) { String localeValue = valueMLT.getValue(locale); exporter.startValueMLText(nodeRef, locale, localeValue == null); walkProperty(nodeRef, property, localeValue, -1, parameters, exporter); exporter.endValueMLText(nodeRef); } } else { walkProperty(nodeRef, property, value, -1, parameters, exporter); } } // end export of property exporter.endProperty(nodeRef, property); } exporter.endProperties(nodeRef); // Export node children if (parameters.isCrawlChildNodes()) { // sort associations into assoc type buckets filtering out unneccessary associations Map<QName, List<ChildAssociationRef>> assocTypes = new HashMap<QName, List<ChildAssociationRef>>(); List<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(nodeRef); for (ChildAssociationRef childAssoc : childAssocs) { QName childAssocType = childAssoc.getTypeQName(); if (isExcludedURI(parameters.getExcludeNamespaceURIs(), childAssocType.getNamespaceURI())) { continue; } if (isExcludedChildAssoc(parameters.getExcludeChildAssocs(), childAssocType)) { continue; } if (isExcludedAspectAssociation(parameters.getExcludeAspects(), childAssocType)) { continue; } if (childAssoc.isPrimary() == false && !exportSecondaryNodes) { context.recordSecondaryLink(nodeRef); continue; } if (isExcludedURI(parameters.getExcludeNamespaceURIs(), childAssoc.getQName().getNamespaceURI())) { continue; } List<ChildAssociationRef> assocRefs = assocTypes.get(childAssocType); if (assocRefs == null) { assocRefs = new ArrayList<ChildAssociationRef>(); assocTypes.put(childAssocType, assocRefs); } assocRefs.add(childAssoc); } // output each association type bucket if (assocTypes.size() > 0) { exporter.startAssocs(nodeRef); for (Map.Entry<QName, List<ChildAssociationRef>> assocType : assocTypes.entrySet()) { List<ChildAssociationRef> assocRefs = assocType.getValue(); if (assocRefs.size() > 0) { exporter.startAssoc(nodeRef, assocType.getKey()); for (ChildAssociationRef assocRef : assocRefs) { walkNode(assocRef.getChildRef(), parameters, exporter, false); } exporter.endAssoc(nodeRef, assocType.getKey()); } } exporter.endAssocs(nodeRef); } } // Export node associations if (parameters.isCrawlAssociations()) { List<AssociationRef> associations = nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL); if (associations.size() > 0) { context.recordAssociation(nodeRef); } } // Signal end of node // export node as reference to node, or as the actual node if (exportAsRef) { exporter.endReference(nodeRef); } else { exporter.endNode(nodeRef); } } /** * Export Property * * @param nodeRef NodeRef * @param property QName * @param value Object * @param index int * @param parameters ExporterCrawlerParameters * @param 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); DataTypeDefinition dataTypeDef = (propDef == null) ? null : propDef.getDataType(); 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(); } } else { valueDataType = dataTypeDef.getName(); } if (valueDataType == null || !valueDataType.equals(DataTypeDefinition.CONTENT)) { // Export non content data types try { 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 == null ? null : value.toString()), index); } } else { // export property of datatype CONTENT ContentReader reader = contentService.getReader(nodeRef, property); if (!parameters.isCrawlContent() || reader == null || reader.exists() == false) { // export an empty url for the content ContentData contentData = (ContentData) value; ContentData noContentURL = null; if (contentData == null) { noContentURL = new ContentData("", null, 0L, "UTF-8"); } else { noContentURL = new ContentData("", contentData.getMimetype(), contentData.getSize(), contentData.getEncoding()); } exporter.content(nodeRef, property, null, noContentURL, index); exporter.warning("Skipped content for property " + property + " on node " + nodeRef); } else { InputStream inputStream = reader.getContentInputStream(); try { exporter.content(nodeRef, property, inputStream, reader.getContentData(), index); } finally { try { inputStream.close(); } catch (IOException e) { throw new ExporterException("Failed to export node content for node " + nodeRef, e); } } } } } /** * Export Secondary Links * * @param nodeRef NodeRef * @param parameters ExporterCrawlerParameters * @param exporter Exporter */ private void walkNodeSecondaryLinks(NodeRef nodeRef, ExporterCrawlerParameters parameters, Exporter exporter) { // sort associations into assoc type buckets filtering out unneccessary associations Map<QName, List<ChildAssociationRef>> assocTypes = new HashMap<QName, List<ChildAssociationRef>>(); List<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(nodeRef); for (ChildAssociationRef childAssoc : childAssocs) { // determine if child association should be exported QName childAssocType = childAssoc.getTypeQName(); if (isExcludedURI(parameters.getExcludeNamespaceURIs(), childAssocType.getNamespaceURI())) { continue; } if (isExcludedChildAssoc(parameters.getExcludeChildAssocs(), childAssocType)) { continue; } if (isExcludedAspectAssociation(parameters.getExcludeAspects(), childAssocType)) { continue; } if (childAssoc.isPrimary()) { continue; } if (!isWithinExport(childAssoc.getChildRef(), parameters)) { continue; } List<ChildAssociationRef> assocRefs = assocTypes.get(childAssocType); if (assocRefs == null) { assocRefs = new ArrayList<ChildAssociationRef>(); assocTypes.put(childAssocType, assocRefs); } assocRefs.add(childAssoc); } // output each association type bucket if (assocTypes.size() > 0) { exporter.startReference(nodeRef, null); exporter.startAssocs(nodeRef); for (Map.Entry<QName, List<ChildAssociationRef>> assocType : assocTypes.entrySet()) { List<ChildAssociationRef> assocRefs = assocType.getValue(); if (assocRefs.size() > 0) { exporter.startAssoc(nodeRef, assocType.getKey()); for (ChildAssociationRef assocRef : assocRefs) { exporter.startReference(assocRef.getChildRef(), assocRef.getQName()); exporter.endReference(assocRef.getChildRef()); } exporter.endAssoc(nodeRef, assocType.getKey()); } } exporter.endAssocs(nodeRef); exporter.endReference(nodeRef); } } /** * Export Node Associations * * @param nodeRef NodeRef * @param parameters ExporterCrawlerParameters * @param exporter Exporter */ private void walkNodeAssociations(NodeRef nodeRef, ExporterCrawlerParameters parameters, Exporter exporter) { // sort associations into assoc type buckets filtering out unneccessary associations Map<QName, List<AssociationRef>> assocTypes = new HashMap<QName, List<AssociationRef>>(); List<AssociationRef> assocs = nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL); for (AssociationRef assoc : assocs) { QName assocType = assoc.getTypeQName(); if (isExcludedURI(parameters.getExcludeNamespaceURIs(), assocType.getNamespaceURI())) { continue; } if (!isWithinExport(assoc.getTargetRef(), parameters)) { continue; } List<AssociationRef> assocRefs = assocTypes.get(assocType); if (assocRefs == null) { assocRefs = new ArrayList<AssociationRef>(); assocTypes.put(assocType, assocRefs); } assocRefs.add(assoc); } // output each association type bucket if (assocTypes.size() > 0) { exporter.startReference(nodeRef, null); exporter.startAssocs(nodeRef); for (Map.Entry<QName, List<AssociationRef>> assocType : assocTypes.entrySet()) { List<AssociationRef> assocRefs = assocType.getValue(); if (assocRefs.size() > 0) { exporter.startAssoc(nodeRef, assocType.getKey()); for (AssociationRef assocRef : assocRefs) { exporter.startReference(assocRef.getTargetRef(), null); exporter.endReference(assocRef.getTargetRef()); } exporter.endAssoc(nodeRef, assocType.getKey()); } } exporter.endAssocs(nodeRef); exporter.endReference(nodeRef); } } /** * Is the specified URI an excluded URI? * * @param uri the URI to test * @return true => it's excluded from the export */ private boolean isExcludedURI(String[] excludeNamespaceURIs, String uri) { for (String excludedURI : excludeNamespaceURIs) { if (uri.equals(excludedURI)) { return true; } } return false; } private boolean isIncludedPath(String[] includedPaths, String path) { for (String includePath : includedPaths) { // note: allow parents or children - e.g. if included path is /a/b/c then /, /a, /a/b, /a/b/c, /a/b/c/d, /a/b/c/d/e are all included if (includePath.startsWith(path) || path.startsWith(includePath)) { return true; } } return false; } /** * Is the aspect unexportable? * * @param aspectQName the aspect name * @return <tt>true</tt> if the aspect can't be exported */ private boolean isExcludedAspect(QName[] excludeAspects, QName aspectQName) { if (aspectQName.equals(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT) || aspectQName.equals(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION)) { return true; } else { for (QName excludeAspect : excludeAspects) { if (aspectQName.equals(excludeAspect)) { return true; } } } return false; } /** * Is the child association unexportable? * * @param childAssocQName the child assoc name * @return <tt>true</tt> if the aspect can't be exported */ private boolean isExcludedChildAssoc(QName[] excludeChildAssocs, QName childAssocQName) { for (QName excludeChildAssoc : excludeChildAssocs) { if (childAssocQName.equals(excludeChildAssoc)) { return true; } } return false; } /** * Is the property unexportable? */ private boolean isExcludedAspectProperty(QName[] excludeAspects, QName propertyQName) { PropertyDefinition propDef = dictionaryService.getProperty(propertyQName); if (propDef == null) { return false; } ClassDefinition classDef = propDef.getContainerClass(); if (classDef == null || !classDef.isAspect()) { return false; } return isExcludedAspect(excludeAspects, classDef.getName()); } /** * Is the association unexportable? */ private boolean isExcludedAspectAssociation(QName[] excludeAspects, QName associationQName) { AssociationDefinition assocDef = dictionaryService.getAssociation(associationQName); if (assocDef == null) { return false; } ClassDefinition classDef = assocDef.getSourceClass(); if (classDef == null || !classDef.isAspect()) { return false; } return isExcludedAspect(excludeAspects, classDef.getName()); } /** * Determine if specified Node Reference is within the set of nodes to be exported * * @param nodeRef node reference to check * @return true => node reference is within export set */ private boolean isWithinExport(NodeRef nodeRef, ExporterCrawlerParameters parameters) { boolean isWithin = false; try { // Current strategy is to determine if node is a child of the root exported node for (NodeRef exportRoot : context.getExportList()) { if (nodeRef.equals(exportRoot) && parameters.isCrawlSelf() == true) { // 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--) { Path.ChildAssocElement pathElement = (Path.ChildAssocElement) nodePath.get(i); if (pathElement.getRef().getChildRef().equals(exportRoot)) { isWithin = true; break; } } } } } catch (AccessDeniedException accessErr) { // use default if this occurs } catch (InvalidNodeRefException nodeErr) { // use default if this occurs } return isWithin; } } /** * Exporter Context */ private class ExporterContextImpl implements ExporterContext { private NodeRef[] exportList; private NodeRef[] parentList; private String exportedBy; private Date exportedDate; private String exporterVersion; private Map<Integer, Set<NodeRef>> nodesWithSecondaryLinks = new HashMap<Integer, Set<NodeRef>>(); private Map<Integer, Set<NodeRef>> nodesWithAssociations = new HashMap<Integer, Set<NodeRef>>(); private int index; /** * Construct * * @param parameters exporter crawler parameters */ 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 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() */ public String getExportedBy() { return exportedBy; } /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ExporterContext#getExportedDate() */ public Date getExportedDate() { return exportedDate; } /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ExporterContext#getExporterVersion() */ public String getExporterVersion() { return exporterVersion; } /* (non-Javadoc) * @see org.alfresco.service.cmr.view.ExporterContext#getExportOf() */ public NodeRef getExportOf() { if (canRetrieve()) { return exportList[index]; } return null; } /* * (non-Javadoc) * @see org.alfresco.service.cmr.view.ExporterContext#getExportParent() */ public NodeRef getExportParent() { 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; } /** * Record that associations exist for node * * @param nodeRef NodeRef */ public void recordAssociation(NodeRef nodeRef) { Set<NodeRef> nodes = nodesWithAssociations.get(index); if (nodes == null) { nodes = new HashSet<NodeRef>(); nodesWithAssociations.put(index, nodes); } nodes.add(nodeRef); } /** * Gets nodes that have been recorded with associations * * @return Set<NodeRef> */ public Set<NodeRef> getNodesWithAssociations() { Set<NodeRef> nodes = nodesWithAssociations.get(index); if (nodes != null) { return nodes; } return null; } /** * Record that secondary links exist for node * * @param nodeRef NodeRef */ public void recordSecondaryLink(NodeRef nodeRef) { Set<NodeRef> nodes = nodesWithSecondaryLinks.get(index); if (nodes == null) { nodes = new HashSet<NodeRef>(); nodesWithSecondaryLinks.put(index, nodes); } nodes.add(nodeRef); } /** * Gets nodes that have been recorded with secondary links * * @return */ public Set<NodeRef> getNodesWithSecondaryLinks() { Set<NodeRef> nodes = nodesWithSecondaryLinks.get(index); if (nodes != null) { return nodes; } return null; } /** * Get the Node Ref from the specified Location * * @param location the location * @return the node reference */ private NodeRef getNodeRef(Location location) { ParameterCheck.mandatory("Location", location); // Establish node to export from NodeRef nodeRef = (location == null) ? null : location.getNodeRef(); if (nodeRef == null) { // If a specific node has not been provided, default to the root nodeRef = nodeService.getRootNode(location.getStoreRef()); } // Resolve to path within node, if one specified String path = (location == null) ? null : location.getPath(); if (path != null && path.length() > 0) { // Create a valid path and search List<NodeRef> nodeRefs = searchService.selectNodes(nodeRef, path, null, namespaceService, false); if (nodeRefs.size() == 0) { throw new ImporterException("Path " + path + " within node " + nodeRef + " does not exist - the path must resolve to a valid location"); } if (nodeRefs.size() > 1) { throw new ImporterException("Path " + path + " within node " + nodeRef + " found too many locations - the path must resolve to one location"); } nodeRef = nodeRefs.get(0); } // TODO: Check Node actually exists return nodeRef; } /** * Gets the parent node of the items to be exported * * @param exportOf NodeRef * @param exportSelf boolean * @return NodeRef */ private NodeRef getParent(NodeRef exportOf, boolean exportSelf) { NodeRef parent = null; if (exportSelf) { NodeRef rootNode = nodeService.getRootNode(exportOf.getStoreRef()); if (rootNode.equals(exportOf)) { parent = exportOf; } else { ChildAssociationRef parentRef = nodeService.getPrimaryParent(exportOf); parent = parentRef.getParentRef(); } } else { parent = exportOf; } return parent; } } }