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 [18/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/spi/PrivilegeInstaller.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/PrivilegeInstaller.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/PrivilegeInstaller.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/PrivilegeInstaller.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,34 @@
+/*
+ * 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.spi;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.security.Privilege;
+
+/**
+ * <code>NodeTypeInstaller</code>...
+ */
+public interface PrivilegeInstaller {
+
+    Collection<Privilege> install(ProgressTracker tracker, PrivilegeDefinitions defs)
+            throws IOException, RepositoryException;
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ProgressTracker.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ProgressTracker.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ProgressTracker.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ProgressTracker.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,80 @@
+/*
+ * 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.spi;
+
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
+
+/**
+ * <code>ProgressTracker</code>...
+ *
+ */
+public class ProgressTracker {
+
+    protected ProgressTrackerListener listener;
+
+    private ProgressTrackerListener.Mode mode = ProgressTrackerListener.Mode.TEXT;
+
+    private boolean enabled = true;
+
+    public ProgressTracker() {
+    }
+
+    public ProgressTracker(ProgressTrackerListener listener) {
+        this.listener = listener;
+    }
+
+    public void setListener(ProgressTrackerListener listener) {
+        this.listener = listener;
+    }
+
+    public ProgressTrackerListener getListener() {
+        return listener;
+    }
+
+    public void track(String action, String path) {
+        if (enabled && listener != null) {
+            listener.onMessage(mode, action, path);
+        }
+    }
+
+    public void track(Exception e, String path) {
+        if (enabled && listener != null) {
+            listener.onError(mode, path, e);
+        }
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public ProgressTrackerListener.Mode getMode() {
+        return mode;
+    }
+
+    public ProgressTrackerListener.Mode setMode(ProgressTrackerListener.Mode mode) {
+        ProgressTrackerListener.Mode prev = this.mode;
+        this.mode = mode;
+        return prev;
+    }
+
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ServiceProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ServiceProvider.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ServiceProvider.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ServiceProvider.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,87 @@
+/*
+ * 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.spi;
+
+import java.io.Writer;
+import java.util.Set;
+
+import javax.jcr.Session;
+
+/**
+ * Defines a general provider for the JCR version specific services such as node
+ * type management and access control handling.
+ */
+public interface ServiceProvider {
+
+    /**
+     * Returns the JCR version of the underlying repository
+     * @return the jcr version
+     */
+    JcrVersion getJCRVersion();
+
+    /**
+     * Returns the names of the default built in nodetypes of the underlying
+     * repository.
+     *
+     * @return a set of names
+     */
+    Set<String> getBuiltInNodeTypeNames();
+
+    /**
+     * Returns the default node type installer.
+     * @param session the session to use
+     * @return the default node type installer.
+     */
+    NodeTypeInstaller getDefaultNodeTypeInstaller(Session session);
+
+    /**
+     * Returns the default privilege installer.
+     * @param session the session to use
+     * @return the default privilege installer.
+     */
+    PrivilegeInstaller getDefaultPrivilegeInstaller(Session session);
+
+    /**
+     * Returns the default CND reader.
+     * @return the default CND reader.
+     */
+    CNDReader getCNDReader();
+
+    /**
+     * Returns the default CND writer
+     * @param out the writer
+     * @param s the session
+     * @param includeNS <code>true</code> if namespace should be included
+     * @return the default CND writer
+     */
+    CNDWriter getCNDWriter(Writer out, Session s, boolean includeNS);
+
+    /**
+     * Returns the repository dependant ACL management
+     * @return the ACL management
+     */
+    ACLManagement getACLManagement();
+
+    /**
+     * Returns the repository dependant User management or <code>null</code> if
+     * the repository does not require a separate user handling.
+     *
+     * @return repository dependant User management or <code>null</code>
+     */
+    UserManagement getUserManagement();
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ServiceProviderFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ServiceProviderFactory.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ServiceProviderFactory.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/ServiceProviderFactory.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,36 @@
+/*
+ * 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.spi;
+
+import org.apache.jackrabbit.vault.fs.spi.impl.jcr20.JcrServiceProvider;
+
+/**
+ * <code>StaticServiceProvider</code>...
+ */
+public class ServiceProviderFactory {
+
+    private static ServiceProvider instance;
+
+    public static ServiceProvider getProvider() {
+        if (instance == null) {
+            instance = new JcrServiceProvider();
+        }
+        return instance;
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/UserManagement.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/UserManagement.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/UserManagement.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/UserManagement.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,53 @@
+/*
+ * 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.spi;
+
+import javax.jcr.Session;
+
+/**
+ * <code>UserManagement</code>...
+ */
+public interface UserManagement {
+
+    /**
+     * Checks if the given node type name is used for a User node.
+     *
+     * @param ntName the node type name
+     * @return <code>true</code> if used for a User node.
+     */
+    boolean isAuthorizableNodeType(String ntName);
+
+    /**
+     * Returns the path of the authorizable or <code>null</code> if not exists.
+     * @param name the authorizable name
+     * @param session the session to access the repository
+     * @return path of authorizable
+     *
+     * @since 2.3.26
+     */
+    String getAuthorizablePath(Session session, String name);
+
+    /**
+     * Adds the given memberships to the specified group.
+     * @param session session to operate on
+     * @param id id of group
+     * @param membersUUID uuids of members
+     * @since 2.3.28
+     */
+    void addMembers(Session session, String id, String[] membersUUID);
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/DefaultCNDReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/DefaultCNDReader.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/DefaultCNDReader.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/DefaultCNDReader.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,61 @@
+/*
+ * 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.spi.impl.jcr20;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
+import org.apache.jackrabbit.commons.cnd.ParseException;
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
+import org.apache.jackrabbit.spi.commons.nodetype.QDefinitionBuilderFactory;
+import org.apache.jackrabbit.vault.fs.spi.CNDReader;
+import org.apache.jackrabbit.vault.fs.spi.DefaultNodeTypeSet;
+
+/**
+ * <code>CNDReaderWrapper</code>...
+ */
+public class DefaultCNDReader extends DefaultNodeTypeSet implements CNDReader {
+
+    public DefaultCNDReader() {
+        super("undefined");
+    }
+
+    public void read(Reader reader, String systemId, NamespaceMapping namespaceMapping)
+            throws IOException {
+        try {
+            setSystemId(systemId);
+            CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping> r;
+            if (namespaceMapping == null) {
+                r = new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(
+                        reader, systemId, new QDefinitionBuilderFactory());
+            } else {
+                r = new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(
+                        reader, systemId, namespaceMapping,
+                        new QDefinitionBuilderFactory());
+            }
+            add(r.getNodeTypeDefinitions(), r.getNamespaceMapping());
+        } catch (ParseException e) {
+            IOException ie = new IOException("I/O Error while reading node types.");
+            ie.initCause(e);
+            throw ie;
+        }
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/DefaultCNDWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/DefaultCNDWriter.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/DefaultCNDWriter.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/DefaultCNDWriter.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,63 @@
+/*
+ * 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.spi.impl.jcr20;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Collection;
+
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
+import org.apache.jackrabbit.spi.commons.nodetype.compact.CompactNodeTypeDefWriter;
+import org.apache.jackrabbit.vault.fs.spi.CNDWriter;
+
+/**
+ * <code>DefaultCNDWriter</code>...
+ */
+public class DefaultCNDWriter implements CNDWriter {
+
+    private CompactNodeTypeDefWriter w;
+
+    public DefaultCNDWriter(Writer out, Session s, boolean includeNs) {
+        w = new CompactNodeTypeDefWriter(out, s, includeNs);
+    }
+
+    public DefaultCNDWriter(Writer out, NamespaceResolver s, boolean includeNs) {
+        w = new CompactNodeTypeDefWriter(out, s, includeNs);
+    }
+
+    public void write(QNodeTypeDefinition nt) throws IOException {
+        w.write(nt);
+    }
+
+    public void write(Collection<QNodeTypeDefinition> nts) throws IOException {
+        w.write(nts);
+    }
+
+    public void write(NodeType nt) throws IOException {
+        w.write(nt);
+    }
+
+    public void close() throws IOException {
+        w.close();
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitPrivilegeInstaller.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitPrivilegeInstaller.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitPrivilegeInstaller.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitPrivilegeInstaller.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,135 @@
+/*
+ * 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.spi.impl.jcr20;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+import javax.jcr.security.Privilege;
+
+import org.apache.jackrabbit.api.JackrabbitWorkspace;
+import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.PrivilegeDefinition;
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
+import org.apache.jackrabbit.vault.fs.spi.PrivilegeDefinitions;
+import org.apache.jackrabbit.vault.fs.spi.PrivilegeInstaller;
+import org.apache.jackrabbit.vault.fs.spi.ProgressTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>JcrNodeTypeInstaller</code> is used to install privileges using the
+ * jackrabbit privilege manager
+ */
+public class JackrabbitPrivilegeInstaller implements PrivilegeInstaller {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(JackrabbitPrivilegeInstaller.class);
+
+    private final Session session;
+
+    public JackrabbitPrivilegeInstaller(Session session) {
+        this.session = session;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<Privilege> install(ProgressTracker tracker, PrivilegeDefinitions defs)
+            throws IOException, RepositoryException {
+
+        Workspace wsp = session.getWorkspace();
+        if (!(wsp instanceof JackrabbitWorkspace)) {
+            throw new RepositoryException("Unable to register privileges. No JackrabbitWorkspace.");
+        }
+        PrivilegeManager mgr = ((JackrabbitWorkspace) wsp).getPrivilegeManager();
+
+        ProgressTrackerListener.Mode mode = null;
+        if (tracker != null) {
+            mode = tracker.setMode(ProgressTrackerListener.Mode.TEXT);
+        }
+
+        // register namespaces
+        Map<String, String> pfxToURI = defs.getNamespaceMapping().getPrefixToURIMapping();
+        if (!pfxToURI.isEmpty()) {
+            for (Object o : pfxToURI.keySet()) {
+                String prefix = (String) o;
+                String uri = pfxToURI.get(prefix);
+                try {
+                    session.getNamespacePrefix(uri);
+                    track(tracker, "-", prefix + " -> " + uri);
+                } catch (RepositoryException e) {
+                    session.getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri);
+                    track(tracker, "A", prefix + " -> " + uri);
+                }
+            }
+        }
+
+        // register node types
+        List<Privilege> registeredPrivs = new LinkedList<Privilege>();
+        for (PrivilegeDefinition def: defs.getDefinitions()) {
+            String name = getJCRName(def.getName());
+            Privilege priv = null;
+            try {
+                priv = mgr.getPrivilege(name);
+            } catch (RepositoryException e) {
+                // ignore, already registered
+            }
+            if (priv == null) {
+                String[] aggregateNames = new String[def.getDeclaredAggregateNames().size()];
+                int i=0;
+                for (Name n: def.getDeclaredAggregateNames()) {
+                    aggregateNames[i++] = getJCRName(n);
+                }
+                registeredPrivs.add(mgr.registerPrivilege(name, def.isAbstract(), aggregateNames));
+                track(tracker, "A", name);
+            } else {
+                track(tracker, "-", name);
+            }
+        }
+
+        if (tracker != null) {
+            tracker.setMode(mode);
+        }
+        return registeredPrivs;
+    }
+
+    private void track(ProgressTracker tracker, String action, String path) {
+        log.debug("{} {}", action, path);
+        if (tracker != null) {
+            tracker.track(action, path);
+        }
+    }
+
+    private String getJCRName(Name name) {
+        StringBuilder str = new StringBuilder("{");
+        str.append(name.getNamespaceURI());
+        str.append("}");
+        str.append(name.getLocalName());
+        return str.toString();
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitUserManagement.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitUserManagement.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitUserManagement.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitUserManagement.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,122 @@
+/*
+ * 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.spi.impl.jcr20;
+
+import java.util.UUID;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.util.Text;
+import org.apache.jackrabbit.vault.fs.spi.UserManagement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>JackrabbitUserManagement</code>...
+ */
+public class JackrabbitUserManagement implements UserManagement {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(JackrabbitUserManagement.class);
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAuthorizableNodeType(String ntName) {
+        return ntName.equals("rep:Group") || ntName.equals("rep:User");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String getAuthorizablePath(Session session, String name) {
+        // currently we rely on the implementation detail to keep the API dependency to jackrabbit  < 2.3.
+        try {
+            UUID uuid = UUID.nameUUIDFromBytes(name.toLowerCase().getBytes("UTF-8"));
+            return session.getNodeByIdentifier(uuid.toString()).getPath();
+        } catch (Exception e) {
+            // ignore
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addMembers(Session session, String id, String[] membersUUID) {
+        if (!(session instanceof JackrabbitSession)) {
+            log.warn("Unable to update membership. no jackrabbit session.");
+            return;
+        }
+        UserManager uMgr = null;
+        try {
+            uMgr = ((JackrabbitSession) session).getUserManager();
+        } catch (RepositoryException e) {
+            log.warn("Unable to update membership of {}. Error while retrieving user manager.", id, e);
+            return;
+        }
+        Authorizable auth = null;
+        try {
+            auth = uMgr.getAuthorizable(id);
+        } catch (RepositoryException e) {
+            log.warn("Unable to update membership of {}. Error while retrieving authorizable.", id, e);
+            return;
+        }
+        if (auth == null) {
+            log.warn("Unable to update membership of {}. No such authorizable.", id);
+            return;
+        }
+        if (!(auth instanceof Group)) {
+            log.warn("Unable to update membership of {}. No a group.", id);
+            return;
+        }
+        Group grp = (Group) auth;
+        for (String uuid: membersUUID) {
+            String authId = null;
+            try {
+                Node authNode = session.getNodeByIdentifier(uuid);
+                // rely on implementation that nodename == userid.
+                authId = Text.unescapeIllegalJcrChars(authNode.getName());
+                auth = uMgr.getAuthorizable(authId);
+            } catch (RepositoryException e) {
+                log.warn("unable to add authorizable '{}' to group '{}'. No such node.", uuid, id);
+            }
+            try {
+                if (auth == null) {
+                    log.warn("unable to add authorizable '{}' to group '{}'. No such authorizable.", authId, id);
+                } else if (grp.isDeclaredMember(auth)) {
+                    log.info("ignoring to add authorizable '{}' to group '{}'. Already member.", authId, id);
+                } else {
+                    grp.addMember(auth);
+                    log.info("added authorizable '{}' to group '{}'.", authId, id);
+                }
+            } catch (RepositoryException e) {
+                log.error("Error while adding authorizable '{}' to group '{}': {}", new Object[]{authId, id, e});
+            }
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrACLManagement.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrACLManagement.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrACLManagement.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrACLManagement.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,89 @@
+/*
+ * 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.spi.impl.jcr20;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+
+import org.apache.jackrabbit.vault.fs.spi.ACLManagement;
+
+/**
+ * <code>JcrACLManagement</code>...
+ */
+public class JcrACLManagement implements ACLManagement {
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isACLNodeType(String name) {
+        return name.equals("rep:ACL");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isAccessControllableMixin(String name) {
+        return name.equals("rep:AccessControllable") || name.equals("rep:RepoAccessControllable");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isACLNode(Node node) throws RepositoryException {
+        return node.isNodeType("rep:Policy");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean ensureAccessControllable(Node node) throws RepositoryException {
+        boolean modified = false;
+        if (!node.isNodeType("rep:AccessControllable")) {
+            node.addMixin("rep:AccessControllable");
+            modified = true;
+        }
+        if (isRootNode(node) && !node.isNodeType("rep:RepoAccessControllable")) {
+            node.addMixin("rep:RepoAccessControllable");
+            modified = true;
+        }
+        return modified;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void clearACL(Node node) throws RepositoryException {
+        AccessControlManager ac = node.getSession().getAccessControlManager();
+        String pPath = node.getPath();
+        for (AccessControlPolicy p: ac.getPolicies(pPath)) {
+            ac.removePolicy(pPath, p);
+        }
+        if (isRootNode(node)) {
+            for (AccessControlPolicy p: ac.getPolicies(null)) {
+                ac.removePolicy(null, p);
+            }
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    private static boolean isRootNode(Node node) throws RepositoryException {
+        return node.getDepth() == 0;
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNodeTypeInstaller.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNodeTypeInstaller.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNodeTypeInstaller.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNodeTypeInstaller.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,141 @@
+/*
+ * 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.spi.impl.jcr20;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.NodeTypeDefinition;
+import javax.jcr.nodetype.NodeTypeIterator;
+import javax.jcr.nodetype.NodeTypeManager;
+
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
+import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
+import org.apache.jackrabbit.spi.commons.nodetype.NodeTypeDefinitionFactory;
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
+import org.apache.jackrabbit.vault.fs.spi.DefaultNodeTypeSet;
+import org.apache.jackrabbit.vault.fs.spi.NodeTypeInstaller;
+import org.apache.jackrabbit.vault.fs.spi.NodeTypeSet;
+import org.apache.jackrabbit.vault.fs.spi.ProgressTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>JcrNodeTypeInstaller</code> is used to install nodetypes using the
+ * JCR 2.0 node type install features
+ */
+public class JcrNodeTypeInstaller implements NodeTypeInstaller {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(JcrNodeTypeInstaller.class);
+
+    private final Session session;
+
+    public JcrNodeTypeInstaller(Session session) {
+        this.session = session;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<NodeType> install(ProgressTracker tracker, NodeTypeSet types)
+            throws IOException, RepositoryException {
+
+        // register node types
+        NodeTypeManager ntMgr = session.getWorkspace().getNodeTypeManager();
+
+        // filter out registered
+        DefaultNodeTypeSet set;
+        if (types instanceof DefaultNodeTypeSet) {
+            set = (DefaultNodeTypeSet) types;
+        } else {
+            set = new DefaultNodeTypeSet(types);
+        }
+        log.debug("Removing registered nodetypes");
+        DefaultNamePathResolver npResolver = new DefaultNamePathResolver(session);
+        NodeTypeIterator iter = ntMgr.getAllNodeTypes();
+        while (iter.hasNext()) {
+            NodeType nt = iter.nextNodeType();
+            set.remove(npResolver.getQName(nt.getName()));
+        }
+
+        ProgressTrackerListener.Mode mode = null;
+        if (tracker != null) {
+            mode = tracker.setMode(ProgressTrackerListener.Mode.TEXT);
+        }
+
+        // register namespaces
+        Map<String, String> pfxToURI = set.getNamespaceMapping().getPrefixToURIMapping();
+        if (!pfxToURI.isEmpty()) {
+            for (Object o : pfxToURI.keySet()) {
+                String prefix = (String) o;
+                String uri = (String) pfxToURI.get(prefix);
+                try {
+                    session.getNamespacePrefix(uri);
+                    track(tracker, "-", prefix + " -> " + uri);
+                } catch (RepositoryException e) {
+                    session.getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri);
+                    track(tracker, "A", prefix + " -> " + uri);
+                }
+            }
+        }
+
+        // register node types
+        NodeTypeDefinitionFactory fac = new NodeTypeDefinitionFactory(session);
+        List<NodeTypeDefinition> nodeTypes = fac.create(set.getNodeTypes().values());
+        if (nodeTypes.size() > 0) {
+            try {
+                ntMgr.registerNodeTypes(nodeTypes.toArray(new NodeTypeDefinition[nodeTypes.size()]), true);
+            } catch (UnsupportedOperationException e) {
+                log.error("Unable to install node types.");
+                throw e;
+            }
+        }
+
+        // add some tracking info
+        for (QNodeTypeDefinition t: set.getRemoved().values()) {
+            String name = npResolver.getJCRName(t.getName());
+            track(tracker, "-", name);
+        }
+        List<NodeType> nts = new LinkedList<NodeType>();
+        for (QNodeTypeDefinition t: set.getNodeTypes().values()) {
+            String name = npResolver.getJCRName(t.getName());
+            track(tracker, "A", name);
+            nts.add(session.getWorkspace().getNodeTypeManager().getNodeType(name));
+        }
+        if (tracker != null) {
+            tracker.setMode(mode);
+        }
+        return nts;
+    }
+
+    private void track(ProgressTracker tracker, String action, String path) {
+        log.debug("{} {}", action, path);
+        if (tracker != null) {
+            tracker.track(action, path);
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrServiceProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrServiceProvider.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrServiceProvider.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrServiceProvider.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,105 @@
+/*
+ * 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.spi.impl.jcr20;
+
+import java.io.Writer;
+import java.util.Set;
+
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.spi.ACLManagement;
+import org.apache.jackrabbit.vault.fs.spi.CNDReader;
+import org.apache.jackrabbit.vault.fs.spi.CNDWriter;
+import org.apache.jackrabbit.vault.fs.spi.DefaultNodeTypes;
+import org.apache.jackrabbit.vault.fs.spi.JcrVersion;
+import org.apache.jackrabbit.vault.fs.spi.NodeTypeInstaller;
+import org.apache.jackrabbit.vault.fs.spi.PrivilegeInstaller;
+import org.apache.jackrabbit.vault.fs.spi.ServiceProvider;
+import org.apache.jackrabbit.vault.fs.spi.UserManagement;
+
+/**
+ * Implements a Service Provider for JCR 2.0 Repositories
+ */
+public class JcrServiceProvider implements ServiceProvider {
+
+    private ACLManagement aclManagement;
+
+    private UserManagement userManagement;
+
+    /**
+     * {@inheritDoc}
+     */
+    public JcrVersion getJCRVersion() {
+        return JcrVersion.V20;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Set<String> getBuiltInNodeTypeNames() {
+        return DefaultNodeTypes.CRX_2X_NODE_TYPES;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public NodeTypeInstaller getDefaultNodeTypeInstaller(Session session) {
+        return new JcrNodeTypeInstaller(session);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PrivilegeInstaller getDefaultPrivilegeInstaller(Session session) {
+        return new JackrabbitPrivilegeInstaller(session);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public CNDReader getCNDReader() {
+        return new DefaultCNDReader();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public CNDWriter getCNDWriter(Writer out, Session s, boolean includeNS) {
+        return new DefaultCNDWriter(out, s, includeNS);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ACLManagement getACLManagement() {
+        if (aclManagement == null) {
+            aclManagement = new JcrACLManagement();
+        }
+        return aclManagement;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public UserManagement getUserManagement() {
+        if (userManagement == null) {
+            userManagement = new JackrabbitUserManagement();
+        }
+        return userManagement;
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/CyclicDependencyException.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/CyclicDependencyException.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/CyclicDependencyException.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/CyclicDependencyException.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,39 @@
+/*
+ * 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.packaging;
+
+/**
+ * <code>CyclicDependencyException</code>...
+ */
+public class CyclicDependencyException extends PackageException {
+
+    public CyclicDependencyException() {
+    }
+
+    public CyclicDependencyException(String message) {
+        super(message);
+    }
+
+    public CyclicDependencyException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public CyclicDependencyException(Throwable cause) {
+        super(cause);
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Dependency.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Dependency.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Dependency.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Dependency.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,269 @@
+/*
+ * 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.packaging;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implements a package dependency reference.
+ * @since 2.0
+ */
+public class Dependency {
+
+    /**
+     * An empty dependency array
+     */
+    public static final Dependency[] EMPTY = new Dependency[0];
+
+    /**
+     * group id of the dependency
+     */
+    private final String groupId;
+
+    /**
+     * name of the dependency
+     */
+    private final String name;
+
+    /**
+     * Version range of the dependency
+     */
+    private final VersionRange range;
+
+    /**
+     * internal string representation
+     */
+    private final String str;
+
+    /**
+     * Creates a new dependency reference.
+     * @param groupId group id
+     * @param name name
+     * @param range version range
+     */
+    public Dependency(String groupId, String name, VersionRange range) {
+        if (groupId.startsWith(PackageId.ETC_PACKAGES_PREFIX)) {
+            groupId = groupId.substring(PackageId.ETC_PACKAGES_PREFIX.length());
+        }
+        this.groupId = groupId;
+        this.name = name;
+        this.range = range == null ? VersionRange.INFINITE : range;
+        StringBuilder b = new StringBuilder();
+        if (groupId.length() > 0 || !VersionRange.INFINITE.equals(this.range)) {
+            b.append(groupId);
+            b.append(":");
+        }
+        b.append(name);
+        if (!VersionRange.INFINITE.equals(this.range)) {
+            b.append(":");
+            b.append(range);
+        }
+        this.str = b.toString();
+    }
+
+    /**
+     * Creates a new dependency to the specified package id
+     * @param id package id.
+     */
+    public Dependency(PackageId id) {
+        this(id.getGroup(), id.getName(), new VersionRange(id.getVersion()));
+    }
+
+    /**
+     * Returns the group of the dependency
+     * @return the group id
+     * @since 2.4
+     */
+    public String getGroup() {
+        return groupId;
+    }
+
+    /**
+     * Returns the name of the dependency
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the version range
+     * @return the version range
+     */
+    public VersionRange getRange() {
+        return range;
+    }
+
+    /**
+     * Returns the installation path of this dependency
+     * @return the installation path;
+     */
+    public String getPath() {
+        StringBuilder b = new StringBuilder();
+        if (groupId.length() > 0) {
+            if (groupId.charAt(0) != '/') {
+                b.append(PackageId.ETC_PACKAGES_PREFIX);
+            }
+            b.append(groupId);
+            b.append("/");
+        } else {
+            b.append(PackageId.ETC_PACKAGES_PREFIX);
+        }
+        b.append(name);
+        return b.toString();
+    }
+
+    /**
+     * Checks if the given package id matches this dependency specification.
+     * @param id the package id
+     * @return <code>true</code> if matches
+     */
+    public boolean matches(PackageId id) {
+        return groupId.equals(id.getGroup())
+                && name.equals(id.getName())
+                && range.isInRange(id.getVersion());
+    }
+
+    /**
+     * Returns a dependency from a string. if the given id is null or an
+     * empty string, <code>null</code> is returned.
+     * @param str the string
+     * @return the dependency
+     */
+    public static Dependency fromString(String str) {
+        if (str == null || str.length() == 0) {
+            return null;
+        }
+        String[] segs = str.split(":");
+        String name;
+        String groupId = "";
+        String range = null;
+        if (segs.length == 1) {
+            name = segs[0];
+            // be backward compatible, respect group in name
+            int idx = name.lastIndexOf('/');
+            if (idx >= 0) {
+                groupId = name.substring(0, idx);
+                name = name.substring(idx + 1);
+            }
+        } else if (segs.length == 2) {
+            groupId = segs[0];
+            name = segs[1];
+            boolean isVersion = true;
+            if (name.length() > 0) {
+                char c = name.charAt(0);
+                isVersion = Character.isDigit(c) || c == '[' || c == ')';
+            }
+            // be backward compatible, respect group in name
+            int idx = name.lastIndexOf('/');
+            if (idx >= 0 && groupId.length() == 0) {
+                groupId = name.substring(0, idx);
+                name = name.substring(idx + 1);
+            } else if ((idx = groupId.lastIndexOf('/')) >=0 && isVersion) {
+                groupId = segs[0].substring(0, idx);
+                name = segs[0].substring(idx + 1);
+                range = segs[1];
+            }
+        } else {
+            groupId = segs[0];
+            name = segs[1];
+            range = segs[2];
+        }
+        return new Dependency(groupId, name, range == null ? null : VersionRange.fromString(range));
+    }
+
+    /**
+     * Parses a string serialization of dependency references generated by
+     * {@link #toString(Dependency...)})}
+     *
+     * @param str serialized string
+     * @return array of dependency references
+     */
+    public static Dependency[] parse(String str) {
+        List<Dependency> deps = new ArrayList<Dependency>();
+        boolean inRange = false;
+        int start = 0;
+        boolean wasSeg = false;
+        for (int i=0; i<str.length(); i++) {
+            char c = str.charAt(i);
+            if (c == ',') {
+                if (!inRange) {
+                    deps.add(Dependency.fromString(str.substring(start, i)));
+                    start = i + 1;
+                }
+            } else if (c == '[' || c == '(') {
+                if (wasSeg) {
+                    inRange = true;
+                }
+            } else if (c == ']' || c == ')') {
+                inRange = false;
+            }
+            wasSeg = c == ':';
+        }
+        if (start < str.length()) {
+            deps.add(Dependency.fromString(str.substring(start)));
+        }
+        return deps.toArray(new Dependency[deps.size()]);
+    }
+    
+    /**
+     * Returns dependencies from the given strings.
+     * @param str the strings
+     * @return the dependencies
+     */
+    public static Dependency[] fromString(String ... str) {
+        Dependency[] ret = new Dependency[str.length];
+        for (int i=0; i<str.length;i++) {
+            ret[i] = Dependency.fromString(str[i]);
+        }
+        return ret;
+    }
+
+    /**
+     * Returns a string representation from given dependencies.
+     * @param deps the dependencies
+     * @return the strings
+     */
+    public static String toString(Dependency ... deps) {
+        String delim = "";
+        StringBuilder b = new StringBuilder();
+        for (Dependency dep: deps) {
+            b.append(delim).append(dep);
+            delim=",";
+        }
+        return b.toString();
+    }
+
+    @Override
+    public String toString() {
+        return str;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return this == obj ||
+                obj instanceof Dependency && str.equals(obj.toString());
+    }
+
+    @Override
+    public int hashCode() {
+        return str.hashCode();
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/DependencyUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/DependencyUtil.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/DependencyUtil.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/DependencyUtil.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,124 @@
+/*
+ * 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.packaging;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Dependency Utilities
+ */
+public class DependencyUtil {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(DependencyUtil.class);
+
+    /**
+     * Sorts the packages by the dependency order
+     * @param packages packages to sort
+     * @throws CyclicDependencyException if a cyclic dependency is detected
+     */
+    public static <T extends VaultPackage> void sort(Collection<T> packages) throws CyclicDependencyException {
+        Map<PackageId, Dependency[]> list = new LinkedHashMap<PackageId, Dependency[]>();
+        Map<PackageId, VaultPackage> byId = new LinkedHashMap<PackageId, VaultPackage>();
+        for (VaultPackage pack: packages) {
+            list.put(pack.getId(), pack.getDependencies());
+            byId.put(pack.getId(), pack);
+        }
+        packages.clear();
+        for (PackageId id: resolve(list)) {
+            packages.add((T) byId.remove(id));
+        }
+    }
+
+    /**
+     * Sorts the packages by the dependency order
+     * @param packages packages to sort
+     * @throws CyclicDependencyException if a cyclic dependency is detected
+     * @throws javax.jcr.RepositoryException if an repository error occurs
+     */
+    public static <T extends JcrPackage> void sortPackages(Collection<T> packages)
+            throws CyclicDependencyException, RepositoryException {
+        Map<PackageId, Dependency[]> list = new LinkedHashMap<PackageId, Dependency[]>();
+        Map<PackageId, JcrPackage> byId = new LinkedHashMap<PackageId, JcrPackage>();
+        for (JcrPackage pack: packages) {
+            PackageId id = pack.getDefinition().getId();
+            list.put(id, pack.getDefinition().getDependencies());
+            byId.put(id, pack);
+        }
+        packages.clear();
+        for (PackageId id: resolve(list)) {
+            packages.add((T) byId.remove(id));
+        }
+
+    }
+
+    /**
+     * Resolves a list of resolutions respecting their internal dependency references.
+     * @param list list of resolutions
+     * @return a new list of resolutions
+     * @throws CyclicDependencyException if a cyclic dependency is detected
+     */
+    public static List<PackageId> resolve(Map<PackageId, Dependency[]> list) throws CyclicDependencyException {
+        // create fake deplist
+        Dependency[] fake = new Dependency[list.size()];
+        int i=0;
+        for (Map.Entry<PackageId, Dependency[]> entry: list.entrySet()) {
+            fake[i++] = new Dependency(entry.getKey());
+        }
+        Map<PackageId, Boolean> result = new LinkedHashMap<PackageId, Boolean>(list.size());
+        resolve(fake, list, result);
+        return new ArrayList<PackageId>(result.keySet());
+    }
+
+    private static void resolve(Dependency[] deps, Map<PackageId, Dependency[]> list, Map<PackageId, Boolean> result)
+            throws CyclicDependencyException {
+        // find the dep in the list
+        for (Dependency dep: deps) {
+            for (Map.Entry<PackageId, Dependency[]> entry: list.entrySet()) {
+                PackageId id = entry.getKey();
+                if (dep.matches(id)) {
+                    Boolean res = result.get(id);
+                    if (res != null && !res) {
+                        log.error("Package dependencies cause cycle.");
+                        throw new CyclicDependencyException();
+                    } else if (res == null) {
+                        result.put(id, res = false);
+                    }
+                    resolve(entry.getValue(), list, result);
+                    // shove at the end of the list if not resolved
+                    if (!res) {
+                        result.remove(id);
+                        result.put(id, true);
+                    }
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/ExportOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/ExportOptions.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/ExportOptions.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/ExportOptions.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,125 @@
+/*
+ * 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.packaging;
+
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
+import org.apache.jackrabbit.vault.fs.config.MetaInf;
+
+/**
+ * Holds options used for exporting.
+ */
+public class ExportOptions {
+
+    private ProgressTrackerListener listener;
+
+    private ExportPostProcessor postProcessor;
+
+    private MetaInf metaInf;
+
+    private String rootPath;
+
+    private String mountPath;
+
+    /**
+     * Returns the progress tracker listener.
+     * @return the progress tracker listener.
+     */
+    public ProgressTrackerListener getListener() {
+        return listener;
+    }
+
+    /**
+     * Sets the progress tracker listener for an export. The listener receives progress messages from the progress
+     * tracker and can use them to provide feedback.
+     * @param listener the listener
+     */
+    public void setListener(ProgressTrackerListener listener) {
+        this.listener = listener;
+    }
+
+    /**
+     * Returns the post processor
+     * @return the post processor
+     */
+    public ExportPostProcessor getPostProcessor() {
+        return postProcessor;
+    }
+
+    /**
+     * Sets the export post processor for an export. The post processor is called after the actual export is performed
+     * but before the archive is closed.
+     * @param postProcessor the post processor
+     */
+    public void setPostProcessor(ExportPostProcessor postProcessor) {
+        this.postProcessor = postProcessor;
+    }
+
+    /**
+     * Returns the meta-inf
+     * @return the meta-inf
+     */
+    public MetaInf getMetaInf() {
+        return metaInf;
+    }
+
+    /**
+     * Sets the meta-inf to be included in an exported archive.
+     * @param metaInf the meta inf
+     */
+    public void setMetaInf(MetaInf metaInf) {
+        this.metaInf = metaInf;
+    }
+
+    /**
+     * Returns the root path.
+     * @return the root path.
+     */
+    public String getRootPath() {
+        return rootPath;
+    }
+
+    /**
+     * Defines the root path where the mounted repository should be mapped into the vault fs. this can be used to
+     * generate packages that have a virtual root. If a root path different than '/' is set, the workspace filter
+     * will be adjusted accordingly, if possible.
+     *
+     * @param rootPath the root path
+     */
+    public void setRootPath(String rootPath) {
+        this.rootPath = rootPath;
+    }
+
+    /**
+     * Returns the mount path
+     * @return the mount path
+     */
+    public String getMountPath() {
+        return mountPath;
+    }
+
+    /**
+     * Defines the root path where the repository should be mounted for the export. this can be used to generate
+     * packages that are not "rooted" at '/'. If a mount path different than '/' is set, the workspace filter
+     * will be adjusted accordingly, if possible
+     *
+     * @param mountPath the mount path
+     */
+    public void setMountPath(String mountPath) {
+        this.mountPath = mountPath;
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/ExportPostProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/ExportPostProcessor.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/ExportPostProcessor.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/ExportPostProcessor.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,32 @@
+/*
+ * 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.packaging;
+
+import org.apache.jackrabbit.vault.fs.io.AbstractExporter;
+
+/**
+ * Defines a post processor that is invoked after a package is assembled.
+ */
+public interface ExportPostProcessor {
+
+    /**
+     * Post process.
+     * @param exporter the exporter that produces the package.
+     */
+    void process(AbstractExporter exporter);
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/InstallContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/InstallContext.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/InstallContext.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/InstallContext.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,90 @@
+/*
+ * 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.packaging;
+
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+
+/**
+ * The install context is passed to {@link InstallHook}s during the different
+ * phases of a package installation.
+ */
+public interface InstallContext {
+
+    /**
+     * The current phase of a package installation
+     */
+    enum Phase {
+
+        /**
+         * Specifies that the package is not yet installed and the hooks can
+         * do some pre-installation work
+         */
+        PREPARE,
+
+        /**
+         * Specifies that the prepare phase failed and the hocks can do some
+         * cleanup work.
+         */
+        PREPARE_FAILED,
+
+        /**
+         * Specifies that the package was successfully installed and the hooks
+         * can do some post-installation work and cleanup.
+         */
+        INSTALLED,
+
+        /**
+         * Specifies that the package installation failed and the hooks can
+         * do some cleanup work.
+         */
+        INSTALL_FAILED,
+
+        /**
+         * Specifies that the hook is going to be discarded. this is guaranteed
+         * to be called at the end of an installation process.
+         */
+        END
+    }
+
+    /**
+     * Returns the current installation phase
+     * @return the phase
+     */
+    Phase getPhase();
+
+    /**
+     * Returns the session that is used to install the package
+     * @return the session
+     */
+    Session getSession();
+
+    /**
+     * Returns the package that is currently installed
+     * @return the vault package
+     */
+    VaultPackage getPackage();
+
+    /**
+     * Returns the import options that are used to install the package
+     * @return the import options
+     */
+    ImportOptions getOptions();
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/InstallHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/InstallHook.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/InstallHook.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/InstallHook.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,46 @@
+/*
+ * 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.packaging;
+
+/**
+ * An install hook is used to do some pre and post work during a package
+ * install. the hooks need to have at least one class that implements this
+ * interface. the class is identified by the normal "Main-Class" manifest
+ * property and needs to be instantiatable. The instantiated hook class is
+ * used for the entire life-cycle of the installation process until the
+ * {@link InstallContext.Phase#END} phase.
+ *
+ * The hook jars need to be placed in the "META-INF/vault/hooks" directory
+ * and are executed in alphabetical sequence for each installation phase.
+ * A hook can throw a {@link PackageException} to abort the current phase,
+ * but this has currently only an effect in the
+ * {@link InstallContext.Phase#PREPARE} phase. If a hook fails, the current
+ * phase is aborted and all hooks (also the failing one) are called again with
+ * the respective "fail" phase.
+ */
+public interface InstallHook {
+
+    /**
+     * Executes hook specific code. This is called for each installation
+     * phase.
+     *
+     * @param context the installation context
+     * @throws PackageException if the hook desires to abort the current phase.
+     */
+    void execute(InstallContext context) throws PackageException;
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackage.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackage.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackage.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackage.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,208 @@
+/*
+ * 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.packaging;
+
+import java.io.IOException;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+
+/**
+ * Specifies the interface of a vault package stored in the repository.
+ */
+public interface JcrPackage extends Comparable<JcrPackage> {
+
+    /**
+     * Nodetype name of a package node
+     */
+    String NT_VLT_PACKAGE = "vlt:Package";
+
+    /**
+     * Nodetype name of a definition node
+     */
+    String NT_VLT_PACKAGE_DEFINITION = "vlt:PackageDefinition";
+
+    /**
+     * Nodename of the definition node
+     */
+    String NN_VLT_DEFINITION = "vlt:definition";
+
+    /**
+     * default mime type of a package
+     */
+    String MIME_TYPE = "application/zip";
+
+    /**
+     * Returns the package definition of this package
+     * @return the package definition or <code>null</code> if this package is
+     *         not valid.
+     * @throws RepositoryException if an error occurrs
+     */
+
+    JcrPackageDefinition getDefinition() throws RepositoryException;
+
+    /**
+     * Checks if the underlying node contains the correct structure.
+     * @return <code>true</code> if this package is valid.
+     */
+    boolean isValid();
+
+    /**
+     * Returns the underlying node
+     * @return the node
+     */
+    Node getNode();
+
+    /**
+     * Checks if this package is sealed. this is the case, if it was not
+     * modified since it was unwrapped.
+     * @return <code>true</code> if this package is sealed.
+     */
+    boolean isSealed();
+
+    /**
+     * Returns the vault package stored in the data of this package
+     * @return the package
+     * @throws RepositoryException if an error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    VaultPackage getPackage() throws RepositoryException, IOException;
+
+    /**
+     * Extracts the package contents to the repository
+     *
+     * @param opts import options
+     * @throws RepositoryException if a repository error during installation occurs.
+     * @throws PackageException if an error during packaging occurs
+     * @throws IllegalStateException if the package is not valid.
+     * @throws IOException if an I/O error occurs
+     * @since 2.3.14
+     */
+    void extract(ImportOptions opts)
+            throws RepositoryException, PackageException, IOException;
+
+    /**
+     * Installs the package contents to the repository but creates a snapshot if
+     * necessary.
+     *
+     * @param opts import options
+     * @throws RepositoryException if a repository error during installation occurs.
+     * @throws PackageException if an error during packaging occurs
+     * @throws IllegalStateException if the package is not valid.
+     * @throws IOException if an I/O error occurs
+     *
+     * @since 2.3.14
+     */
+    void install(ImportOptions opts)
+            throws RepositoryException, PackageException, IOException;
+
+    /**
+     * Creates a snapshot of this package.
+     *
+     * @param opts export options
+     * @param replace if <code>true</code> any existing snapshot is replaced.
+     * @return a package that represents the snapshot of this package.
+     * @throws RepositoryException if a repository error during installation occurs.
+     * @throws PackageException if an error during packaging occurs
+     * @throws IllegalStateException if the package is not valid.
+     * @throws IOException if an I/O error occurs
+     *
+     * @since 2.0
+     */
+    JcrPackage snapshot(ExportOptions opts, boolean replace)
+            throws RepositoryException, PackageException, IOException;
+
+    /**
+     * Returns the snapshot that was taken when installing this package.
+     * @return the snapshot package or <code>null</code>
+     * @throws RepositoryException if an error occurs.
+     *
+     * @since 2.0
+     */
+    JcrPackage getSnapshot() throws RepositoryException;
+
+    /**
+     * Reverts the changes of a prior installation of this package.
+     *
+     * @param opts import options
+     * @throws RepositoryException if a repository error during installation occurs.
+     * @throws PackageException if an error during packaging occurs or if no
+     *         snapshot is available.
+     * @throws IllegalStateException if the package is not valid.
+     * @throws IOException if an I/O error occurs
+     *
+     * @since 2.3.14
+     */
+    void uninstall(ImportOptions opts)
+            throws RepositoryException, PackageException, IOException;
+
+    /**
+     * Checks if the package id is correct in respect to the installation path
+     * and adjusts it accordingly.
+     *
+     * @param autoFix <code>true</code> to automatically fix the id
+     * @param autoSave <code>true</code> to save changes immediately
+     * @return <code>true</code> if id is correct.
+     * @throws RepositoryException if an error occurs.
+     *
+     * @since 2.2.18
+     */
+    boolean verifyId(boolean autoFix, boolean autoSave) throws RepositoryException;
+
+    /**
+     * Checks if this package is installed.
+     *
+     * Note: the default implementation only checks the {@link org.apache.jackrabbit.vault.packaging.JcrPackageDefinition#getLastUnpacked()}
+     * date. If the package is replaced since it was installed. this method will return <code>false</code>.
+     *
+     * @return <code>true</code> if this package is installed.
+     * @throws RepositoryException if an error occurs.
+     *
+     * @since 2.4.6
+     */
+    boolean isInstalled() throws RepositoryException;
+
+    /**
+     * Returns the size of the underlying package.
+     * @return the size in bytes or -1 if not valid.
+     */
+    long getSize();
+
+    /**
+     * Closes this package and destroys all temporary data.
+     */
+    void close();
+
+    /**
+     * Returns the jcr:data property of the package
+     * @return the jcr:data property
+     * @throws RepositoryException if an error occurrs
+     */
+    Property getData() throws RepositoryException;
+
+    /**
+     * Returns the definition node or <code>null</code> if not exists
+     * @return the definition node.
+     * @throws RepositoryException if an error occurrs
+     */
+    Node getDefNode() throws RepositoryException;
+
+}
\ No newline at end of file