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 [19/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/packaging/JcrPackageDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackageDefinition.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackageDefinition.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackageDefinition.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,401 @@
+/*
+ * 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 java.util.Calendar;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.config.MetaInf;
+import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
+
+/**
+ * Specifies the interface of a package definition stored in the repository.
+ */
+public interface JcrPackageDefinition {
+
+    /**
+     * Property name of the last unpacked date
+     */
+    public static final String PN_LAST_UNPACKED = "lastUnpacked";
+
+    /**
+     * Property name of the last unpacked user id
+     */
+    public static final String PN_LAST_UNPACKED_BY = "lastUnpackedBy";
+
+    /**
+     * Property name of the creation date
+     */
+    public static final String PN_CREATED = "jcr:created";
+
+    /**
+     * Property name of the creation user id
+     */
+    public static final String PN_CREATED_BY = "jcr:createdBy";
+
+    /**
+     * Property name of the last modification date
+     */
+    public static final String PN_LASTMODIFIED = "jcr:lastModified";
+
+    /**
+     * Property name of the last modification user id
+     */
+    public static final String PN_LASTMODIFIED_BY = "jcr:lastModifiedBy";
+
+    /**
+     * Property name of the last wrapped date
+     * @since 2.2.22
+     */
+    public static final String PN_LAST_WRAPPED = "lastWrapped";
+
+    /**
+     * Property name of the last wrapped user id
+     * @since 2.2.22
+     */
+    public static final String PN_LAST_WRAPPED_BY = "lastWrappedBy";
+
+    /**
+     * Property name of the package description
+     */
+    public static final String PN_DESCRIPTION = "jcr:description";
+
+    /**
+     * Property name of the package version
+     */
+    public static final String PN_VERSION = "version";
+
+    /**
+     * Property name of the build count
+     */
+    public static final String PN_BUILD_COUNT = "buildCount";
+
+    /**
+     * Property name of the 'name'
+     * @since 2.2
+     */
+    public static final String PN_NAME = "name";
+
+    /**
+     * Property name of the 'group'
+     * @since 2.2
+     */
+    public static final String PN_GROUP = "group";
+
+    /**
+     * Property name of the "requires root" flag
+     */
+    public static final String PN_REQUIRES_ROOT = "requiresRoot";
+
+    /**
+     * Property name of the "require restart" flag
+     */
+    public static final String PN_REQUIRES_RESTART = "requiresRestart";
+
+    /**
+     * Property name of the package dependencies
+     */
+    public static final String PN_DEPENDENCIES = "dependencies";
+
+    /**
+     * Property name of the sub packages (only used in snapshots)
+     */
+    public static final String PN_SUB_PACKAGES = "subPackages";
+
+    /**
+     * Property name of the last unwrapped date
+     */
+    public static final String PN_LAST_UNWRAPPED = "lastUnwrapped";
+
+    /**
+     * Property name of the last unwrapped user id
+     */
+    public static final String PN_LAST_UNWRAPPED_BY = "lastUnwrappedBy";
+
+    /**
+     * Property name of the access control handling mode
+     */
+    public static final String PN_AC_HANDLING = "acHandling";
+
+    /**
+     * Property name of the cnd pattern filter
+     */
+    public static final String PN_CND_PATTERN = "cndPattern";
+
+    /**
+     * Node name of the filter node
+     */
+    public static final String NN_FILTER = "filter";
+
+    /**
+     * Property name of the filter root
+     */
+    public static final String PN_ROOT = "root";
+
+    /**
+     * Property name of the filter root
+     */
+    public static final String PN_MODE = "mode";
+
+    /**
+     * Property name of the filter rules
+     */
+    public static final String PN_RULES = "rules";
+
+    /**
+     * Property name of the rule type
+     */
+    public static final String PN_TYPE = "type";
+
+    /**
+     * Property name of the rule pattern
+     */
+    public static final String PN_PATTERN = "pattern";
+
+    /**
+     * Property name of the disable intermediate save flag
+     */
+    public static final String PN_DISABLE_INTERMEDIATE_SAVE = "noIntermediateSaves";
+
+    /**
+     * Returns the underlying node
+     * @return the node
+     */
+    Node getNode();
+
+    /**
+     * Returns the package id
+     * @return the package id
+     */
+    PackageId getId();
+
+    /**
+     * Writes the properties derived from the package id to the content
+     * @param id the package id
+     * @param autoSave if <code>true</code> the changes are saved automatically.
+     * @since 2.2
+     */
+    void setId(PackageId id, boolean autoSave);
+
+    /**
+     * Checks if this definition is unwrapped, i.e. if the definition structured
+     * was extracted from a VaultPackage.
+     * @return <code>true</code> if unwrapped.
+     */
+    boolean isUnwrapped();
+
+    /**
+     * Checks if the definition was modified since it was last wrapped.
+     * new packages are considered modified.
+     * @return <code>true</code> if modified
+     */
+    boolean isModified();
+
+    /**
+     * Unwrapps the package definition to the underlying node.
+     * @param pack the package
+     * @param force if <code>true</code> unwrapping is forced
+     * @param autoSave if <code>true</code> modifications are saved automatically
+     * @throws RepositoryException if an error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    void unwrap(VaultPackage pack, boolean force, boolean autoSave)
+                    throws RepositoryException, IOException;
+
+    /**
+     * Dumps the coverage of this definition to the given listener
+     * @param listener the listener
+     * @throws RepositoryException if an error occurrs
+     */
+    void dumpCoverage(ProgressTrackerListener listener) throws RepositoryException;
+
+    /**
+     * Returns the dependencies stored in this definition
+     * @return the dependencies
+     */
+    Dependency[] getDependencies();
+
+    /**
+     * Generic method to retrieve a string property of this definition.
+     * @param name the name of the property.
+     * @return the property value or <code>null</code> if it does not exist.
+     */
+    String get(String name);
+
+    /**
+     * Generic method to retrieve a boolean property of this definition.
+     * @param name the name of the property.
+     * @return the property value or <code>null</code> if it does not exist.
+     */
+    boolean getBoolean(String name);
+
+    /**
+     * Generic method to retrieve a date property of this definition.
+     * @param name the name of the property.
+     * @return the property value or <code>null</code> if it does not exist.
+     */
+    Calendar getCalendar(String name);
+
+    /**
+     * Generic method to set a string property to this definition.
+     * @param name the name of the property
+     * @param value the value or <code>null</code> to clear the property
+     * @param autoSave if <code>true</code> the modifications are saved automatically.
+     */
+    void set(String name, String value, boolean autoSave);
+
+    /**
+     * Generic method to set a date property to this definition.
+     * @param name the name of the property
+     * @param value the value or <code>null</code> to clear the property
+     * @param autoSave if <code>true</code> the modifications are saved automatically.
+     */
+    void set(String name, Calendar value, boolean autoSave);
+
+    /**
+     * Generic method to set a boolean property to this definition.
+     * @param name the name of the property
+     * @param value the value
+     * @param autoSave if <code>true</code> the modifications are saved automatically.
+     */
+    void set(String name, boolean value, boolean autoSave);
+
+    /**
+     * Touches the last modified and last modified by property.
+     * @param now calendar or <code>null</code>
+     * @param autoSave if <code>true</code> the modifications are saved automatically.
+     */
+    void touch(Calendar now, boolean autoSave);
+
+    /**
+     * Sets the filter to this definition and stores it in a node representation.
+     *
+     * @param filter the filter to set
+     * @param autoSave if <code>true</code> the modifications are saved automatically.
+     */
+    void setFilter(WorkspaceFilter filter, boolean autoSave);
+
+    /**
+     * Returns the last modified date
+     * @return the last modified date
+     */
+    Calendar getLastModified();
+
+    /**
+     * Returns the last modified user id
+     * @return the last modified user id
+     */
+    String getLastModifiedBy();
+
+    /**
+     * Returns the created date
+     * @return the created date
+     */
+    Calendar getCreated();
+
+    /**
+     * Returns the creator user id
+     * @return the creator
+     */
+    String getCreatedBy();
+
+    /**
+     * Returns the last wrapped date
+     * @return the last wrapped date
+     * @since 2.2.22
+     */
+    Calendar getLastWrapped();
+
+    /**
+     * Returns the wrapper user id
+     * @return the wrapper
+     * @since 2.2.22
+     */
+    String getLastWrappedBy();
+
+    /**
+     * Returns the last unwrapped date
+     * @return the last unwrapped date
+     */
+    Calendar getLastUnwrapped();
+
+    /**
+     * Returns the last unwrapped user id
+     * @return the last unwrapped user id
+     */
+    String getLastUnwrappedBy();
+
+    /**
+     * Returns the date when the package was unpacked
+     * @return the unpacked date
+     */
+    Calendar getLastUnpacked();
+
+    /**
+     * Returns the user id who unpacked the package
+     * @return the unpacked user id
+     */
+    String getLastUnpackedBy();
+
+    /**
+     * Returns <code>true</code> if this package needs a admin user to install it.
+     * @return the "requires root" flag
+     * @deprecated
+     */
+    @Deprecated
+    boolean requiresRoot();
+
+    /**
+     * Returns <code>true</code> if this package needs restart after installation.
+     * @return the "requires restart" flag.
+     */
+    boolean requiresRestart();
+
+    /**
+     * Returns the access control handling defined in the definition, or <code>null</code>
+     * if not defined.
+     * @return the access control handling or <code>null</code>
+     * @since 2.3.2
+     */
+    AccessControlHandling getAccessControlHandling();
+
+    /**
+     * Returns the description of this package
+     * @return the description
+     */
+    String getDescription();
+
+    /**
+     * Returns the build count of this package
+     * @return the build count.
+     */
+    long getBuildCount();
+
+    /**
+     * Returns the meta inf of this package
+     * @return the meta inf
+     * @throws RepositoryException if an error occurs.
+     */
+    MetaInf getMetaInf() throws RepositoryException;
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackageManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackageManager.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackageManager.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/JcrPackageManager.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,334 @@
+/*
+ * 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.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+import javax.jcr.ItemExistsException;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
+import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
+
+/**
+ * Extends the {@link PackageManager} by repository specific operations.
+ */
+public interface JcrPackageManager extends PackageManager {
+
+    /**
+     * Opens a package with the given package id.
+     *
+     * @param id the package id.
+     * @return the new package or <code>null</code> it the package does not exist or is not valid.
+     * @throws RepositoryException if an error occurs
+     * @since 2.3.22
+     */
+    JcrPackage open(PackageId id) throws RepositoryException;
+
+    /**
+     * Opens a package that is based on the given node.
+     *
+     * @param node the underlying node
+     * @return the new package or <code>null</code> it the package is not
+     *         valid.
+     * @throws RepositoryException if an error occurs
+     */
+    JcrPackage open(Node node) throws RepositoryException;
+
+    /**
+     * Opens a package that is based on the given node. If <code>allowInvalid</code>
+     * is <code>true</code> also invalid packages are returned, but only if the
+     * node is file like (i.e. is nt:hierarchyNode and has a
+     * jcr:content/jcr:data property).
+     *
+     * @param node the underlying node
+     * @param allowInvalid if <code>true</code> invalid packages are openend, too.
+     * @return the new package or <code>null</code> it the package is not
+     *         valid unless <code>allowInvalid</code> is <code>true</code>.
+     * @throws RepositoryException if an error occurs
+     */
+    JcrPackage open(Node node, boolean allowInvalid) throws RepositoryException;
+
+    /**
+     * Finds the id of the package that matches the given dependency best.
+     * If <code>onlyInstalled</code> is <code>true</code> only installed packages are searched.
+     *
+     * @param dependency dependency information
+     * @param onlyInstalled if <code>true</code> only installed packages are searched.
+     *
+     * @return the id of the matching package or <code>null</code> if not found.
+     * @throws RepositoryException if an error occurs
+     *
+     * @since 2.4.6
+     */
+    PackageId resolve(Dependency dependency, boolean onlyInstalled) throws RepositoryException;
+
+    /**
+     * Uploads a package. The location is chosen from the installation path of
+     * the package. if the package does not provide such a path, the nameHint
+     * is respected and the package is placed below the package root.
+     * if the package already exists at that path it is not installed and
+     * <code>null</code> is returned unless <code>replace</code> is <code>true</code>.
+     *
+     * @param file package file to upload
+     * @param isTmpFile indicates if the given file is a temp file and can be
+     *        deleted when the package is closed
+     * @param replace if <code>true</code> existing packages are replaced.
+     * @param nameHint hint for the name if package does not provide one
+     * @return the new jcr package or <code>null</code> if not installed
+     * @throws RepositoryException if an error occurrs
+     * @throws IOException if an I/O error occurrs
+     */
+    JcrPackage upload(File file, boolean isTmpFile, boolean replace, String nameHint)
+            throws RepositoryException, IOException;
+
+    /**
+     * Uploads a package. The location is chosen from the installation path of
+     * the package. if the package does not provide such a path, the nameHint
+     * is respected and the package is placed below the package root.
+     * if the package already exists at that path it is not uploaded a
+     * {@link ItemExistsException} is thrown unless <code>replace</code> is
+     * <code>true</code>.
+     *
+     * @param file package file to upload
+     * @param isTmpFile indicates if the given file is a temp file and can be
+     *        deleted when the package is closed
+     * @param replace if <code>true</code> existing packages are replaced.
+     * @param nameHint hint for the name if package does not provide one
+     * @param strict if <code>true</code> import is more strict in regards to errors
+     * @return the new jcr package
+     * @throws RepositoryException if an error occurrs
+     * @throws IOException if an I/O error occurrs
+     */
+    JcrPackage upload(File file, boolean isTmpFile, boolean replace, String nameHint, boolean strict)
+            throws RepositoryException, IOException;
+
+    /**
+     * Uploads a package. The location is chosen from the installation path of
+     * the package. if the package does not provide such a path an IOException is thrown.
+     * if the package already exists at that path it is not uploaded a
+     * {@link ItemExistsException} is thrown unless <code>replace</code> is
+     * <code>true</code>.
+     *
+     * @param in input stream that provides the content of the package. note that after this method returns,
+     *        the input stream is closed in any case.
+     * @param replace if <code>true</code> existing packages are replaced.
+     * @return the new jcr package
+     * @throws RepositoryException if an error occurrs
+     * @throws IOException if an I/O error occurrs
+     */
+    JcrPackage upload(InputStream in, boolean replace) throws RepositoryException, IOException;
+
+    /**
+     * Uploads a package. The location is chosen from the installation path of
+     * the package. if the package does not provide such a path an IOException is thrown.
+     * if the package already exists at that path it is not uploaded a
+     * {@link ItemExistsException} is thrown unless <code>replace</code> is
+     * <code>true</code>.
+     *
+     * @param in input stream that provides the content of the package. note that after this method returns,
+     *        the input stream is closed in any case.
+     * @param replace if <code>true</code> existing packages are replaced.
+     * @param strict if <code>true</code> import is more strict in regards to errors
+     * @return the new jcr package
+     * @throws RepositoryException if an error occurrs
+     * @throws IOException if an I/O error occurrs
+     */
+    JcrPackage upload(InputStream in, boolean replace, boolean strict) throws RepositoryException, IOException;
+
+    /**
+     * Creates a new package below the given folder.
+     *
+     * @param folder parent folder
+     * @param name name of the new package
+     * @return a new jcr package
+     * @throws RepositoryException if a repository error occurrs
+     * @throws IOException if an I/O exception occurs
+     */
+    JcrPackage create(Node folder, String name)
+            throws RepositoryException, IOException;
+
+    /**
+     * Creates a new package with the new group and name.
+     *
+     * @param group group of the new package
+     * @param name name of the new package
+     * @return a new jcr package
+     * @throws RepositoryException if a repository error occurrs
+     * @throws IOException if an I/O exception occurs
+     * @since 2.2.5
+     */
+    JcrPackage create(String group, String name)
+            throws RepositoryException, IOException;
+
+    /**
+     * Creates a new package with the new group, name and version.
+     *
+     * @param group group of the new package
+     * @param name name of the new package
+     * @param version version of the new package; can be <code>null</code>
+     * @return a new jcr package
+     * @throws RepositoryException if a repository error occurrs
+     * @throws IOException if an I/O exception occurs
+     * @since 2.3
+     */
+    JcrPackage create(String group, String name, String version)
+            throws RepositoryException, IOException;
+
+    /**
+     * Removes a package and its snaphost if present.
+     * @param pack the package to remove
+     * @throws RepositoryException if a repository error occurrs
+     * @since 2.2.7
+     */
+    void remove(JcrPackage pack) throws RepositoryException;
+
+    /**
+     * Renames the given package with a new group id and name. Please note that
+     * the package is moved and the internal 'path' is adjusted in the deinition,
+     * but the package is not rewrapped.
+     *
+     * @param pack the package to rename
+     * @param groupId the new group id or <code>null</code>
+     * @param name the new name or <code>null</code>
+     * @return the renamed package
+     * @throws RepositoryException if an error occurs
+     * @throws PackageException if the package is not unwrapped.
+     *
+     * @since 2.0
+     */
+    JcrPackage rename(JcrPackage pack, String groupId, String name)
+            throws PackageException, RepositoryException;
+
+    /**
+     * Renames the given package with a new group id, name and version. Please
+     * note that the package is moved and the internal 'path' is adjusted in
+     * the definition, but the package is not rewrapped.
+     *
+     * @param pack the package to rename
+     * @param groupId the new group id or <code>null</code>
+     * @param name the new name or <code>null</code>
+     * @param version the new version or <code>null</code>
+     * @return the renamed package
+     * @throws RepositoryException if an error occurs
+     * @throws PackageException if the package is not unwrapped.
+     *
+     * @since 2.3
+     */
+    JcrPackage rename(JcrPackage pack, String groupId, String name, String version)
+            throws PackageException, RepositoryException;
+
+    /**
+     * Assembles a package.
+     * @param pack the package to assemble
+     * @param listener a progress listener
+     * @throws PackageException if a package error occurs
+     * @throws RepositoryException if a repository error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    void assemble(JcrPackage pack, ProgressTrackerListener listener)
+            throws PackageException, RepositoryException, IOException;
+
+    /**
+     * Assembles a package.
+     * @param packNode the node of the package
+     * @param definition the definition of the package
+     * @param listener a progress listener
+     * @throws PackageException if a package error occurs
+     * @throws RepositoryException if a repository error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    void assemble(Node packNode, JcrPackageDefinition definition,
+                         ProgressTrackerListener listener)
+            throws PackageException, RepositoryException, IOException;
+
+    /**
+     * Assembles a package directly to a output stream
+     * @param definition the definition of the package
+     * @param listener a progress listener
+     * @param out the output stream to write to
+     * @throws RepositoryException if a repository error occurs
+     * @throws IOException if an I/O error occurs
+     * @throws PackageException if a package error occurs
+     */
+    void assemble(JcrPackageDefinition definition,
+                         ProgressTrackerListener listener, OutputStream out)
+            throws IOException, RepositoryException, PackageException;
+
+    /**
+     * Rewraps the package in respect to its underlying definition.
+     * @param pack the package to rewrap
+     * @param listener the progress listener
+     * @throws PackageException if a package error occurs
+     * @throws RepositoryException if a repository error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    void rewrap(JcrPackage pack, ProgressTrackerListener listener)
+            throws PackageException, RepositoryException, IOException;
+
+    /**
+     * Returns the configured package root node.
+     * @return the package root node
+     * @throws RepositoryException if an error occurs
+     */
+    Node getPackageRoot() throws RepositoryException;
+
+    /**
+     * Returns the configured package root node.
+     * @param noCreate do not create missing root if <code>true</code>
+     * @return the package root node or <code>null</code> if not present and noCreate is <code>true</code>.
+     * @throws RepositoryException if an error occurs
+     */
+    Node getPackageRoot(boolean noCreate) throws RepositoryException;
+
+    /**
+     * Returns the list of all packages installed below the package root.
+     *
+     * @return a list of packages
+     * @throws RepositoryException if an error occurs
+     */
+    List<JcrPackage> listPackages() throws RepositoryException;
+
+    /**
+     * Returns the list of all packages installed below the package root that are
+     * included in the filter.
+     *
+     * @param filter filter for packages
+     * @return a list of packages
+     * @throws RepositoryException if an error occurs
+     */
+    List<JcrPackage> listPackages(WorkspaceFilter filter) throws RepositoryException;
+
+
+    /**
+     * Returns the list of all packages installed below the package root that
+     * match the given group. if <code>group</code> is <code>null</code> all
+     * packages are returned.
+     *
+     * @param group the group filter
+     * @param built if <code>true</code> only packages with size > 0 are listed
+     * @return the list of packages
+     * @throws RepositoryException if an error occurs
+     */
+    List<JcrPackage> listPackages(String group, boolean built) throws RepositoryException;
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageException.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,40 @@
+/*
+ * 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>PackageException</code>...
+ */
+public class PackageException extends Exception {
+
+    public PackageException() {
+        super();
+    }
+
+    public PackageException(String message) {
+        super(message);
+    }
+
+    public PackageException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public PackageException(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/PackageId.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageId.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageId.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageId.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,398 @@
+/*
+ * 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.util.Text;
+
+/**
+ * <code>PackageId</code> provides the basic metrics for identifying a package.
+ * A package id consists of a group id, a name and a version.
+ * the group is a relative path, eg: "company/project/subgroup", the name and the version
+ * can be of any format.
+ */
+public class PackageId implements Comparable<PackageId> {
+
+    public static final String ETC_PACKAGES = "/etc/packages";
+
+    public static final String ETC_PACKAGES_PREFIX = "/etc/packages/";
+
+    public static final PackageId[] EMPTY = new PackageId[0];
+    
+    private final String group;
+
+    private final String name;
+
+    private final Version version;
+
+    private final String str;
+
+    private final boolean fromPath;
+
+    /**
+     * Creates a new package id
+     * @param path path of the package
+     */
+    public PackageId(String path) {
+        fromPath = true;
+        path = path.trim();
+        int idx = path.lastIndexOf('.');
+        if (idx > 0) {
+            String ext = path.substring(idx);
+            if (ext.equalsIgnoreCase(".zip") || ext.equalsIgnoreCase(".jar")) {
+                path = path.substring(0, idx);
+            }
+        }
+        idx = path.lastIndexOf('/');
+        String name;
+        if (idx < 0) {
+            name = path;
+            this.group = "";
+        } else {
+            name = path.substring(idx + 1);
+            String grp = path.substring(0, idx);
+            if (grp.equals(ETC_PACKAGES)) {
+                grp = "";
+            } else if (grp.startsWith(ETC_PACKAGES_PREFIX)) {
+                grp = grp.substring(ETC_PACKAGES_PREFIX.length());
+            } else if (grp.startsWith("/")) {
+                grp = grp.substring(1);
+            }
+            this.group = grp;
+        }
+        // check if name contains a version
+        String[] segs = Text.explode(name, '-');
+        int i=segs.length-1;
+        while (i>0) {
+            try {
+                // accept numbers < 1000 (hotfix case)
+                if (Integer.parseInt(segs[i]) >= 1000) {
+                    break;
+                }
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+            // check if starts with a letter'
+            if (Character.isJavaIdentifierStart(segs[i].charAt(0))) {
+                // then need a digit
+                if (segs[i].length() == 1 || !Character.isDigit(segs[i].charAt(1)) && !segs[i].equals("SNAPSHOT")) {
+                    break;
+                }
+            }
+            i--;
+        }
+        if (i == segs.length-1) {
+            this.name = name;
+            version = Version.EMPTY;
+        } else {
+            StringBuilder str = new StringBuilder();
+            for (int j = 0; j<= i; j++) {
+                if (j > 0) {
+                    str.append('-');
+                }
+                str.append(segs[j]);
+            }
+            this.name = str.toString();
+            str.setLength(0);
+            for (int j = i+1; j<segs.length; j++) {
+                if (j > i+1) {
+                    str.append('-');
+                }
+                str.append(segs[j]);
+            }
+            this.version = Version.create(str.toString());
+        }
+        this.str = getString(group, this.name, version);
+
+    }
+    /**
+     * Creates a new package id
+     * @param path path of the package
+     * @param version version of the package
+     */
+    public PackageId(String path, String version) {
+        this(path, Version.create(version));
+    }
+
+    /**
+     * Creates a new package id
+     * @param path path of the package
+     * @param version version of the package
+     */
+    public PackageId(String path, Version version) {
+        fromPath = true;
+        path = path.trim();
+        int idx = path.lastIndexOf('.');
+        if (idx > 0) {
+            String ext = path.substring(idx);
+            if (ext.equalsIgnoreCase(".zip") || ext.equalsIgnoreCase(".jar")) {
+                path = path.substring(0, idx);
+            }
+        }
+        if (version != null && path.endsWith('-'+version.toString())) {
+            path = path.substring(0, path.length() - version.toString().length() - 1);
+        }
+        idx = path.lastIndexOf('/');
+        if (idx < 0) {
+            this.name = path;
+            this.group = "";
+        } else {
+            this.name = path.substring(idx + 1);
+            String grp = path.substring(0, idx);
+            if (grp.equals(ETC_PACKAGES)) {
+                grp = "";
+            } else if (grp.startsWith(ETC_PACKAGES_PREFIX)) {
+                grp = grp.substring(ETC_PACKAGES_PREFIX.length());
+            } else if (grp.startsWith("/")) {
+                grp = grp.substring(1);
+            }
+            this.group = grp;
+        }
+        // sanitize version
+        if (version == null || version.toString().length() == 0) {
+            version = Version.EMPTY;
+        }
+        this.version = version;
+        this.str = getString(group, name, version);
+    }
+
+    /**
+     * Creates a new package id
+     * @param group group id
+     * @param name name
+     * @param version version
+     */
+    public PackageId(String group, String name, String version) {
+        this(group, name, Version.create(version));
+    }
+
+    /**
+     * Creates a new package id
+     * @param group group id
+     * @param name name
+     * @param version version
+     */
+    public PackageId(String group, String name, Version version) {
+        fromPath = false;
+        // validate group
+        if (group.equals(ETC_PACKAGES)) {
+            group = "";
+        } else if (group.startsWith(ETC_PACKAGES_PREFIX)) {
+            group = group.substring(ETC_PACKAGES_PREFIX.length());
+        } else if (group.startsWith("/")) {
+            group = group.substring(1);
+        }
+        this.group = group;
+        this.name = name;
+        this.version = version == null ? Version.EMPTY : version;
+        this.str = getString(this.group, name, this.version);
+    }
+
+    /**
+     * Returns a package id from a id string. if the given id is null or an
+     * empty string, <code>null</code> is returned.
+     * @param str the string
+     * @return the package id
+     */
+    public static PackageId fromString(String str) {
+        if (str == null || str.length() == 0) {
+            return null;
+        }
+        String[] segs = str.split(":");
+        if (segs.length == 1) {
+            return new PackageId("", segs[0], "");
+        } else if (segs.length == 2) {
+            return new PackageId(segs[0], segs[1], "");
+        } else {
+            return new PackageId(segs[0], segs[1], segs[2]);
+        }
+    }
+
+    /**
+     * Returns an array of package id from strings
+     * @param str the strings
+     * @return the array of package ids
+     */
+    public static PackageId[] fromString(String ... str) {
+        PackageId[] ret = new PackageId[str.length];
+        for (int i=0; i<str.length; i++) {
+            ret[i] = PackageId.fromString(str[i]);
+        }
+        return ret;
+    }
+
+    /**
+     * Creates a comma separated list of id strings.
+     * @param packs the ids
+     * @return the string
+     */
+    public static String toString(PackageId ... packs) {
+        String delim = "";
+        StringBuilder b = new StringBuilder();
+        for (PackageId pack: packs) {
+            b.append(delim).append(pack);
+            delim=",";
+        }
+        return b.toString();
+    }
+
+    /**
+     * Checks if this definition was constructed from a path, rather from a
+     * group and name.
+     * @return <code>true</code> if constructed from path.
+     *
+     * @since 2.2.26
+     */
+    public boolean isFromPath() {
+        return fromPath;
+    }
+
+    /**
+     * Returns the path of this package. please note that since 2.3 this also
+     * includes the version, but never the extension (.zip).
+     *
+     * @return the path of this package
+     * @since 2.2
+     */
+    public String getInstallationPath() {
+        StringBuilder b = new StringBuilder(ETC_PACKAGES_PREFIX);
+        if (group.length() > 0) {
+            b.append(group);
+            b.append("/");
+        }
+        b.append(name);
+        if (version.toString().length() > 0) {
+            b.append("-").append(version);
+        }
+        return b.toString();
+    }
+
+    /**
+     * Returns the group id of this package
+     * @return the group id;
+     * @since 2.2
+     */
+    public String getGroup() {
+        return group;
+    }
+
+    /**
+     * Returns the name of this package which is the last segment of the path.
+     * @return the name of this package.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the version of this package or and empty string if n/a.
+     * @return the version of this package
+     * @since 2.0
+     */
+    public String getVersionString() {
+        return version.toString();
+    }
+
+    /**
+     * Returns a download name in the form
+     * <code>name [ "-" version ] ".zip"</code>
+     * @return the download name
+     * @since 2.0
+     */
+    public String getDownloadName() {
+        StringBuilder str = new StringBuilder(name);
+        if (version.toString().length() > 0) {
+            str.append("-").append(version);
+        }
+        str.append(".zip");
+        return str.toString();
+    }
+
+    /**
+     * Returns the version of this package or <code>null</code> if n/a.
+     * @return the version of this package
+     */
+    public Version getVersion() {
+        return version;
+    }
+
+    /**
+     * Returns a string representation of this id
+     */
+    @Override
+    public String toString() {
+        return str;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return this == o ||
+                o instanceof PackageId && str.equals(o.toString());
+
+    }
+
+    @Override
+    public int hashCode() {
+        return str.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     *  
+     * Compares this id with the given one.
+     */
+    public int compareTo(PackageId o) {
+        int comp = group.compareTo(o.getGroup());
+        if (comp != 0) {
+            return comp;
+        }
+        comp = name.compareTo(o.getName());
+        if (comp != 0) {
+            return comp;
+        }
+        return version.compareTo(o.getVersion());
+    }
+
+    /**
+     * Internally get the string representation, colon separated.
+     * @param group group name
+     * @param name name
+     * @param version version
+     * @return string version
+     */
+    private static String getString(String group, String name, Version version) {
+        return getString(group, name, version == null ? "" : version.toString());
+    }
+
+    /**
+     * Internally get the string representation, colon separated.
+     * @param group group name
+     * @param name name
+     * @param version version
+     * @return string version
+     */
+    private static String getString(String group, String name, String version) {
+        StringBuilder b = new StringBuilder();
+        b.append(group).append(':');
+        b.append(name);
+        if (version.length() > 0) {
+            b.append(':').append(version);
+        }
+        return b.toString();
+    }
+
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageManager.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageManager.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackageManager.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,145 @@
+/*
+ * 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.File;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * The package manager is used to deal with packages. the following operations
+ * are defined:
+ *
+ * <dl>
+ * <dt>open</dt>
+ * <dd>read underlying data and validate them</dd>
+ *
+ * <dt>close</dt>
+ * <dd>release underlying data. the package is unusable afterwards</dd>
+ *
+ * <dt>upload</dt>
+ * <dd>import the package from a binary source to the system. for example
+ * create a new jcr node structure or create a file.
+ * </dd>
+ *
+ * <dt>export</dt>
+ * <dd>export the package in binary format.
+ * </dd>
+ *
+ * <dt>unwrap</dt>
+ * <dd>extract the meta information of the binary data and store it in the
+ * repository</dd>
+ *
+ * <dt>assemble</dt>
+ * <dd>create a vault export of the repository using the package definition
+ * and filter.</dd>
+ *
+ * <dt>extract</dt>
+ * <dd>extract the packaged content to the repository.</dd>
+ *
+ * <dt>install</dt>
+ * <dd>install the packaged content to the repository but create a snapshot if needed.</dd>
+ *
+ * <dt>snapshot</dt>
+ * <dd>assemble snapshot information that can be used for a later uninstall. this
+ * is done by assembling the content using the same filter definition.</dd>
+ *
+ * <dt>uninstall</dt>
+ * <dd>revert changes to the repository of a previous installation.</dd>
+ *
+ * </dl>
+ */
+public interface PackageManager {
+
+    /**
+     * Opens the given file and creates a package
+     * @param file the file
+     * @return the package
+     * @throws IOException if an error occurrs
+     */
+    VaultPackage open(File file) throws IOException;
+
+    /**
+     * Opens the given file and creates a package
+     * @param file the file
+     * @param strict if <code>true</code> the import is more strict in respect to errors.
+     * @return the package
+     * @throws IOException if an error occurrs
+     */
+    VaultPackage open(File file, boolean strict) throws IOException;
+
+    /**
+     * Assembles a package using the given meta information and file to
+     * store to. if file is <code>null</code> a temp file is generated.
+     *
+     * @param s the repository session
+     * @param opts export options
+     * @param file the file to write to
+     * @return the newly created vault package
+     *
+     * @throws IOException if an I/O error occurs.
+     * @throws RepositoryException if a repository error during building occurs.
+     * @throws IllegalStateException if the package is not new.
+     */
+    VaultPackage assemble(Session s, ExportOptions opts, File file)
+            throws IOException, RepositoryException;
+
+    /**
+     * Assembles a package using the given meta information. The package
+     * is directly streamed to the given output stream.
+     *
+     * @param s the repository session
+     * @param opts the export options
+     * @param out the output stream to write to
+     * @throws IOException if an I/O error occurs.
+     * @throws RepositoryException if a repository error during building occurs.
+     * @throws IllegalStateException if the package is not new.
+     */
+    void assemble(Session s, ExportOptions opts, OutputStream out)
+            throws IOException, RepositoryException;
+
+    /**
+     * Re-wraps a package using the given meta information and file to
+     * store to. if file is <code>null</code> a temp file is generated.
+     *
+     * @param opts export options
+     * @param src source package
+     * @param file the file to write to
+     * @return the newly created vault package
+     *
+     * @throws IOException if an I/O error occurs.
+     * @throws RepositoryException if a repository error during building occurs.
+     * @throws IllegalStateException if the package is not new.
+     */
+    VaultPackage rewrap(ExportOptions opts, VaultPackage src, File file)
+            throws IOException, RepositoryException;
+
+    /**
+     * Re-wraps the given package with the definition provided in the export
+     * options.
+     * @param opts export options
+     * @param src source package
+     * @param out destination output stream
+     * @throws IOException if an I/O error occurs
+     */
+    void rewrap(ExportOptions opts, VaultPackage src, OutputStream out)
+            throws IOException;
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Packaging.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Packaging.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Packaging.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Packaging.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,68 @@
+/*
+ * 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.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * Default access point to package managers.
+ * @since 2.4.0
+ */
+public interface Packaging {
+
+    /**
+     * Returns a non-repository based package manager.
+     * @return the package manager
+     */
+    PackageManager getPackageManager();
+
+    /**
+     * Returns a repository based package manager.
+     * @param session repository session
+     * @return the package manager
+     */
+    JcrPackageManager getPackageManager(Session session);
+
+    /**
+     * Creates a new jcr package definition based on the given node.
+     * @param defNode the node
+     * @return the definition
+     */
+    JcrPackageDefinition createPackageDefinition(Node defNode);
+
+    /**
+     * Opens a package that is based on the given node. If <code>allowInvalid</code>
+     * is <code>true</code> also invalid packages are returned, but only if the
+     * node is file like (i.e. is nt:hierarchyNode and has a
+     * jcr:content/jcr:data property).
+     *
+     * This is a shortcut version of {@link org.apache.jackrabbit.vault.packaging.JcrPackageManager#open(javax.jcr.Node, boolean)}
+     * which does not create a package manager instance.
+     *
+     * @param node the underlying node
+     * @param allowInvalid if <code>true</code> invalid packages are openend, too.
+     * @return the new package or <code>null</code> it the package is not
+     *         valid unless <code>allowInvalid</code> is <code>true</code>.
+     * @throws javax.jcr.RepositoryException if an error occurs
+     * 
+     * @since 2.3.0
+     */
+    JcrPackage open(Node node, boolean allowInvalid) throws RepositoryException;
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackagingService.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackagingService.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackagingService.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/PackagingService.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,94 @@
+/*
+ * 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.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.packaging.impl.JcrPackageDefinitionImpl;
+import org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl;
+import org.apache.jackrabbit.vault.packaging.impl.JcrPackageManagerImpl;
+import org.apache.jackrabbit.vault.packaging.impl.PackageManagerImpl;
+import org.apache.jackrabbit.vault.util.JcrConstants;
+
+/**
+ * Default access point to package managers for non OSGi clients.
+ * 
+ * @since 2.0
+ */
+public class PackagingService {
+
+    /**
+     * Returns a non-repository based package manager.
+     * @return the package manager
+     */
+    public static PackageManager getPackageManager() {
+        return new PackageManagerImpl();
+    }
+
+    /**
+     * Returns a repository based package manager.
+     * @param session repository session
+     * @return the package manager
+     */
+    public static JcrPackageManager getPackageManager(Session session) {
+        return new JcrPackageManagerImpl(session);
+    }
+
+    /**
+     * Creates a new jcr package definition based on the given node.
+     * @param defNode the node
+     * @return the definition
+     * @since 2.2.14
+     */
+    public static JcrPackageDefinition createPackageDefinition(Node defNode) {
+        return new JcrPackageDefinitionImpl(defNode);
+    }
+
+    /**
+     * Opens a package that is based on the given node. If <code>allowInvalid</code>
+     * is <code>true</code> also invalid packages are returned, but only if the
+     * node is file like (i.e. is nt:hierarchyNode and has a
+     * jcr:content/jcr:data property).
+     *
+     * This is a shortcut version of {@link JcrPackageManager#open(Node, boolean)}
+     * which does not create a package manager instance.
+     *
+     * @param node the underlying node
+     * @param allowInvalid if <code>true</code> invalid packages are openend, too.
+     * @return the new package or <code>null</code> it the package is not
+     *         valid unless <code>allowInvalid</code> is <code>true</code>.
+     * @throws RepositoryException if an error occurs
+     * 
+     * @since 2.3.0
+     */
+    public static JcrPackage open(Node node, boolean allowInvalid)
+            throws RepositoryException {
+        JcrPackage pack = new JcrPackageImpl(node);
+        if (pack.isValid()) {
+            return pack;
+        } else if (allowInvalid
+                && node.isNodeType(JcrConstants.NT_HIERARCHYNODE)
+                && node.hasProperty(JcrConstants.JCR_CONTENT + "/" + JcrConstants.JCR_DATA)) {
+            return pack;
+        } else {
+            return null;
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/VaultPackage.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/VaultPackage.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/VaultPackage.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/VaultPackage.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,259 @@
+/*
+ * 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.File;
+import java.util.Calendar;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.config.MetaInf;
+import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
+import org.apache.jackrabbit.vault.fs.io.Archive;
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+
+/**
+ * Defines a vault package. A vault package is a binary assembled representation
+ * of a vault export.
+ */
+public interface VaultPackage {
+
+    /**
+     * Name of the last modified meta-inf property
+     */
+    String NAME_LAST_MODIFIED = "lastModified";
+
+    /**
+     * Name of the last modified by meta-inf property
+     */
+    String NAME_LAST_MODIFIED_BY = "lastModifiedBy";
+
+    /**
+     * Name of the group property
+     * @since 2.2
+     */
+    String NAME_GROUP = "group";
+
+    /**
+     * Name of the 'name' property
+     * @since 2.2
+     */
+    String NAME_NAME = "name";
+
+    /**
+     * Name of the build count meta-inf property
+     */
+    String NAME_BUILD_COUNT = "buildCount";
+
+    /**
+     * Name of the version meta-inf property
+     */
+    String NAME_VERSION = "version";
+
+    /**
+     * Name of the dependencies meta-inf property
+     */
+    String NAME_DEPENDENCIES = "dependencies";
+
+    /**
+     * Name of the created meta-inf property
+     */
+    String NAME_CREATED = "created";
+
+    /**
+     * Name of the created by meta-inf property
+     */
+    String NAME_CREATED_BY = "createdBy";
+
+    /**
+     * Name of the last wrapped meta-inf property
+     * @since 2.2.22
+     */
+    String NAME_LAST_WRAPPED = "lastWrapped";
+
+    /**
+     * Name of the last wrapped by meta-inf property
+     * @since 2.2.22
+     */
+    String NAME_LAST_WRAPPED_BY = "lastWrappedBy";
+
+    /**
+     * Name of the 'acHandling' by meta-inf property.
+     * @see AccessControlHandling
+     */
+    String NAME_AC_HANDLING = "acHandling";
+
+    /**
+     * Name of the 'cndPattern' by meta-inf property.
+     * @since 2.3.12
+     */
+    String NAME_CND_PATTERN = "cndPattern";
+
+    /**
+     * Name of the description meta-inf property
+     */
+    String NAME_DESCRIPTION = "description";
+
+    /**
+     * Name of the flag that indicates in only admin sessions
+     * can extract this package.
+     */
+    String NAME_REQUIRES_ROOT = "requiresRoot";
+
+    /**
+     * Name of the flag that indicates that the system needs a restart after
+     * package extraction.
+     */
+    String NAME_REQUIRES_RESTART = "requiresRestart";
+
+    /**
+     * Name of the flag that indicates to disable intermediate saves.
+     */
+    String NAME_DISABLE_INTERMEDIATE_SAVE = "noIntermediateSaves";
+
+    /**
+     * the prefix for an install hook property. eg:
+     * 'installhook.test1.class = ....'
+     */
+    String PREFIX_INSTALL_HOOK = "installhook.";
+
+
+    /**
+     * Returns the id of this package or <code>null</code> if the id can't
+     * be determined.
+     * @return the id of this package.
+     */
+    PackageId getId();
+
+    /**
+     * Checks if this package is valid.
+     * @return <code>true</code> if this package is valid.
+     */
+    boolean isValid();
+
+    /**
+     * Checks if this package is closed.
+     * @return <code>true</code> if this package is closed.
+     */
+    boolean isClosed();
+
+    /**
+     * Returns the meta inf that was either loaded or specified during build.
+     * @return the meta inf or <code>null</code>.
+     */
+    MetaInf getMetaInf();
+
+    /**
+     * Returns the size of the package or -1 if n/a.
+     * @return the size
+     */
+    long getSize();
+
+    /**
+     * Returns the last modification date or <code>null</code> if n/a.
+     * @return last modification date or <code>null</code>
+     */
+    Calendar getLastModified();
+
+    /**
+     * Returns the user that last modified the package or <code>null</code> if n/a.
+     * @return the user or <code>null</code>
+     */
+    String getLastModifiedBy();
+
+    /**
+     * Returns the date when this package was built or <code>null</code> if n/a.
+     * @return the creation date
+     */
+    Calendar getCreated();
+
+    /**
+     * Returns the user that built this package or null if n/a.
+     * @return the creator
+     */
+    String getCreatedBy();
+
+    /**
+     * Returns the date when this package was wrapped or <code>null</code> if n/a.
+     * @return the wrapped date
+     * @since 2.2.22
+     */
+    Calendar getLastWrapped();
+
+    /**
+     * Returns the user that wrapped this package or null if n/a.
+     * @return the wrapper
+     * @since 2.2.22
+     */
+    String getLastWrappedBy();
+
+    /**
+     * Returns a description of this package or <code>null</code> if n/a
+     * @return a description
+     */
+    String getDescription();
+
+    /**
+     * Returns <code>true</code> if this package can only be extracted by a
+     * admin session.
+     * @return <code>true</code> if this package requires an admin session for extraction.
+     */
+    boolean requiresRoot();
+
+    /**
+     * Returns an unmodifiable list of dependencies
+     * @return list of dependencies
+     */
+    Dependency[] getDependencies();
+
+    /**
+     * Returns the access control handling defined in this package.
+     * @return the access control handling.
+     */
+    AccessControlHandling getACHandling();
+
+    /**
+     * Extracts the package contents to the repository
+     *
+     * @param session repository session
+     * @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.
+     */
+    void extract(Session session, ImportOptions opts) throws RepositoryException, PackageException;
+
+    /**
+     * Returns the underlying file or <code>null</code> if not available.
+     * @return the file
+     * @since 2.0
+     */
+    File getFile();
+
+    /**
+     * Closes this package and releases underlying data.
+     */
+    void close();
+
+    /**
+     * Returns the underlying package archive
+     * @return the archive or <code>null</code> if already closed
+     */
+    Archive getArchive();
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Version.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Version.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Version.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/Version.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,224 @@
+/*
+ * 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.Arrays;
+import java.util.List;
+
+import org.apache.jackrabbit.vault.util.Text;
+
+/**
+ * Implements a package version.
+ * @since 2.0
+ */
+public class Version implements Comparable<Version> {
+
+    /**
+     * The empty version
+     */
+    public static final Version EMPTY = new Version("", new String[0]);
+
+    /**
+     * internal string representation
+     */
+    private final String str;
+
+    /**
+     * All segments of this version
+     */
+    private final String[] segments;
+
+    /**
+     * Creates a new version from the given string.
+     * @param str the version string.
+     * @return the new version or {@link Version#EMPTY} if <code>str</code> is an empty string.
+     * @since 2.2.4
+     */
+    public static Version create(String str) {
+        if (str == null || str.length() == 0) {
+            return Version.EMPTY;
+        }else {
+            return new Version(str, Text.explode(str, '.'));
+        }
+    }
+
+    /**
+     * Creates a new version from version segments
+     * @param segments version segments
+     * @return the new version or {@link Version#EMPTY} if <code>segments</code> is empty.
+     * @since 2.2.4
+     */
+    public static Version create(String[] segments) {
+        if (segments == null || segments.length == 0) {
+            return Version.EMPTY;
+        } else {
+            return new Version(Text.implode(segments, "."), segments);
+        }
+    }
+
+    /**
+     * Internal constructor
+     * @param str string
+     * @param segments segments
+     */
+    private Version(String str, String[] segments) {
+        if (str == null) {
+            throw new NullPointerException("Version String must not be null.");
+        }
+        this.str = str;
+        this.segments = segments;
+    }
+
+    @Override
+    public int hashCode() {
+        return str.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return this == o ||
+                o instanceof Version && str.equals(((Version) o).str);
+
+    }
+
+    @Override
+    public String toString() {
+        return str;
+    }
+
+    /**
+     * Returns all segments.
+     * @return all segments.
+     */
+    public String[] getNormalizedSegments() {
+        return segments;
+    }
+
+    /**
+     * Compares this version to the given one, segment by segment with a special
+     * "SNAPSHOT" handling.
+     *
+     * Examples:
+     * "1" < "2"
+     * "1.0" < "2"
+     * "2.0.1" < "2.1"
+     * "2.1" < "2.1.1"
+     * "2.9" < "2.11"
+     * "2.1" > "2.1-SNAPSHOT"
+     * "2.1" > "2.1-R1234556"
+     * "2.1-R12345" < "2.1-SNAPSHOT"
+     *
+     * @param o the other version
+     * @return  a negative integer, zero, or a positive integer as this version
+     *		is less than, equal to, or greater than the specified version.
+     */
+    public int compareTo(Version o) {
+        String[] oSegs = o.getNormalizedSegments();
+        for (int i=0; i< Math.min(segments.length, oSegs.length); i++) {
+            String s1 = segments[i];
+            String s2 = oSegs[i];
+            if (s1.equals(s2)) {
+                continue;
+            }
+            try {
+                int v1 = Integer.parseInt(segments[i]);
+                int v2 = Integer.parseInt(oSegs[i]);
+                if (v1 != v2) {
+                    return v1 - v2;
+                }
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+            String ss1[] = Text.explode(s1,'-');
+            String ss2[] = Text.explode(s2,'-');
+            for (int j=0; j< Math.min(ss1.length, ss2.length); j++) {
+                String c1 = ss1[j];
+                String c2 = ss2[j];
+                try {
+                    int v1 = Integer.parseInt(c1);
+                    int v2 = Integer.parseInt(c2);
+                    if (v1 != v2) {
+                        return v1 - v2;
+                    }
+                } catch (NumberFormatException e) {
+                    // ignore
+                }
+                int c = c1.compareTo(c2);
+                if (c!=0) {
+                    return c;
+                }
+            }
+            int c = ss1.length - ss2.length;
+            if (c != 0) {
+                return -c;
+            }
+        }
+        return segments.length - oSegs.length;
+    }
+
+    /**
+     * Compares this version to the given one, segment by segment without any special
+     * "SNAPSHOT" handling.
+     *
+     * Examples:
+     * "1" < "2"
+     * "1.0" < "2"
+     * "2.0.1" < "2.1"
+     * "2.1" < "2.1.1"
+     * "2.9" < "2.11"
+     * "2.1" < "2.1-SNAPSHOT"
+     * "2.1" < "2.1-R1234556"
+     * "2.1-R12345" < "2.1-SNAPSHOT"
+     *
+     * @param o the other version
+     * @return  a negative integer, zero, or a positive integer as this version
+     *		is less than, equal to, or greater than the specified version.
+     */
+    public int osgiCompareTo(Version o) {
+        // first convert into 'osgi' form
+        List<String> segs0 = new ArrayList<String>();
+        List<String> segs1 = new ArrayList<String>();
+        for (String s: segments) {
+            segs0.addAll(Arrays.asList(Text.explode(s, '-')));
+        }
+        for (String s: o.getNormalizedSegments()) {
+            segs1.addAll(Arrays.asList(Text.explode(s, '-')));
+        }
+        int len = Math.min(segs0.size(), segs1.size());
+        for (int i=0; i<len; i++) {
+            String s1 = segs0.get(i);
+            String s2 = segs1.get(i);
+            int c = s1.compareTo(s2);
+            if (c == 0) {
+                continue;
+            }
+            try {
+                int v1 = Integer.parseInt(s1);
+                int v2 = Integer.parseInt(s2);
+                if (v1 != v2) {
+                    return v1 - v2;
+                }
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+            return c;
+        }
+        return segs0.size() - segs1.size();
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/VersionRange.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/VersionRange.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/VersionRange.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/VersionRange.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,223 @@
+/*
+ * 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;
+
+/**
+ * Implements a version range
+ * @since 2.0
+ */
+public class VersionRange {
+
+    /**
+     * Infinite (covers all) range.
+     */
+    public static final VersionRange INFINITE = new VersionRange(null, true, null, true);
+
+    /**
+     * lower bound
+     */
+    private final Version low;
+
+    /**
+     * specifies if lower bound is inclusive
+     */
+    private final boolean lowIncl;
+
+    /**
+     * upper bound
+     */
+    private final Version high;
+
+    /**
+     * specifies if upper bound is inclusive
+     */
+    private final boolean highIncl;
+
+    /**
+     * internal string representation
+     */
+    private final String str;
+
+    /**
+     * Creates a new version range.
+     * @param low lower bound or <code>null</code>
+     * @param lowIncl specifies if lower bound is inclusive
+     * @param high upper bound or <code>null</code>
+     * @param highIncl specifies if upper bound is inclusive
+     * @throws IllegalArgumentException if bounds are not valid
+     */
+    public VersionRange(Version low, boolean lowIncl, Version high, boolean highIncl) {
+        // check if range is valid
+        if (low != null && high != null) {
+            int comp = low.compareTo(high);
+            if (comp > 0) {
+                throw new IllegalArgumentException("lower bound must be less or equal to upper bound.");
+            } else if (comp == 0) {
+                if (!lowIncl || !highIncl) {
+                    throw new IllegalArgumentException("invalid empty range. upper and lower bound must be inclusive.");
+                }
+            }
+        }
+        this.low = low;
+        this.lowIncl = lowIncl;
+        this.high = high;
+        this.highIncl = highIncl;
+        StringBuilder b = new StringBuilder();
+        if (low == null && high == null) {
+            // infinite range, empty string
+        } else if (high == null) {
+            // no high bound,
+            if (lowIncl) {
+                // special case, just use version
+                b.append(low);
+            } else {
+                b.append('(');
+                b.append(low);
+                b.append(",)");
+            }
+        } else if (low == null) {
+            b.append("[,");
+            b.append(high);
+            b.append(highIncl ? ']' : ')');
+        } else {
+            b.append(lowIncl ? '[' : '(');
+            b.append(low);
+            b.append(',');
+            b.append(high);
+            b.append(highIncl ? ']' : ')');
+        }
+        this.str = b.toString();
+    }
+
+    /**
+     * Creates a new version range that exactly includes the given version.
+     * @param v the version.
+     */
+    public VersionRange(Version v) {
+        this(v, true, v, true);
+    }
+
+    /**
+     * Returns the lower bound
+     * @return the lower bound or <code>null</code>
+     */
+    public Version getLow() {
+        return low;
+    }
+
+    /**
+     * Returns <code>true</code> if the lower bound is inclusive
+     * @return <code>true</code> if the lower bound is inclusive
+     */
+    public boolean isLowInclusive() {
+        return lowIncl;
+    }
+
+    /**
+     * Returns the upper bound
+     * @return the upper bound or <code>null</code>
+     */
+    public Version getHigh() {
+        return high;
+    }
+
+    /**
+     * Returns <code>true</code> if the upper bound is inclusive
+     * @return <code>true</code> if the upper bound is inclusive
+     */
+    public boolean isHighInclusive() {
+        return highIncl;
+    }
+
+    @Override
+    public int hashCode() {
+        return str.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return this == obj ||
+                obj instanceof VersionRange && str.equals(obj.toString());
+    }
+
+    @Override
+    public String toString() {
+        return str;
+    }
+
+    /**
+     * Checks if the given version is in this range.
+     * @param v the version to check
+     * @return <code>true</code> if the given version is in this range.
+     */
+    public boolean isInRange(Version v) {
+        if (low != null) {
+            int comp = v.osgiCompareTo(low);
+            if (comp < 0 || comp == 0 && !lowIncl) {
+                return false;
+            }
+        }
+        if (high != null) {
+            int comp = v.osgiCompareTo(high);
+            if (comp > 0 || comp == 0 && !highIncl) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Creates a range from a string
+     * @param str string
+     * @return the version range
+     */
+    public static VersionRange fromString(String str) {
+        int idx = str.indexOf(',');
+        if (idx >= 0) {
+            boolean linc = false;
+            int lm = str.indexOf('(');
+            if (lm < 0) {
+                lm = str.indexOf('[');
+                if (lm < 0) {
+                    throw new IllegalArgumentException("Range must start with '[' or '('");
+                }
+                linc = true;
+            }
+            boolean hinc = false;
+            int hm = str.indexOf(')');
+            if (hm < 0) {
+                hm = str.indexOf(']');
+                if (hm < 0) {
+                    throw new IllegalArgumentException("Range must end with ']' or ')'");
+                }
+                hinc = true;
+            }
+            String low = str.substring(lm + 1, idx).trim();
+            String high = str.substring(idx+1, hm).trim();
+            Version vLow = low.length() == 0 ? null : Version.create(low);
+            Version vHigh = high.length() == 0 ? null : Version.create(high);
+            return new VersionRange(vLow, linc, vHigh, hinc);
+        } else if (str.length() == 0) {
+            // infinite range
+            return new VersionRange(null, false, null, false);
+        } else {
+            // simple range where given version is minimum
+            return new VersionRange(Version.create(str), true, null, false);
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/AdminPermissionChecker.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/AdminPermissionChecker.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/AdminPermissionChecker.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/AdminPermissionChecker.java Sat Aug 10 05:53:42 2013
@@ -0,0 +1,68 @@
+/*
+ * 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.impl;
+
+import java.util.Iterator;
+
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility class to check if a user/session has administrative permissions (e.g. to check if a package can be installed)
+ */
+public class AdminPermissionChecker {
+
+    private static final Logger log = LoggerFactory.getLogger(AdminPermissionChecker.class);
+    private static final String ADMIN_USER = "admin";
+    private static final String SYSTEM_USER = "system";
+    private static final String ADMINISTRATORS_GROUP = "administrators";
+
+    /**
+     * Checks if the user who opened the session has administrative permissions
+     *
+     * @param session a JCR session
+     * @return whether the passed session is an admin session
+     * @throws RepositoryException
+     */
+    public static boolean hasAdministrativePermissions(Session session) throws RepositoryException {
+        String userId = session.getUserID();
+        boolean isAdministrator = ADMIN_USER.equals(userId) || SYSTEM_USER.equals(userId);
+        boolean isJackrabbitSession = session instanceof JackrabbitSession;
+        if (!isAdministrator) {
+            if (isJackrabbitSession) {
+                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
+                Authorizable authorizable = jackrabbitSession.getUserManager().getAuthorizable(userId);
+                Iterator<Group> groupIterator = authorizable.memberOf();
+                while (groupIterator.hasNext()) {
+                    if (ADMINISTRATORS_GROUP.equals(groupIterator.next().getID())) {
+                        isAdministrator = true;
+                        break;
+                    }
+                }
+            } else
+                log.warn("could not evaluate group permissions but just user name");
+        }
+        return isAdministrator;
+    }
+}

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/InstallContextImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/InstallContextImpl.java?rev=1512568&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/InstallContextImpl.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/InstallContextImpl.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.packaging.impl;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+import org.apache.jackrabbit.vault.fs.io.Importer;
+import org.apache.jackrabbit.vault.packaging.InstallContext;
+import org.apache.jackrabbit.vault.packaging.VaultPackage;
+
+/**
+ * <code>InstallContextImpl</code>...
+ */
+public class InstallContextImpl implements InstallContext {
+
+    private final Session session;
+
+    private final Node importRoot;
+
+    private final VaultPackage pack;
+
+    private Phase phase = Phase.PREPARE;
+
+    private final Importer importer;
+
+    private final InstallHookProcessor hooks;
+
+    public InstallContextImpl(Node importRoot, VaultPackage pack,
+                              Importer importer, InstallHookProcessor hooks)
+            throws RepositoryException {
+        this.session = importRoot.getSession();
+        this.importRoot = importRoot;
+        this.pack = pack;
+        this.importer = importer;
+        this.hooks = hooks;
+    }
+
+    public Session getSession() {
+        return session;
+    }
+
+    public VaultPackage getPackage() {
+        return pack;
+    }
+
+    public ImportOptions getOptions() {
+        return importer.getOptions();
+    }
+
+    public Phase getPhase() {
+        return phase;
+    }
+
+    protected void setPhase(Phase phase) {
+        this.phase = phase;
+    }
+
+    protected Importer getImporter() {
+        return importer;
+    }
+
+    protected InstallHookProcessor getHooks() {
+        return hooks;
+    }
+
+    protected Node getImportRoot() {
+        return importRoot;
+    }
+}
\ No newline at end of file