You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2013/08/10 07:53:54 UTC
svn commit: r1512568 [15/39] - in /jackrabbit/commons/filevault/trunk: ./
parent/ vault-cli/ vault-cli/src/ vault-cli/src/main/
vault-cli/src/main/appassembler/ vault-cli/src/main/assembly/
vault-cli/src/main/java/ vault-cli/src/main/java/org/ vault-cl...
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FileArtifactHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FileArtifactHandler.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FileArtifactHandler.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FileArtifactHandler.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,370 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Collection;
+
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.jackrabbit.vault.fs.api.Artifact;
+import org.apache.jackrabbit.vault.fs.api.ArtifactType;
+import org.apache.jackrabbit.vault.fs.api.ImportArtifact;
+import org.apache.jackrabbit.vault.fs.api.ImportInfo;
+import org.apache.jackrabbit.vault.fs.api.ImportMode;
+import org.apache.jackrabbit.vault.fs.api.ItemFilterSet;
+import org.apache.jackrabbit.vault.fs.api.SerializationType;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.impl.ArtifactSetImpl;
+import org.apache.jackrabbit.vault.util.JcrConstants;
+import org.apache.jackrabbit.vault.util.MimeTypes;
+import org.apache.jackrabbit.vault.util.PathUtil;
+import org.apache.jackrabbit.vault.util.Text;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Creates nt:file structures from {@link SerializationType#XML_GENERIC} or
+ * {@link SerializationType#GENERIC} artifacts.
+ *
+ */
+public class FileArtifactHandler extends AbstractArtifactHandler {
+
+ /**
+ * The node type for xml deserialization
+ */
+ private String xmlNodeType = "nt:xmlDocument";
+
+ /**
+ * Indicates if xml should be deserialized
+ */
+ private boolean explodeXml = false;
+
+ /**
+ * Returns the node type that is used for generic xml deserialization.
+ * This has only an effect if {@link #isExplodeXml()} is <code>true</code>.
+ *
+ * @return the xml node type.
+ */
+ public String getXmlNodeType() {
+ return xmlNodeType;
+ }
+
+ /**
+ * Sets the node type that is used for generic xml deserialization.
+ * This has only an effect if {@link #isExplodeXml()} is <code>true</code>.
+ * <p/>
+ * Default is <code>nt:xmlDocument</code>
+ *
+ * @param xmlNodeType the xml node type name
+ */
+ public void setXmlNodeType(String xmlNodeType) {
+ this.xmlNodeType = xmlNodeType;
+ }
+
+ /**
+ * Checks if this handler explodes the xml for a generic xml deserialization.
+ *
+ * @return <code>true</code> if this handler explodes the xml
+ */
+ public boolean isExplodeXml() {
+ return explodeXml;
+ }
+
+ /**
+ * Sets whether this handler should explode the xml of a generic xml
+ * serialization.
+ * <p/>
+ * Default is <code>false</code>.
+ *
+ * @param explodeXml <code>true</code> if to explode the xml
+ */
+ public void setExplodeXml(boolean explodeXml) {
+ this.explodeXml = explodeXml;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Handles generic artifact sets
+ */
+ public ImportInfoImpl accept(WorkspaceFilter wspFilter, Node parent,
+ String name, ArtifactSetImpl artifacts)
+ throws RepositoryException, IOException {
+ // check if any file artifacts was removed
+ ImportInfoImpl info = null;
+ Collection<Artifact> removed = artifacts.removed();
+ for (Artifact a: removed) {
+ if (a.getType() == ArtifactType.FILE) {
+ if (parent.hasNode(a.getRelativePath())) {
+ Node file = parent.getNode(a.getRelativePath());
+ String path = file.getPath();
+ // check wsp filter, only remove if 'REPLACE'
+ if (info == null) {
+ info = new ImportInfoImpl();
+ }
+ if (wspFilter.getImportMode(path) == ImportMode.REPLACE) {
+ info.onDeleted(path);
+ file.remove();
+ } else {
+ info.onNop(path);
+ }
+ }
+ }
+ }
+
+ // need at least a file or binary artifact
+ if (artifacts.size(ArtifactType.FILE) > 0 || artifacts.size(ArtifactType.BINARY) > 0) {
+ // check if the generic handler can import something
+ Artifact primary = artifacts.getPrimaryData();
+ if (primary != null) {
+ if (info == null) {
+ info = new ImportInfoImpl();
+ }
+ // check import mode
+ ImportMode mode = ImportMode.REPLACE;
+ String path = PathUtil.getPath(parent, primary.getRelativePath());
+ if (primary.getRelativePath().length() == 0 || parent.hasNode(primary.getRelativePath())) {
+ mode = wspFilter.getImportMode(path);
+ }
+ // only update if not MERGE (i.e. is REPLACE or UPDATE)
+ if (mode != ImportMode.MERGE) {
+ InputSource source = primary.getInputSource();
+ if (source != null) {
+ info.merge(importDocView(parent, source, artifacts, wspFilter));
+ }
+ } else {
+ info.onNop(path);
+ }
+ }
+ // handle files
+ for (Artifact file: artifacts.values(ArtifactType.FILE)) {
+ if (info == null) {
+ info = new ImportInfoImpl();
+ }
+ // check type of file artifact
+ if (file.getSerializationType() == SerializationType.GENERIC
+ || file.getSerializationType() == SerializationType.XML_GENERIC) {
+ // case 1: new file
+ if (!parent.hasNode(file.getRelativePath())) {
+ importFile(info, parent, file);
+ } else {
+ // case 2: same structure, new data
+ if (file instanceof ImportArtifact) {
+ Node fileNode = parent.getNode(file.getRelativePath());
+ // check import mode, only replace if not MERGE
+ if (wspFilter.getImportMode(fileNode.getPath()) != ImportMode.MERGE) {
+ if (!fileNode.hasNode(JcrConstants.JCR_CONTENT)) {
+ // apparently no nt:file, recreate file node
+ fileNode.remove();
+ importFile(info, parent, file);
+ } else {
+ if (!importNtResource(info, fileNode.getNode(JcrConstants.JCR_CONTENT), file)) {
+ info.onNop(fileNode.getPath());
+ }
+ }
+ } else {
+ info.onNop(fileNode.getPath());
+ }
+ } else {
+ // do nothing
+ }
+ }
+ } else if (file.getSerializationType() == SerializationType.XML_DOCVIEW) {
+ // special case for full coverage files below a intermediate node
+ String relPath = Text.getRelativeParent(file.getRelativePath(), 1);
+ String newName = Text.getName(file.getRelativePath());
+ Node newParent = parent;
+ if (relPath.length() > 0) {
+ if (parent.hasNode(relPath)) {
+ newParent = parent.getNode(relPath);
+ } else {
+ throw new IllegalArgumentException("Special docview file can't be imported. parent does not exist: " + parent.getPath() + "/" + relPath);
+ }
+ }
+ ArtifactSetImpl newSet = new ArtifactSetImpl();
+ newSet.setCoverage(ItemFilterSet.INCLUDE_ALL);
+
+ // check import mode
+ ImportMode mode = ImportMode.REPLACE;
+ String path = PathUtil.getPath(newParent, newName);
+ if (newName.length() == 0 || newParent.hasNode(newName)) {
+ mode = wspFilter.getImportMode(path);
+ }
+ if (mode != ImportMode.MERGE) {
+ try {
+ DocViewSAXImporter handler = new DocViewSAXImporter(newParent, newName, newSet, wspFilter);
+ handler.setAclHandling(getAcHandling());
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ SAXParser parser = factory.newSAXParser();
+ parser.parse(file.getInputSource(), handler);
+ info.merge(handler.getInfo());
+ } catch (ParserConfigurationException e) {
+ throw new RepositoryException(e);
+ } catch (SAXException e) {
+ throw new RepositoryException(e);
+ }
+ } else {
+ info.onNop(path);
+ }
+ } else {
+ throw new IllegalArgumentException("Files of type " + file.getSerializationType() + " can't be handled by this handler " + this);
+ }
+ }
+ ValueFactory factory = parent.getSession().getValueFactory();
+ for (Artifact binary: artifacts.values(ArtifactType.BINARY)) {
+ // get parent node
+ Node parentNode = parent;
+ String path = binary.getRelativePath();
+ int idx = path.lastIndexOf('/');
+ if (idx > 0) {
+ parentNode = parent.getNode(path.substring(0, idx));
+ path = path.substring(idx + 1);
+ }
+ // only update binary if import mode is not MERGE
+ if (wspFilter.getImportMode(parentNode.getPath()) != ImportMode.MERGE) {
+ Value value = factory.createValue(binary.getInputStream());
+ if (!parentNode.hasProperty(path)
+ || !value.equals(parentNode.getProperty(path).getValue())) {
+ parent.setProperty(path, value);
+ if (info == null) {
+ info = new ImportInfoImpl();
+ }
+ info.onModified(path);
+ info.onModified(parentNode.getPath());
+ }
+ }
+ }
+ }
+ return info;
+ }
+
+ private Node importFile(ImportInfo info, Node parent, Artifact primary)
+ throws RepositoryException, IOException {
+ String name = primary.getRelativePath();
+ Node fileNode;
+ Node contentNode;
+ if (parent.hasNode(name)) {
+ fileNode = parent.getNode(name);
+ if (!fileNode.isNodeType(JcrConstants.NT_FILE)) {
+ parent.refresh(false);
+ throw new IOException("Incompatible content. Expected a nt:file but was " + fileNode.getPrimaryNodeType().getName());
+ }
+ contentNode = fileNode.getNode(JcrConstants.JCR_CONTENT);
+ info.onNop(fileNode.getPath());
+ } else {
+ fileNode = parent.addNode(name, JcrConstants.NT_FILE);
+ String contentNodeType = primary.getSerializationType() == SerializationType.XML_GENERIC
+ && isExplodeXml() ? getXmlNodeType() : JcrConstants.NT_RESOURCE;
+ contentNode = fileNode.addNode(JcrConstants.JCR_CONTENT, contentNodeType);
+ info.onCreated(fileNode.getPath());
+ info.onCreated(contentNode.getPath());
+ }
+ importNtResource(info, contentNode, primary);
+ return fileNode;
+ }
+
+ private ImportInfoImpl importDocView(Node parent, InputSource source,
+ ArtifactSetImpl artifacts, WorkspaceFilter wspFilter)
+ throws RepositoryException, IOException {
+ String rootName = artifacts.getPrimaryData().getRelativePath();
+ int idx = rootName.indexOf('/');
+ if (idx > 0) {
+ rootName = rootName.substring(0, idx);
+ }
+ DocViewSAXImporter handler = new DocViewSAXImporter(parent, rootName, artifacts, wspFilter);
+ handler.setAclHandling(getAcHandling());
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ SAXParser parser = factory.newSAXParser();
+ parser.parse(source, handler);
+ return handler.getInfo();
+ } catch (ParserConfigurationException e) {
+ throw new RepositoryException(e);
+ } catch (SAXException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ private boolean importNtResource(ImportInfo info, Node content, Artifact artifact)
+ throws RepositoryException, IOException {
+
+ String path = content.getPath();
+ boolean modified = false;
+ if (explodeXml && !content.isNodeType(JcrConstants.NT_RESOURCE)) {
+ // explode xml
+ InputStream in = artifact.getInputStream();
+ try {
+ content.getSession().importXML(path, in, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
+ // can't really augment info here
+ } finally {
+ in.close();
+ }
+ modified = true;
+ } else {
+ ValueFactory factory = content.getSession().getValueFactory();
+ Value value = factory.createValue(artifact.getInputStream());
+ if (!content.hasProperty(JcrConstants.JCR_DATA)
+ || !value.equals(content.getProperty(JcrConstants.JCR_DATA).getValue())) {
+ content.setProperty(JcrConstants.JCR_DATA, value);
+ modified = true;
+ }
+
+ // always update last modified if binary was modified (bug #22969)
+ if (!content.hasProperty(JcrConstants.JCR_LASTMODIFIED) || modified) {
+ Calendar lastMod = Calendar.getInstance();
+ content.setProperty(JcrConstants.JCR_LASTMODIFIED, lastMod);
+ modified = true;
+ }
+
+ if (!content.hasProperty(JcrConstants.JCR_MIMETYPE)) {
+ String mimeType = artifact.getContentType();
+ if (mimeType == null) {
+ mimeType = Text.getName(artifact.getRelativePath(), '.');
+ mimeType = MimeTypes.getMimeType(mimeType, MimeTypes.APPLICATION_OCTET_STREAM);
+ }
+ content.setProperty(JcrConstants.JCR_MIMETYPE, mimeType);
+ modified = true;
+ }
+ if (content.isNew()) {
+ // mark binary data as modified
+ info.onCreated(path + "/" + JcrConstants.JCR_DATA);
+ info.onNop(path);
+ } else if (modified) {
+ // mark binary data as modified
+ info.onModified(path + "/" + JcrConstants.JCR_DATA);
+ info.onModified(path);
+ }
+ }
+ return modified;
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FilteredXMLSerializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FilteredXMLSerializer.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FilteredXMLSerializer.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FilteredXMLSerializer.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.util.xml.serialize.OutputFormat;
+import org.apache.jackrabbit.vault.util.xml.serialize.XMLSerializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * FilteredXMLSerializer extends {@link XMLSerializer} by adding the possibility to
+ * set an element filter for specific namespace URIs and/or raw names.
+ *
+ */
+public class FilteredXMLSerializer extends XMLSerializer {
+
+ private static Logger log = LoggerFactory.getLogger(FilteredXMLSerializer.class);
+
+ private Filter filter = new DefaultFilter();
+
+ public FilteredXMLSerializer(OutputStream outputStream, OutputFormat outputFormat) throws RepositoryException {
+ super(outputStream, outputFormat);
+ }
+
+ public void setFilter(Filter filter) {
+ this.filter = filter;
+ }
+
+ public Filter getFilter() {
+ return filter;
+ }
+
+ public void startElement(String namespaceURI, String localName, String rawName, Attributes attrs) throws SAXException {
+ if (filter.isFilteredNamespace(namespaceURI) || filter.isFilteredRawName(rawName)) {
+ log.debug("Filtering: {" + namespaceURI + "}" + localName + " -> " + rawName);
+ } else {
+ AttributesImpl fAttrs = new AttributesImpl(attrs);
+ for (int i = 0; i < fAttrs.getLength(); i++) {
+ String uri = fAttrs.getURI(i);
+ if (filter.isFilteredNamespace(uri)) {
+ fAttrs.removeAttribute(i);
+ }
+ }
+ super.startElement(namespaceURI, localName, rawName, fAttrs);
+ }
+ }
+
+ public void endElement(String namespaceURI, String localName, String rawName) throws SAXException {
+ if (filter.isFilteredNamespace(namespaceURI) || filter.isFilteredRawName(rawName)) {
+ log.debug("Filtering: {" + namespaceURI + "}" + localName + " -> " + rawName);
+ } else {
+ super.endElement(namespaceURI, localName, rawName);
+ }
+ }
+
+ public void endElementIO(String namespaceURI, String localName, String rawName) throws IOException {
+ if (filter.isFilteredNamespace(namespaceURI) || filter.isFilteredRawName(rawName)) {
+ log.debug("Filtering: {" + namespaceURI + "}" + localName + " -> " + rawName);
+ } else {
+ super.endElementIO(namespaceURI, localName, rawName);
+ }
+ }
+
+ public interface Filter {
+
+ public void addNamespaceFilter(String namespaceURI);
+
+ public void removeNamespaceFilter(String namespaceURI);
+
+ public String[] getNamespaceFilters();
+
+ public void addRawNameFilter(String rawName);
+
+ public void removeRawNameFilter(String rawName);
+
+ public String[] getRawNameFilters();
+
+ public boolean isFilteredNamespace(String namespaceURI);
+
+ public boolean isFilteredRawName(String rawName);
+ }
+
+ /**
+ * Default filter with no entries.
+ */
+ public static class DefaultFilter implements Filter {
+
+ private Set<String> namespaces = new HashSet<String>();
+ private Set<String> rawNames = new HashSet<String>();
+
+ protected DefaultFilter() {
+ }
+
+ public void addNamespaceFilter(String namespaceURI) {
+ namespaces.add(namespaceURI);
+ }
+
+ public void removeNamespaceFilter(String namespaceURI) {
+ namespaces.remove(namespaceURI);
+ }
+
+ public String[] getNamespaceFilters() {
+ return namespaces.toArray(new String[namespaces.size()]);
+ }
+
+ public void addRawNameFilter(String rawName) {
+ rawNames.add(rawName);
+ }
+
+ public void removeRawNameFilter(String rawName) {
+ rawNames.remove(rawName);
+ }
+
+ public String[] getRawNameFilters() {
+ return rawNames.toArray(new String[rawNames.size()]);
+ }
+
+ public boolean isFilteredNamespace(String namespaceURI) {
+ return namespaces.contains(namespaceURI);
+ }
+
+ public boolean isFilteredRawName(String rawName) {
+ return rawNames.contains(rawName);
+ }
+ }
+}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FolderArtifactHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FolderArtifactHandler.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FolderArtifactHandler.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FolderArtifactHandler.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.fs.api.Artifact;
+import org.apache.jackrabbit.vault.fs.api.ArtifactType;
+import org.apache.jackrabbit.vault.fs.api.ImportMode;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.impl.ArtifactSetImpl;
+import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
+import org.apache.jackrabbit.vault.util.JcrConstants;
+
+/**
+ * Handles artifact sets with just a directory.
+ *
+ */
+public class FolderArtifactHandler extends AbstractArtifactHandler {
+
+ /**
+ * node type to use for the folders
+ */
+ private String nodeType = JcrConstants.NT_FOLDER;
+
+ /**
+ * Returns the node type that is used to create folders.
+ * @return the node type name.
+ */
+ public String getNodeType() {
+ return nodeType;
+ }
+
+ /**
+ * Sets the node type name that is used to create folders. Default is "nt:folder"
+ * @param nodeType the node type name
+ */
+ public void setNodeType(String nodeType) {
+ this.nodeType = nodeType;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Handles generic artifact sets
+ */
+ public ImportInfoImpl accept(WorkspaceFilter wspFilter, Node parent, String name,
+ ArtifactSetImpl artifacts)
+ throws RepositoryException, IOException {
+ Artifact dir = artifacts.getDirectory();
+ if (dir == null || artifacts.size() != 1) {
+ return null;
+ }
+ ImportInfoImpl info = new ImportInfoImpl();
+ if (dir.getRelativePath().length() == 0) {
+ // special check if artifact addresses itself
+ return info;
+ }
+ if (!parent.hasNode(dir.getRelativePath())) {
+ Node node = parent.addNode(dir.getRelativePath(), nodeType);
+ info.onCreated(node.getPath());
+ } else {
+ // sync nodes
+ Set<String> hints = new HashSet<String>();
+ String rootPath = parent.getPath();
+ if (!rootPath.equals("/")) {
+ rootPath += "/";
+ }
+ for (Artifact a: artifacts.values(ArtifactType.HINT)) {
+ hints.add(rootPath + a.getRelativePath());
+ }
+
+ Node node = parent.getNode(dir.getRelativePath());
+ NodeIterator iter = node.getNodes();
+ while (iter.hasNext()) {
+ Node child = iter.nextNode();
+ String path = child.getPath();
+ if (wspFilter.contains(path)) {
+ if (wspFilter.getImportMode(path) == ImportMode.REPLACE) {
+ if (!hints.contains(path)) {
+ // if the child is in the filter, it belongs to
+ // this aggregate and needs to be removed
+ if (getAclManagement().isACLNode(child)) {
+ if (acHandling == AccessControlHandling.OVERWRITE
+ || acHandling == AccessControlHandling.CLEAR) {
+ info.onDeleted(path);
+ getAclManagement().clearACL(node);
+ }
+ } else {
+ info.onDeleted(path);
+ child.remove();
+ }
+ } else if (acHandling == AccessControlHandling.CLEAR
+ && getAclManagement().isACLNode(child)) {
+ info.onDeleted(path);
+ getAclManagement().clearACL(node);
+ }
+ }
+ }
+ }
+
+ }
+ return info;
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/GenericArtifactHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/GenericArtifactHandler.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/GenericArtifactHandler.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/GenericArtifactHandler.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io;
+
+import java.io.IOException;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.jackrabbit.vault.fs.api.Artifact;
+import org.apache.jackrabbit.vault.fs.api.ImportMode;
+import org.apache.jackrabbit.vault.fs.api.SerializationType;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.impl.ArtifactSetImpl;
+import org.apache.jackrabbit.vault.fs.spi.ACLManagement;
+import org.apache.jackrabbit.vault.fs.spi.ServiceProviderFactory;
+import org.apache.jackrabbit.vault.fs.spi.UserManagement;
+import org.apache.jackrabbit.vault.util.PathUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Handles docview artifacts.
+ *
+ */
+public class GenericArtifactHandler extends AbstractArtifactHandler {
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(GenericArtifactHandler.class);
+
+ private UserManagement userManagement = ServiceProviderFactory.getProvider().getUserManagement();
+
+ private ACLManagement aclManagement = ServiceProviderFactory.getProvider().getACLManagement();
+
+ /**
+ * {@inheritDoc}
+ *
+ * Handles generic artifact sets
+ */
+ public ImportInfoImpl accept(WorkspaceFilter wspFilter, Node parent,
+ String name, ArtifactSetImpl artifacts)
+ throws RepositoryException, IOException {
+ Artifact primary = artifacts.getPrimaryData();
+ if (primary == null) {
+ return null;
+ }
+
+ // check type of primary artifact
+ ImportInfoImpl info = null;
+ InputSource source = primary.getInputSource();
+ if (source != null && primary.getSerializationType() == SerializationType.XML_DOCVIEW) {
+ // primary docview artifact. don't except to have additional
+ // extra content artifacts
+ info = new ImportInfoImpl();
+ String path = PathUtil.getPath(parent, name);
+ if (name.length() == 0 || parent.hasNode(name)) {
+ if (wspFilter.getImportMode(path) == ImportMode.MERGE) {
+ // do import the content if node is an authorizable or ACL
+ Node newNode = parent.getNode(name);
+ if (userManagement.isAuthorizableNodeType(newNode.getPrimaryNodeType().getName())) {
+ log.debug("don't skip authorizable node on MERGE: {}", path);
+ } else if (aclManagement.isACLNode(newNode)) {
+ log.debug("don't skip policy node on MERGE: {}", path);
+ } else {
+ info.onNop(path);
+ return info;
+ }
+ }
+ }
+ try {
+ DocViewSAXImporter handler = new DocViewSAXImporter(parent, name, artifacts, wspFilter);
+ handler.setAclHandling(getAcHandling());
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ factory.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ SAXParser parser = factory.newSAXParser();
+ parser.parse(source, handler);
+ info.merge(handler.getInfo());
+ } catch (ParserConfigurationException e) {
+ throw new RepositoryException(e);
+ } catch (SAXException e) {
+ info = new ImportInfoImpl();
+ info.onError(path, e);
+ log.error("Error while parsing {}: {}", source.getSystemId(), e);
+ }
+ }
+ return info;
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/ImportInfoImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/ImportInfoImpl.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/ImportInfoImpl.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/ImportInfoImpl.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.version.Version;
+
+import org.apache.jackrabbit.vault.fs.api.ImportInfo;
+import org.apache.jackrabbit.vault.fs.api.NodeNameList;
+import org.apache.jackrabbit.vault.util.JcrConstants;
+import org.apache.jackrabbit.vault.util.PathComparator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>ImportInfo</code>...
+ *
+ */
+public class ImportInfoImpl implements ImportInfo {
+
+ /**
+ * the default logger
+ */
+ static final Logger log = LoggerFactory.getLogger(ImportInfoImpl.class);
+
+ private final TreeMap<String, Type> mods = new TreeMap<String, Type>(new PathComparator());
+
+ private final Map<String, Exception> errorMap = new HashMap<String, Exception>();
+
+ private Map<String, String> remapped;
+
+ /**
+ * list of uuids of nodes that need to be checked-in after the import
+ */
+ private final Set<String> toVersion = new LinkedHashSet<String>();
+
+ private NodeNameList nameList;
+
+ private Node node;
+
+ private int numModified;
+
+ private Map<String, String[]> memberships;
+
+ public static ImportInfo create(ImportInfo base) {
+ if (base == null) {
+ return new ImportInfoImpl();
+ } else {
+ return base;
+ }
+ }
+
+ public ImportInfoImpl() {
+ }
+
+ public ImportInfoImpl merge(ImportInfo base) {
+ if (base instanceof ImportInfoImpl) {
+ ImportInfoImpl baseImpl = (ImportInfoImpl) base;
+ mods.putAll(baseImpl.mods);
+ errorMap.putAll(baseImpl.errorMap);
+ numModified +=baseImpl.numModified;
+ toVersion.addAll(baseImpl.toVersion);
+ // also merge node and name list if not set yet
+ if (node == null) {
+ node = baseImpl.node;
+ nameList = baseImpl.nameList;
+ }
+ if (remapped == null) {
+ remapped = baseImpl.remapped;
+ } else {
+ remapped.putAll(baseImpl.getRemapped());
+ }
+ if (memberships == null) {
+ memberships = baseImpl.memberships;
+ } else {
+ memberships.putAll(baseImpl.getMemberships());
+ }
+ }
+ return this;
+ }
+
+ public NodeNameList getNameList() {
+ return nameList;
+ }
+
+ public void setNameList(NodeNameList nameList) {
+ this.nameList = nameList;
+ }
+
+ /**
+ * Returns the root node of this import.
+ * @return root node if this import or <code>null</code>
+ */
+ public Node getNode() {
+ return node;
+ }
+
+ public void setNode(Node node) {
+ this.node = node;
+ }
+
+ public void onModified(String path) {
+ Type prev = mods.get(path);
+ if (prev == null || prev != Type.CRE) {
+ addMod(path, Type.MOD);
+ }
+ }
+
+ public void onNop(String path) {
+ if (!mods.containsKey(path)) {
+ addMod(path, Type.NOP);
+ }
+ }
+
+ public void onCreated(String path) {
+ addMod(path, Type.CRE);
+ }
+
+ public void onDeleted(String path) {
+ addMod(path, Type.DEL);
+ }
+
+ public void onReplaced(String path) {
+ addMod(path, Type.REP);
+ }
+
+ public void onMissing(String path) {
+ addMod(path, Type.MIS);
+ }
+
+ public void onError(String path, Exception e) {
+ addMod(path, Type.ERR);
+ errorMap.put(path, e);
+ }
+
+ public void onRemapped(String oldPath, String newPath) {
+ if (remapped == null) {
+ remapped = new HashMap<String, String>();
+ }
+ remapped.put(oldPath, newPath);
+ }
+
+ public Map<String, String> getRemapped() {
+ return remapped == null ? Collections.<String, String>emptyMap() : remapped;
+ }
+
+ private void addMod(String path, Type mod) {
+ // don't overwrite errors
+ if (mods.get(path) != Type.ERR) {
+ mods.put(path, mod);
+ if (mod != Type.NOP) {
+ numModified++;
+ }
+ }
+ log.debug("{} {}", mod, path);
+ }
+
+ public TreeMap<String, Type> getModifications() {
+ return mods;
+ }
+
+ public Exception getError(String path) {
+ return errorMap.get(path);
+ }
+
+ public Collection<String> getToVersion() {
+ return toVersion;
+ }
+
+ public void registerToVersion(String path) {
+ toVersion.add(path);
+ }
+
+ public void checkinNodes(Session session) {
+ Iterator<String> iter = toVersion.iterator();
+ while (iter.hasNext()) {
+ String path = iter.next();
+ iter.remove();
+ try {
+ Node node = session.getNode(path);
+ // check if node is really versionable. SPI might not have known it at the time
+ // this node was registered for versioning
+ if (node.isNodeType(JcrConstants.MIX_VERSIONABLE)) {
+ try {
+ Version v = node.checkin();
+ log.info("Checked in versionable node {} (v={})", path, v.getName());
+ } catch (RepositoryException e) {
+ log.error("Error while checkin node {}: {}", path, e.toString());
+ }
+ }
+ } catch (RepositoryException e) {
+ log.error("Error while retrieving node to be versioned at {}.", path, e);
+ }
+ }
+ }
+
+ public int numModified() {
+ return numModified;
+ }
+
+ public int numErrors() {
+ return errorMap.size();
+ }
+
+ public void registerMemberships(String id, String[] members) {
+ if (memberships == null) {
+ memberships = new HashMap<String, String[]>();
+ }
+ memberships.put(id, members);
+ }
+
+ public Map<String, String[]> getMemberships() {
+ return memberships == null ? Collections.<String, String[]>emptyMap() : memberships;
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/InputSourceArtifact.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/InputSourceArtifact.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/InputSourceArtifact.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/InputSourceArtifact.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.fs.api.AccessType;
+import org.apache.jackrabbit.vault.fs.api.Artifact;
+import org.apache.jackrabbit.vault.fs.api.ArtifactType;
+import org.apache.jackrabbit.vault.fs.api.ImportArtifact;
+import org.apache.jackrabbit.vault.fs.api.SerializationType;
+import org.apache.jackrabbit.vault.fs.api.VaultInputSource;
+import org.apache.jackrabbit.vault.fs.impl.AbstractArtifact;
+import org.xml.sax.InputSource;
+
+/**
+ * Implements an artifact that is based on a {@link InputSource}.
+ *
+ */
+public class InputSourceArtifact extends AbstractArtifact implements ImportArtifact {
+
+ /**
+ * the input source
+ */
+ private final VaultInputSource source;
+
+ private final SerializationType serType;
+
+ /**
+ * Constructs a compatible artifact of the given base one.
+ *
+ * @param base the base artifact
+ * @param source the input source
+ */
+ public InputSourceArtifact(Artifact base, VaultInputSource source) {
+ super(base, base.getType());
+ this.source = source;
+ this.serType = base.getSerializationType();
+ setContentType(base.getContentType());
+ }
+
+ /**
+ * Constructs a new artifact for the given source. the parent artifact is
+ * only used for generating the paths and is not linked to this artifact.
+ *
+ * @param parent the parent artifact
+ * @param repoName the repository name
+ * @param extension the platform extension
+ * @param type the type of the artifact
+ * @param source the input source of the artifact
+ * @param serType the serialization type
+ */
+ public InputSourceArtifact(Artifact parent, String repoName, String extension,
+ ArtifactType type, VaultInputSource source,
+ SerializationType serType) {
+ super(parent, repoName, extension, type);
+ this.source = source;
+ this.serType = serType;
+ }
+
+ /**
+ * Creates a new input source artifact based on a given one.
+ * @param isa the base source artifact
+ * @param type the new type.
+ */
+ public InputSourceArtifact(InputSourceArtifact isa, ArtifactType type) {
+ super(isa, type);
+ this.source = isa.source;
+ this.serType = isa.serType;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public SerializationType getSerializationType() {
+ return serType;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return {@link AccessType#STREAM} always.
+ */
+ public AccessType getPreferredAccess() {
+ return AccessType.STREAM;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public InputStream getInputStream()
+ throws IOException, RepositoryException {
+ return source.getByteStream();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the underlying source
+ */
+ public VaultInputSource getInputSource()
+ throws IOException, RepositoryException {
+ return source;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastModified() {
+ return source.getLastModified();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getContentLength() {
+ return source.getContentLength();
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/NodeTypeArtifactHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/NodeTypeArtifactHandler.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/NodeTypeArtifactHandler.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/NodeTypeArtifactHandler.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.fs.api.Artifact;
+import org.apache.jackrabbit.vault.fs.api.ImportMode;
+import org.apache.jackrabbit.vault.fs.api.SerializationType;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.impl.ArtifactSetImpl;
+import org.apache.jackrabbit.vault.util.PathUtil;
+
+/**
+ * Creates nt:nodeType structures from {@link SerializationType#CND} artifacts.
+ *
+ */
+public class NodeTypeArtifactHandler extends AbstractArtifactHandler {
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * Handles generic artifact sets
+ */
+ protected ImportInfoImpl accept(WorkspaceFilter wspFilter, Node parent,
+ String name, ArtifactSetImpl artifacts)
+ throws RepositoryException, IOException {
+ // need at least one primary data
+ Artifact primary = artifacts.getPrimaryData();
+ if (primary == null) {
+ return null;
+ }
+ if (artifacts.size() != 1) {
+ return null;
+ }
+ if (primary.getSerializationType() != SerializationType.CND) {
+ return null;
+ }
+ String path = PathUtil.getPath(parent, primary.getRelativePath());
+ if (wspFilter.getImportMode(path) == ImportMode.MERGE) {
+ ImportInfoImpl info = new ImportInfoImpl();
+ info.onNop(path);
+ return info;
+ }
+ // do import
+ CNDImporter importer = new CNDImporter();
+ InputStream in = primary.getInputStream();
+ try {
+ Reader r = new InputStreamReader(in, "utf-8");
+ return importer.doImport(parent, primary.getRelativePath(), r, primary.getRelativePath());
+ } finally {
+ in.close();
+ }
+ }
+
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/XmlAnalyzer.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/XmlAnalyzer.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/XmlAnalyzer.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/XmlAnalyzer.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.vault.fs.api.SerializationType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.InputSource;
+
+/**
+ * Analyzes a xml source and guesses the type. the following types are
+ * recognized:
+ * <ul>
+ * <li> {@link SerializationType#GENERIC} if the source is not a valid XML
+ * <li> {@link SerializationType#XML_GENERIC} if the XML type is not known. eg. a user-xml
+ * <li> {@link SerializationType#XML_DOCVIEW} if the XML is a docview serialization
+ * </ul>
+ * Please note, that the docview serialization is recognized if the first
+ * element contains a jcr:primaryType attribute.
+ *
+ */
+public class XmlAnalyzer {
+
+ /**
+ * the default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(XmlAnalyzer.class);
+
+ private XmlAnalyzer() {
+ }
+
+ /**
+ * Analyzes the given source.
+ *
+ * @param source the source to analyze
+ * @return the serialization type
+ * @throws IOException if an I/O error occurs
+ */
+ public static SerializationType analyze(InputSource source) throws IOException {
+ Reader r = source.getCharacterStream();
+ SerializationType type = SerializationType.UNKOWN;
+ if (r == null) {
+ if (source.getEncoding() == null) {
+ r = new InputStreamReader(source.getByteStream());
+ } else {
+ r = new InputStreamReader(source.getByteStream(), source.getEncoding());
+ }
+ }
+ try {
+ // read a couple of chars...1024 should be enough
+ char[] buffer = new char[1024];
+ int pos = 0;
+ while (pos<buffer.length) {
+ int read = r.read(buffer, pos, buffer.length - pos);
+ if (read < 0) {
+ break;
+ }
+ pos+=read;
+ }
+ String str = new String(buffer, 0, pos);
+ // check for docview
+ if (str.contains("<jcr:root ") && str.contains("\"http://www.jcp.org/jcr/1.0\"")) {
+ type = SerializationType.XML_DOCVIEW;
+ } else if (str.contains("<?xml ")) {
+ type = SerializationType.XML_GENERIC;
+ } else {
+ type = SerializationType.GENERIC;
+ }
+ } finally {
+ IOUtils.closeQuietly(r);
+ }
+ log.debug("Analyzed {}. Type = {}", source.getSystemId(), type);
+ return type;
+ }
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/legacycnd/Lexer.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/legacycnd/Lexer.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/legacycnd/Lexer.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/legacycnd/Lexer.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io.legacycnd;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StreamTokenizer;
+
+/**
+ * This is copied from jackrabbit-spi-commons-1.6
+ *
+ * Lexer
+ */
+public class Lexer {
+ public static final char SINGLE_QUOTE = '\'';
+ public static final char DOUBLE_QUOTE = '\"';
+ public static final char BEGIN_NODE_TYPE_NAME = '[';
+ public static final char END_NODE_TYPE_NAME = ']';
+ public static final char EXTENDS = '>';
+ public static final char LIST_DELIMITER = ',';
+ public static final char PROPERTY_DEFINITION = '-';
+ public static final char CHILD_NODE_DEFINITION = '+';
+ public static final char BEGIN_TYPE = '(';
+ public static final char END_TYPE = ')';
+ public static final char DEFAULT = '=';
+ public static final char CONSTRAINT = '<';
+
+ public static final String[] ORDERABLE = new String[] {"orderable", "ord", "o"};
+ public static final String[] MIXIN = new String[]{"mixin", "mix", "m"};
+
+ public static final String[] PRIMARY = new String[]{"primary", "pri", "!"};
+ public static final String[] AUTOCREATED = new String[]{"autocreated", "aut", "a"};
+ public static final String[] MANDATORY = new String[]{"mandatory", "man", "m"};
+ public static final String[] PROTECTED = new String[]{"protected", "pro", "p"};
+ public static final String[] MULTIPLE = new String[]{"multiple", "mul", "*"};
+
+ public static final String[] COPY = new String[]{"copy", "Copy", "COPY"};
+ public static final String[] VERSION = new String[]{"version", "Version", "VERSION"};
+ public static final String[] INITIALIZE = new String[]{"initialize", "Initialize", "INITIALIZE"};
+ public static final String[] COMPUTE = new String[]{"compute", "Compute", "COMPUTE"};
+ public static final String[] IGNORE = new String[]{"ignore", "Ignore", "IGNORE"};
+ public static final String[] ABORT = new String[]{"abort", "Abort", "ABORT"};
+
+ public static final String[] ATTRIBUTE = new String[]{"primary", "pri", "!",
+ "autocreated", "aut", "a",
+ "mandatory", "man", "m",
+ "protected", "pro", "p",
+ "multiple", "mul", "*",
+ "copy", "Copy", "COPY",
+ "version", "Version", "VERSION",
+ "initialize", "Initialize", "INITIALIZE",
+ "compute", "Compute", "COMPUTE",
+ "ignore", "Ignore", "IGNORE",
+ "abort", "Abort", "ABORT"};
+
+ public static final String[] STRING = {"string", "String", "STRING"};
+ public static final String[] BINARY = {"binary", "Binary", "BINARY"};
+ public static final String[] LONG = {"long", "Long", "LONG"};
+ public static final String[] DOUBLE = {"double", "Double", "DOUBLE"};
+ public static final String[] BOOLEAN = {"boolean", "Boolean", "BOOLEAN"};
+ public static final String[] DATE = {"date", "Date", "DATE"};
+ public static final String[] NAME = {"name", "Name", "NAME"};
+ public static final String[] PATH = {"path", "Path", "PATH"};
+ public static final String[] REFERENCE = {"reference", "Reference", "REFERENCE"};
+
+ public static final String[] UNDEFINED = new String[]{"undefined", "Undefined", "UNDEFINED", "*"};
+
+ public static final String EOF = "eof";
+
+ private final StreamTokenizer st;
+
+ private final String systemId;
+
+ /**
+ * Constructor
+ * @param r
+ */
+ public Lexer(Reader r, String systemId) {
+ this.systemId = systemId;
+ st = new StreamTokenizer(r);
+
+ st.eolIsSignificant(false);
+
+ st.lowerCaseMode(false);
+
+ st.slashSlashComments(true);
+ st.slashStarComments(true);
+
+ st.wordChars('a', 'z');
+ st.wordChars('A', 'Z');
+ st.wordChars(':', ':');
+ st.wordChars('_', '_');
+
+ st.quoteChar(SINGLE_QUOTE);
+ st.quoteChar(DOUBLE_QUOTE);
+
+ st.ordinaryChar(BEGIN_NODE_TYPE_NAME);
+ st.ordinaryChar(END_NODE_TYPE_NAME);
+ st.ordinaryChar(EXTENDS);
+ st.ordinaryChar(LIST_DELIMITER);
+ st.ordinaryChar(PROPERTY_DEFINITION);
+ st.ordinaryChar(CHILD_NODE_DEFINITION);
+ st.ordinaryChar(BEGIN_TYPE);
+ st.ordinaryChar(END_TYPE);
+ st.ordinaryChar(DEFAULT);
+ st.ordinaryChar(CONSTRAINT);
+ }
+
+ /**
+ * getNextToken
+ *
+ * @return
+ * @throws ParseException
+ */
+ public String getNextToken() throws ParseException {
+ try {
+ int tokenType = st.nextToken();
+ if (tokenType == StreamTokenizer.TT_EOF) {
+ return EOF;
+ } else if (tokenType == StreamTokenizer.TT_WORD
+ || tokenType == SINGLE_QUOTE
+ || tokenType == DOUBLE_QUOTE) {
+ return st.sval;
+ } else if (tokenType == StreamTokenizer.TT_NUMBER) {
+ return String.valueOf(st.nval);
+ } else {
+ return new String(new char[] {(char) tokenType});
+ }
+ } catch (IOException e) {
+ fail("IOException while attempting to read input stream", e);
+ return null;
+ }
+ }
+
+ public void fail(String message) throws ParseException {
+ throw new ParseException(message, st.lineno(), -1, systemId);
+ }
+
+ public void fail(String message, Throwable e) throws ParseException {
+ throw new ParseException(message, e, st.lineno(), -1, systemId);
+ }
+
+ public void fail(Throwable e) throws ParseException {
+ throw new ParseException(e, st.lineno(), -1, systemId);
+ }
+}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/legacycnd/ParseException.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/legacycnd/ParseException.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/legacycnd/ParseException.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/legacycnd/ParseException.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.impl.io.legacycnd;
+
+/**
+ * This is copied from jackrabbit-spi-commons-1.6
+ *
+ * ParseException
+ */
+public class ParseException extends Exception {
+
+ /**
+ * the line number where the error occurred
+ */
+ private final int lineNumber;
+
+ /**
+ * the column number where the error occurred
+ */
+ private final int colNumber;
+
+ /**
+ * the systemid of the source that produced the error
+ */
+ private final String systemId;
+
+
+ /**
+ * Constructs a new instance of this class with <code>null</code> as its
+ * detail message.
+ */
+ public ParseException(int lineNumber, int colNumber, String systemId) {
+ super();
+ this.lineNumber = lineNumber;
+ this.colNumber = colNumber;
+ this.systemId = systemId;
+ }
+
+ /**
+ * Constructs a new instance of this class with the specified detail
+ * message.
+ *
+ * @param message the detail message. The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ */
+ public ParseException(String message, int lineNumber, int colNumber, String systemId) {
+ super(message);
+ this.lineNumber = lineNumber;
+ this.colNumber = colNumber;
+ this.systemId = systemId;
+ }
+
+ /**
+ * Constructs a new instance of this class with the specified detail
+ * message and root cause.
+ *
+ * @param message the detail message. The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ * @param rootCause root failure cause
+ */
+ public ParseException(String message, Throwable rootCause, int lineNumber, int colNumber, String systemId) {
+ super(message, rootCause);
+ this.lineNumber = lineNumber;
+ this.colNumber = colNumber;
+ this.systemId = systemId;
+ }
+
+ /**
+ * Constructs a new instance of this class with the specified root cause.
+ *
+ * @param rootCause root failure cause
+ */
+ public ParseException(Throwable rootCause, int lineNumber, int colNumber, String systemId) {
+ super(rootCause);
+ this.lineNumber = lineNumber;
+ this.colNumber = colNumber;
+ this.systemId = systemId;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getMessage() {
+ StringBuffer b = new StringBuffer(super.getMessage());
+ String delim = " (";
+ if (systemId != null && !systemId.equals("")) {
+ b.append(delim);
+ b.append(systemId);
+ delim = ", ";
+ }
+ if (lineNumber >= 0) {
+ b.append(delim);
+ b.append("line ");
+ b.append(lineNumber);
+ delim = ", ";
+ }
+ if (colNumber >= 0) {
+ b.append(delim);
+ b.append("col ");
+ b.append(colNumber);
+ delim = ", ";
+ }
+ if (delim.equals(", ")) {
+ b.append(")");
+ }
+ return b.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return super.toString(); // + " (" + systemId + ", line " + lineNumber +", col " + colNumber +")";
+ }
+
+}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractArchive.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractArchive.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractArchive.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractArchive.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.io;
+
+import java.io.IOException;
+
+import org.apache.jackrabbit.vault.util.Constants;
+import org.apache.jackrabbit.vault.util.Text;
+
+/**
+ * <code>AbstractArchive</code>...
+ */
+abstract class AbstractArchive implements Archive {
+
+ public Entry getEntry(String path) throws IOException {
+ String[] segs = Text.explode(path, '/');
+ Entry root = getRoot();
+ for (String name: segs) {
+ root = root.getChild(name);
+ if (root == null) {
+ break;
+ }
+ }
+ return root;
+ }
+
+ public Entry getJcrRoot() throws IOException {
+ return getRoot().getChild(Constants.ROOT_DIR);
+ }
+
+ public Archive getSubArchive(String rootPath, boolean asJcrRoot) throws IOException {
+ Entry root = getEntry(rootPath);
+ return root == null ? null : new SubArchive(this, root, asJcrRoot);
+ }
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractExporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractExporter.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractExporter.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractExporter.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,313 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeManager;
+
+import org.apache.jackrabbit.util.ISO8601;
+import org.apache.jackrabbit.vault.fs.api.AggregateManager;
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
+import org.apache.jackrabbit.vault.fs.api.SimplePathMapping;
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.config.MetaInf;
+import org.apache.jackrabbit.vault.fs.spi.CNDWriter;
+import org.apache.jackrabbit.vault.fs.spi.ProgressTracker;
+import org.apache.jackrabbit.vault.fs.spi.ServiceProviderFactory;
+import org.apache.jackrabbit.vault.util.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Generic context for exporters
+ *
+ */
+public abstract class AbstractExporter {
+
+ /**
+ * default logger
+ */
+ private static final Logger log = LoggerFactory.getLogger(AbstractExporter.class);
+
+ private ProgressTracker tracker;
+
+ private boolean relativePaths;
+
+ private String rootPath = Constants.ROOT_DIR;
+
+ private Properties properties = new Properties();
+
+ private boolean noMetaInf;
+
+ protected ExportInfo exportInfo = new ExportInfo();
+
+ public boolean isVerbose() {
+ return tracker != null;
+ }
+
+ public void setVerbose(ProgressTrackerListener out) {
+ if (out == null) {
+ tracker = null;
+ } else {
+ if (tracker == null) {
+ tracker = new ProgressTracker();
+ }
+ tracker.setListener(out);
+ }
+ }
+
+ public boolean isRelativePaths() {
+ return relativePaths;
+ }
+
+ public void setProperty(String name, String value) {
+ properties.put(name, value);
+ }
+
+ public void setProperty(String name, Calendar value) {
+ properties.put(name, ISO8601.format(value));
+ }
+
+ public void setProperties(Properties properties) {
+ if (properties != null) {
+ this.properties.putAll(properties);
+ }
+ }
+
+ public String getRootPath() {
+ return rootPath;
+ }
+
+ public void setRootPath(String rootPath) {
+ this.rootPath = rootPath;
+ }
+
+ public boolean isNoMetaInf() {
+ return noMetaInf;
+ }
+
+ public void setNoMetaInf(boolean noMetaInf) {
+ this.noMetaInf = noMetaInf;
+ }
+
+ public ExportInfo getExportInfo() {
+ return exportInfo;
+ }
+
+ /**
+ * Defines if the exported files should include their entire path or just
+ * be relative to the export root. eg.: exporting /apps/components relative
+ * would not include /apps in the path.
+ *
+ * @param relativePaths relative flag
+ */
+ public void setRelativePaths(boolean relativePaths) {
+ this.relativePaths = relativePaths;
+ }
+
+ /**
+ * Exports the given vault file and writes the META-INF data.
+ * @param parent the vault file
+ * @throws RepositoryException if an error occurs
+ * @throws IOException if an I/O error occurs
+ */
+ public void export(VaultFile parent) throws RepositoryException, IOException {
+ export(parent, false);
+ }
+
+ /**
+ * Exports the given vault file and writes the META-INF data.
+ * @param parent the vault file
+ * @param noClose if <code>true</code> exporter will not be closed after export
+ * @throws RepositoryException if an error occurs
+ * @throws IOException if an I/O error occurs
+ */
+ public void export(VaultFile parent, boolean noClose)
+ throws RepositoryException, IOException {
+ exportInfo.getEntries().clear();
+ open();
+ AggregateManager mgr = parent.getFileSystem().getAggregateManager();
+ mgr.startTracking(tracker == null ? null : tracker.getListener());
+ if (!noMetaInf) {
+ createDirectory(Constants.META_INF);
+ createDirectory(Constants.META_DIR);
+ // add some 'fake' tracking
+ track("A", Constants.META_INF);
+ track("A", Constants.META_DIR);
+ track("A", Constants.META_DIR + "/" + Constants.CONFIG_XML);
+ track("A", Constants.META_DIR + "/" + Constants.FILTER_XML);
+ track("A", Constants.META_DIR + "/" + Constants.NODETYPES_CND);
+ track("A", Constants.META_DIR + "/" + Constants.PROPERTIES_XML);
+ writeFile(mgr.getConfig().getSource(), Constants.META_DIR + "/" + Constants.CONFIG_XML);
+ // get filter and translate if necessary
+ WorkspaceFilter filter = mgr.getWorkspaceFilter();
+ String mountPath = mgr.getRoot().getPath();
+ String rootPath = parent.getPath();
+ if (rootPath.equals("/")) {
+ rootPath = "";
+ }
+ if (mountPath.length() > 0 || rootPath.length() > 0) {
+ filter = filter.translate(new SimplePathMapping(mountPath, rootPath));
+ }
+ writeFile(filter.getSource(), Constants.META_DIR + "/" + Constants.FILTER_XML);
+ }
+ export(parent, "");
+ if (!noMetaInf) {
+ writeFile(getNodeTypes(mgr.getSession(), mgr.getNodeTypes()), Constants.META_DIR + "/" + Constants.NODETYPES_CND);
+ // update properties
+ setProperty(MetaInf.CREATED, Calendar.getInstance());
+ setProperty(MetaInf.CREATED_BY, mgr.getUserId());
+ setProperty(MetaInf.PACKAGE_FORMAT_VERSION, String.valueOf(MetaInf.FORMAT_VERSION_2));
+ ByteArrayOutputStream tmpOut = new ByteArrayOutputStream();
+ properties.storeToXML(tmpOut, "FileVault Package Properties", "utf-8");
+ writeFile(new ByteArrayInputStream(tmpOut.toByteArray()), Constants.META_DIR + "/" + Constants.PROPERTIES_XML);
+ }
+ if (!noClose) {
+ close();
+ }
+ mgr.stopTracking();
+ }
+
+ /**
+ * Exports the vault file to the relative path.
+ * @param parent the file
+ * @param relPath the path
+ * @throws RepositoryException if an error occurs
+ * @throws IOException if an I/O error occurs
+ */
+ public void export(VaultFile parent, String relPath)
+ throws RepositoryException, IOException {
+ for (VaultFile vaultFile : parent.getChildren()) {
+ String path = relPath + "/" + vaultFile.getName();
+ if (vaultFile.isDirectory()) {
+ createDirectory(vaultFile, path);
+ export(vaultFile, path);
+ } else {
+ writeFile(vaultFile, path);
+ }
+ }
+ }
+
+ protected void track(String action, String path) {
+ if ("E".equals(action)) {
+ log.error("{} {}", action, path);
+ } else {
+ log.debug("{} {}", action, path);
+ }
+ if (tracker != null) {
+ tracker.track(action, path);
+ }
+ }
+
+ protected void track(Exception e, String path) {
+ log.error("E {} ({})", path, e.toString());
+ if (tracker != null) {
+ tracker.track(e, path);
+ }
+ }
+
+ protected String getPlatformFilePath(VaultFile file, String relPath) {
+ StringBuilder buf = new StringBuilder(rootPath);
+ if (isRelativePaths()) {
+ // relative paths are only needed for special exports, like the definition export of packaging
+ if (buf.length() > 0) {
+ buf.append("/");
+ }
+ buf.append(relPath);
+ } else {
+ buf.append(file.getPath());
+ }
+ return buf.toString();
+ }
+
+ private InputStream getNodeTypes(Session s, Collection<String> nodeTypes)
+ throws IOException, RepositoryException {
+ NodeTypeManager ntMgr = s.getWorkspace().getNodeTypeManager();
+ // init with repository predefined node types
+ Set<String> written = new HashSet<String>();
+ written.addAll(ServiceProviderFactory.getProvider().getBuiltInNodeTypeNames());
+ StringWriter out = new StringWriter();
+ CNDWriter w = ServiceProviderFactory.getProvider().getCNDWriter(out, s, true);
+ for (String nt: nodeTypes) {
+ writeNodeType(ntMgr.getNodeType(nt), w, written);
+ }
+ w.close();
+ return new ByteArrayInputStream(out.getBuffer().toString().getBytes("utf-8"));
+ }
+
+ private void writeNodeType(NodeType nt, CNDWriter w, Set<String> written)
+ throws IOException, RepositoryException {
+ if (nt != null && !written.contains(nt.getName())) {
+ written.add(nt.getName());
+ w.write(nt);
+ for (NodeType s: nt.getSupertypes()) {
+ writeNodeType(s, w, written);
+ }
+ for (NodeDefinition n: nt.getChildNodeDefinitions()) {
+ writeNodeType(n.getDefaultPrimaryType(), w, written);
+ if (n.getRequiredPrimaryTypes() != null) {
+ for (NodeType r: n.getRequiredPrimaryTypes()) {
+ writeNodeType(r, w, written);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Opens the exporter and initializes the undelying structures.
+ * @throws IOException if an I/O error occurs
+ * @throws RepositoryException if a repository error occurs
+ */
+ public abstract void open() throws IOException, RepositoryException;
+
+ /**
+ * Closes the exporter and releases the undelying structures.
+ * @throws IOException if an I/O error occurs
+ * @throws RepositoryException if a repository error occurs
+ */
+ public abstract void close() throws IOException, RepositoryException;
+
+ public abstract void createDirectory(String relPath)
+ throws IOException;
+
+ public abstract void createDirectory(VaultFile file, String relPath)
+ throws RepositoryException, IOException;
+
+ public abstract void writeFile(InputStream in, String relPath)
+ throws IOException;
+
+ public abstract void writeFile(VaultFile file, String relPath)
+ throws RepositoryException, IOException;
+
+}
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AccessControlHandling.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AccessControlHandling.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AccessControlHandling.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AccessControlHandling.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.apache.jackrabbit.vault.fs.io;
+
+/**
+ * <code>AccessControlHandling</code> defines the behavior when importing
+ * access control nodes.
+ */
+public enum AccessControlHandling {
+
+ /**
+ * Ignores the packaged access control and leaves the target unchanged.
+ */
+ IGNORE,
+
+ /**
+ * Applies the access control provided with the package to the target. this
+ * also removes existing access control.
+ */
+ OVERWRITE,
+
+ /**
+ * Tries to merge access control provided with the package with the one on
+ * the target.
+ *
+ * This is currently not fully supported and behaves like {@link #OVERWRITE}
+ * for existing ACLs. ACLs not in the package are retained.
+ */
+ MERGE,
+
+ /**
+ * Tries to merge access control in the content with the one provided by the package.
+ *
+ * This is currently not fully supported and behaves like {@link #IGNORE}
+ * for existing ACLs. ACLs not in the package are retained.
+ */
+ MERGE_PRESERVE,
+
+ /**
+ * Clears all access control on the target system.
+ */
+ CLEAR,
+
+}