You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2017/03/08 16:11:54 UTC

svn commit: r1785998 - /sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/

Author: sseifert
Date: Wed Mar  8 16:11:54 2017
New Revision: 1785998

URL: http://svn.apache.org/viewvc?rev=1785998&view=rev
Log:
SLING-6622 maven-sling-plugin: Add "fsmount" and "fsunmount" goals
move fsresoure logic do separate class FsMountHelper
remove obsolete method checkWebConsoleVersion

Added:
    sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountHelper.java   (with props)
    sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java   (with props)
    sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java   (with props)
Modified:
    sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java
    sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundlePostMojo.java
    sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/BundleUninstallMojo.java

Modified: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java?rev=1785998&r1=1785997&r2=1785998&view=diff
==============================================================================
--- sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java (original)
+++ sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java Wed Mar  8 16:11:54 2017
@@ -21,25 +21,11 @@ package org.apache.sling.maven.bundlesup
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-
-import javax.json.JsonArray;
-import javax.json.JsonException;
-import javax.json.JsonObject;
 
-import org.apache.commons.httpclient.Credentials;
-import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.UsernamePasswordCredentials;
-import org.apache.commons.httpclient.auth.AuthScope;
 import org.apache.commons.httpclient.methods.FileRequestEntity;
-import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.methods.HeadMethod;
 import org.apache.commons.httpclient.methods.PostMethod;
 import org.apache.commons.httpclient.methods.PutMethod;
@@ -48,40 +34,14 @@ import org.apache.commons.httpclient.met
 import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
 import org.apache.commons.httpclient.methods.multipart.Part;
 import org.apache.commons.httpclient.methods.multipart.StringPart;
-import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
-import org.apache.sling.commons.osgi.ManifestHeader;
-import org.apache.sling.commons.osgi.ManifestHeader.Entry;
 
 abstract class AbstractBundleInstallMojo extends AbstractBundlePostMojo {
 
-    /** Header containing the sling initial content information. */
-    private static final String HEADER_INITIAL_CONTENT = "Sling-Initial-Content";
-    /** The fs resource provider factory. */
-    private static final String FS_FACTORY = "org.apache.sling.fsprovider.internal.FsResourceProvider";
     /** Mime type for json response. */
-    protected static final String JSON_MIME_TYPE = "application/json";
-    /** Http header for content type. */
-    private static final String HEADER_CONTENT_TYPE = "Content-Type";
-
-    /**
-     * The URL of the running Sling instance. The default is only useful for <strong>WebConsole</strong> deployment (see {@link #deploymentMethod}).
-     */
-    @Parameter(property="sling.url", defaultValue="http://localhost:8080/system/console", required = true)
-    protected String slingUrl;
-
-    /**
-     * An optional url suffix which will be appended to the <code>sling.url</code>
-     * for use as the real target url. This allows to configure different target URLs
-     * in each POM, while using the same common <code>sling.url</code> in a parent
-     * POM (eg. <code>sling.url=http://localhost:8080</code> and
-     * <code>sling.urlSuffix=/project/specific/path</code>). This is typically used
-     * in conjunction with WebDAV or SlingPostServlet deployment methods.
-     */
-    @Parameter(property="sling.urlSuffix")
-    protected String slingUrlSuffix;
+    public static final String JSON_MIME_TYPE = "application/json";
 
     /**
      * If a PUT via WebDAV should be used instead of the standard POST to the
@@ -134,18 +94,6 @@ abstract class AbstractBundleInstallMojo
     protected String mimeType;
 
     /**
-     * The user name to authenticate at the running Sling instance.
-     */
-    @Parameter(property="sling.user", defaultValue = "admin", required = true)
-    private String user;
-
-    /**
-     * The password to authenticate at the running Sling instance.
-     */
-    @Parameter(property="sling.password", defaultValue = "admin", required = true)
-    private String password;
-
-    /**
      * The startlevel for the uploaded bundle. Only applies when POSTing to
      * Felix Web Console.
      */
@@ -185,18 +133,6 @@ abstract class AbstractBundleInstallMojo
     protected abstract String getBundleFileName() throws MojoExecutionException;
 
     /**
-     * Returns the combination of <code>sling.url</code> and
-     * <code>sling.urlSuffix</code>.
-     */
-    protected String getTargetURL() {
-        String targetURL = slingUrl;
-        if (slingUrlSuffix != null) {
-            targetURL += slingUrlSuffix;
-        }
-        return targetURL;
-    }
-
-    /**
      * Returns the URL with the filename appended to it.
      * @param targetURL the original requested targetURL to append fileName to
      * @param fileName the name of the file to append to the targetURL.
@@ -252,6 +188,11 @@ abstract class AbstractBundleInstallMojo
             configure(targetURL, bundleFile);
         }
     }
+    
+    protected void configure(final String targetURL, final File file) throws MojoExecutionException {
+        FsMountHelper fsMountHelper = new FsMountHelper(getLog(), getHttpClient(), project);
+        fsMountHelper.configureInstall(targetURL, file);
+    }
 
     /**
      * Retrieve the bundle deployment method matching the configuration.
@@ -271,35 +212,6 @@ abstract class AbstractBundleInstallMojo
     }
 
     /**
-     * Helper method to throw a meaningful exception for an outdated felix
-     * web console.
-     * @throws MojoExecutionException
-     */
-    protected void throwWebConsoleTooOldException()
-    throws MojoExecutionException {
-        throw new MojoExecutionException("The Apache Felix Web Console is too old to mount " +
-                "the initial content through file system provider configs. " +
-                "Either upgrade the web console or disable this feature.");
-    }
-
-    /**
-     * Get the http client
-     */
-    protected HttpClient getHttpClient() {
-        final HttpClient client = new HttpClient();
-        client.getHttpConnectionManager().getParams().setConnectionTimeout(
-            5000);
-
-        // authentication stuff
-        client.getParams().setAuthenticationPreemptive(true);
-        Credentials defaultcreds = new UsernamePasswordCredentials(user,
-            password);
-        client.getState().setCredentials(AuthScope.ANY, defaultcreds);
-
-        return client;
-    }
-
-    /**
      * Install the bundle via POST to the Felix Web Console
      * @param targetURL the URL to the Felix Web Console Bundles listing
      * @param file the file to POST
@@ -525,317 +437,4 @@ abstract class AbstractBundleInstallMojo
         }
     }
 
-    /**
-     * Add configurations to a running OSGi instance for initial content.
-     * @param targetURL The web console base url
-     * @param file The artifact (bundle)
-     * @throws MojoExecutionException
-     */
-    protected void configure(String targetURL, File file)
-    throws MojoExecutionException {
-        // first, let's get the manifest and see if initial content is configured
-        ManifestHeader header = null;
-        try {
-            final Manifest mf = this.getManifest(file);
-            final String value = mf.getMainAttributes().getValue(HEADER_INITIAL_CONTENT);
-            if ( value == null ) {
-                getLog().debug("Bundle has no initial content - no file system provider config created.");
-                return;
-            }
-            header = ManifestHeader.parse(value);
-            if ( header == null || header.getEntries().length == 0 ) {
-                getLog().warn("Unable to parse header or header is empty: " + value);
-                return;
-            }
-        } catch (IOException ioe) {
-            throw new MojoExecutionException("Unable to read manifest from file " + file, ioe);
-        }
-        // setup http client
-        final HttpClient client = getHttpClient();
-
-        getLog().info("Trying to configure file system provider...");
-        // quick check if resources are configured
-        final List resources = project.getResources();
-        if ( resources == null || resources.size() == 0 ) {
-            throw new MojoExecutionException("No resources configured for this project.");
-        }
-        // now get current configurations
-        final Map<String,String[]> oldConfigs = this.getCurrentFileProviderConfigs(targetURL, client);
-
-        final Entry[] entries = header.getEntries();
-        for(final Entry entry : entries) {
-            String path = entry.getValue();
-            if ( path != null && !path.endsWith("/") ) {
-                path += "/";
-            }
-            // check if we should ignore this
-            final String ignoreValue = entry.getDirectiveValue("maven:mount");
-            if ( ignoreValue != null && ignoreValue.equalsIgnoreCase("false") ) {
-                getLog().debug("Ignoring " + path);
-                continue;
-            }
-            String installPath = entry.getDirectiveValue("path");
-            if ( installPath == null ) {
-                installPath = "/";
-            }
-            // search the path in the resources (usually this should be the first resource
-            // entry but this might be reconfigured
-            File dir = null;
-            final Iterator i = resources.iterator();
-            while ( dir == null && i.hasNext() ) {
-                final Resource rsrc = (Resource)i.next();
-                String child = path;
-                // if resource mapping defines a target path: remove target path from checked resource path
-                String targetPath = rsrc.getTargetPath();
-                if ( targetPath != null && !targetPath.endsWith("/") ) {
-                    targetPath = targetPath + "/";
-                }
-                if ( targetPath != null && path.startsWith(targetPath) ) {
-                    child = child.substring(targetPath.length());
-                }
-                dir = new File(rsrc.getDirectory(), child);
-                if ( !dir.exists() ) {
-                    dir = null;
-                }
-            }
-            if ( dir == null ) {
-                throw new MojoExecutionException("No resource entry found containing " + path);
-            }
-            // check for root mapping - which we don't support atm
-            if ( "/".equals(installPath) ) {
-                throw new MojoExecutionException("Mapping to root path not supported by fs provider at the moment. Please adapt your initial content configuration.");
-            }
-            getLog().info("Mapping " + dir + " to " + installPath);
-
-            // check if this is already configured
-            boolean found = false;
-            final Iterator<Map.Entry<String,String[]>> entryIterator = oldConfigs.entrySet().iterator();
-            while ( !found && entryIterator.hasNext() ) {
-                final Map.Entry<String,String[]> current = entryIterator.next();
-                final String[] value = current.getValue();
-                getLog().debug("Comparing " + dir.getAbsolutePath() + " with " + value[0] + " (" + value[1] + ")");
-                if ( dir.getAbsolutePath().equals(value[0]) ) {
-                    if ( installPath.equals(value[1]) ) {
-                        getLog().debug("Using existing configuration for " + dir + " and " + installPath);
-                        found = true;
-                    } else {
-                        // remove old config
-                        getLog().debug("Removing old configuration for " + value[0] + " and " + value[1]);
-                        removeConfiguration(client, targetURL, current.getKey().toString());
-                    }
-                    entryIterator.remove();
-                }
-            }
-            if ( !found ) {
-                getLog().debug("Adding new configuration for " + dir + " and " + installPath);
-                addConfiguration(client, targetURL, dir.getAbsolutePath(), installPath);
-            }
-        }
-        // finally remove old configs
-        final Iterator<Map.Entry<String,String[]>> entryIterator = oldConfigs.entrySet().iterator();
-        while ( entryIterator.hasNext() ) {
-            final Map.Entry<String,String[]> current = entryIterator.next();
-            final String[] value = current.getValue();
-            getLog().debug("Removing old configuration for " + value[0] + " and " + value[1]);
-            // remove old config
-            removeConfiguration(client, targetURL, current.getKey().toString());
-        }
-    }
-
-    protected void removeConfiguration(final HttpClient client, final String targetURL, String pid)
-    throws MojoExecutionException {
-        final String postUrl = targetURL  + "/configMgr/" + pid;
-        final PostMethod post = new PostMethod(postUrl);
-        post.addParameter("apply", "true");
-        post.addParameter("delete", "true");
-        try {
-            final int status = client.executeMethod(post);
-            // we get a moved temporarily back from the configMgr plugin
-            if (status == HttpStatus.SC_MOVED_TEMPORARILY || status == HttpStatus.SC_OK) {
-                getLog().debug("Configuration removed.");
-            } else {
-                getLog().error(
-                    "Removing configuration failed, cause: "
-                        + HttpStatus.getStatusText(status));
-            }
-        } catch (HttpException ex) {
-            throw new MojoExecutionException("Removing configuration at " + postUrl
-                    + " failed, cause: " + ex.getMessage(), ex);
-        } catch (IOException ex) {
-            throw new MojoExecutionException("Removing configuration at " + postUrl
-                    + " failed, cause: " + ex.getMessage(), ex);
-        } finally {
-            post.releaseConnection();
-        }
-    }
-
-    /**
-     * Add a new configuration for the file system provider
-     * @throws MojoExecutionException
-     */
-    protected void addConfiguration(final HttpClient client, final String targetURL, String dir, String path)
-    throws MojoExecutionException {
-        final String postUrl = targetURL  + "/configMgr/" + FS_FACTORY;
-        final PostMethod post = new PostMethod(postUrl);
-        post.addParameter("apply", "true");
-        post.addParameter("factoryPid", FS_FACTORY);
-        post.addParameter("pid", "[Temporary PID replaced by real PID upon save]");
-        post.addParameter("provider.file", dir);
-        // save property value to both "provider.roots" and "provider.root" because the name has changed since fsresource 1.1.6
-        post.addParameter("provider.root", path);
-        post.addParameter("provider.roots", path);
-        post.addParameter("propertylist", "provider.root,provider.roots,provider.file");
-        try {
-            final int status = client.executeMethod(post);
-            // we get a moved temporarily back from the configMgr plugin
-            if (status == HttpStatus.SC_MOVED_TEMPORARILY || status == HttpStatus.SC_OK) {
-                getLog().info("Configuration created.");
-            } else {
-                getLog().error(
-                    "Configuration failed, cause: "
-                        + HttpStatus.getStatusText(status));
-            }
-        } catch (HttpException ex) {
-            throw new MojoExecutionException("Configuration on " + postUrl
-                    + " failed, cause: " + ex.getMessage(), ex);
-        } catch (IOException ex) {
-            throw new MojoExecutionException("Configuration on " + postUrl
-                    + " failed, cause: " + ex.getMessage(), ex);
-        } finally {
-            post.releaseConnection();
-        }
-    }
-
-    /**
-     * Return all file provider configs for this project
-     * @param targetURL The targetURL of the webconsole
-     * @param client The http client
-     * @return A map (may be empty) with the pids as keys and a string array
-     *         containing the path and the root
-     * @throws MojoExecutionException
-     */
-    protected Map<String,String[]> getCurrentFileProviderConfigs(final String targetURL, final HttpClient client)
-    throws MojoExecutionException {
-        getLog().debug("Getting current file provider configurations.");
-        final Map<String,String[]> result = new HashMap<>();
-        final String getUrl = targetURL  + "/configMgr/(service.factoryPid=" + FS_FACTORY + ").json";
-        final GetMethod get = new GetMethod(getUrl);
-
-        try {
-            final int status = client.executeMethod(get);
-            if ( status == 200 ) {
-                String contentType = get.getResponseHeader(HEADER_CONTENT_TYPE).getValue();
-                int pos = contentType.indexOf(';');
-                if ( pos != -1 ) {
-                    contentType = contentType.substring(0, pos);
-                }
-                if ( !JSON_MIME_TYPE.equals(contentType) ) {
-                    getLog().debug("Response type from web console is not JSON, but " + contentType);
-                    throwWebConsoleTooOldException();
-                }
-                final String jsonText = get.getResponseBodyAsString();
-                try {
-                    JsonArray array = JsonSupport.parseArray(jsonText);
-                    for(int i=0; i<array.size(); i++) {
-                        final JsonObject obj = array.getJsonObject(i);
-                        final String pid = obj.getString("pid");
-                        final JsonObject properties = obj.getJsonObject("properties");
-                        final String path = properties.getJsonObject("provider.file").getString("value", null);
-                        final String roots;
-                        if (properties.containsKey("provider.roots")) {
-                            roots = properties.getJsonObject("provider.roots").getString("value", null);
-                        }
-                        else {
-                            roots = properties.getJsonObject("provider.root").getString("value", null);
-                        }
-                        if ( path != null && path.startsWith(this.project.getBasedir().getAbsolutePath()) && roots != null ) {
-                            getLog().debug("Found configuration with pid: " + pid + ", path: " + path + ", roots: " + roots);
-                            result.put(pid, new String[] {path, roots});
-                        }
-                    }
-                } catch (JsonException ex) {
-                    throw new MojoExecutionException("Reading configuration from " + getUrl
-                            + " failed, cause: " + ex.getMessage(), ex);
-                }
-            }
-        } catch (HttpException ex) {
-            throw new MojoExecutionException("Reading configuration from " + getUrl
-                    + " failed, cause: " + ex.getMessage(), ex);
-        } catch (IOException ex) {
-            throw new MojoExecutionException("Reading configuration from " + getUrl
-                    + " failed, cause: " + ex.getMessage(), ex);
-        } finally {
-            get.releaseConnection();
-        }
-        return result;
-    }
-
-    /**
-     * Get the manifest from the File.
-     * @param bundleFile The bundle jar
-     * @return The manifest.
-     * @throws IOException
-     */
-    protected Manifest getManifest(final File bundleFile) throws IOException {
-        JarFile file = null;
-        try {
-            file = new JarFile(bundleFile);
-            return file.getManifest();
-        } finally {
-            if (file != null) {
-                try {
-                    file.close();
-                } catch (IOException ignore) {
-                }
-            }
-        }
-    }
-
-    /**
-     * Try to get the version of the web console
-     * @return The version or <code>null</code> if version is not detectable.
-     */
-    protected String checkWebConsoleVersion(final String targetUrl) {
-        getLog().debug("Checking web console version....");
-        final String bundleUrl = targetUrl + "/bundles/org.apache.felix.webconsole.json";
-        final HttpClient client = getHttpClient();
-        final GetMethod gm = new GetMethod(bundleUrl);
-        // if something goes wrong, we assume an older version!!
-        try {
-            final int status = client.executeMethod(gm);
-            if ( status == 200 ) {
-                if ( gm.getResponseContentLength() == 0 ) {
-                    getLog().debug("Response has zero length. Assuming older version of web console.");
-                    return null;
-                }
-                final String jsonText = gm.getResponseBodyAsString();
-                try {
-                    final JsonObject obj = JsonSupport.parseObject(jsonText);
-                    final JsonArray props = obj.getJsonArray("props");
-                    for(int i=0; i<props.size(); i++) {
-                        final JsonObject property = props.getJsonObject(i);
-                        if ( "Version".equals(property.get("key")) ) {
-                            final String version = property.getString("value");
-                            getLog().debug("Found web console version " + version);
-                            return version;
-                        }
-                    }
-                    getLog().debug("Version property not found in response. Assuming older version.");
-                    return null;
-                } catch (JsonException ex) {
-                    getLog().debug("Converting response to JSON failed. Assuming older version: " + ex.getMessage());
-                    return null;
-                }
-
-            }
-            getLog().debug("Status code from web console: " + status);
-        } catch (HttpException e) {
-            getLog().debug("HttpException: " + e.getMessage());
-        } catch (IOException e) {
-            getLog().debug("IOException: " + e.getMessage());
-        }
-
-        getLog().debug("Unknown version.");
-        return null;
-    }
-}
\ No newline at end of file
+}

Modified: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundlePostMojo.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundlePostMojo.java?rev=1785998&r1=1785997&r2=1785998&view=diff
==============================================================================
--- sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundlePostMojo.java (original)
+++ sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundlePostMojo.java Wed Mar  8 16:11:54 2017
@@ -23,12 +23,45 @@ import java.io.IOException;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
 
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugins.annotations.Parameter;
 
 abstract class AbstractBundlePostMojo extends AbstractMojo {
 
     /**
+     * The URL of the running Sling instance. The default is only useful for <strong>WebConsole</strong> deployment (see {@link #deploymentMethod}).
+     */
+    @Parameter(property="sling.url", defaultValue="http://localhost:8080/system/console", required = true)
+    protected String slingUrl;
+
+    /**
+     * An optional url suffix which will be appended to the <code>sling.url</code>
+     * for use as the real target url. This allows to configure different target URLs
+     * in each POM, while using the same common <code>sling.url</code> in a parent
+     * POM (eg. <code>sling.url=http://localhost:8080</code> and
+     * <code>sling.urlSuffix=/project/specific/path</code>). This is typically used
+     * in conjunction with WebDAV or SlingPostServlet deployment methods.
+     */
+    @Parameter(property="sling.urlSuffix")
+    protected String slingUrlSuffix;
+    
+    /**
+     * The user name to authenticate at the running Sling instance.
+     */
+    @Parameter(property="sling.user", defaultValue = "admin", required = true)
+    private String user;
+
+    /**
+     * The password to authenticate at the running Sling instance.
+     */
+    @Parameter(property="sling.password", defaultValue = "admin", required = true)
+    private String password;
+    
+    /**
      * Determines whether or not to fail the build if
      * the HTTP POST or PUT returns an non-OK response code.
      */
@@ -98,4 +131,33 @@ abstract class AbstractBundlePostMojo ex
         return null;
     }
 
+    /**
+     * Returns the combination of <code>sling.url</code> and
+     * <code>sling.urlSuffix</code>.
+     */
+    protected String getTargetURL() {
+        String targetURL = slingUrl;
+        if (slingUrlSuffix != null) {
+            targetURL += slingUrlSuffix;
+        }
+        return targetURL;
+    }
+
+    /**
+     * Get the http client
+     */
+    protected HttpClient getHttpClient() {
+        final HttpClient client = new HttpClient();
+        client.getHttpConnectionManager().getParams().setConnectionTimeout(
+            5000);
+
+        // authentication stuff
+        client.getParams().setAuthenticationPreemptive(true);
+        Credentials defaultcreds = new UsernamePasswordCredentials(user,
+            password);
+        client.getState().setCredentials(AuthScope.ANY, defaultcreds);
+
+        return client;
+    }
+
 }

Modified: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/BundleUninstallMojo.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/BundleUninstallMojo.java?rev=1785998&r1=1785997&r2=1785998&view=diff
==============================================================================
--- sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/BundleUninstallMojo.java (original)
+++ sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/BundleUninstallMojo.java Wed Mar  8 16:11:54 2017
@@ -19,10 +19,7 @@
 package org.apache.sling.maven.bundlesupport;
 
 import java.io.File;
-import java.util.Iterator;
-import java.util.Map;
 
-import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpStatus;
 import org.apache.commons.httpclient.methods.DeleteMethod;
 import org.apache.commons.httpclient.methods.PostMethod;
@@ -165,30 +162,10 @@ public class BundleUninstallMojo extends
         }
     }
 
-    /**
-     * Add configurations to a running OSGi instance for initial content.
-     * @param targetURL The web console base url
-     * @param file The artifact (bundle)
-     * @throws MojoExecutionException
-     */
     @Override
-    protected void configure(String targetURL, File file)
-    throws MojoExecutionException {
-        getLog().info("Removing file system provider configurations...");
-
-        // now get current configurations
-        final HttpClient client = this.getHttpClient();
-        final Map oldConfigs = this.getCurrentFileProviderConfigs(targetURL, client);
-
-
-        final Iterator entryIterator = oldConfigs.entrySet().iterator();
-        while ( entryIterator.hasNext() ) {
-            final Map.Entry current = (Map.Entry) entryIterator.next();
-            final String[] value = (String[])current.getValue();
-            getLog().debug("Removing old configuration for " + value[0] + " and " + value[1]);
-            // remove old config
-            removeConfiguration(client, targetURL, current.getKey().toString());
-        }
+    protected void configure(final String targetURL, final File file) throws MojoExecutionException {
+        FsMountHelper fsMountHelper = new FsMountHelper(getLog(), getHttpClient(), project);
+        fsMountHelper.configureUninstall(targetURL, file);
     }
-
+    
 }
\ No newline at end of file

Added: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountHelper.java?rev=1785998&view=auto
==============================================================================
--- sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountHelper.java (added)
+++ sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountHelper.java Wed Mar  8 16:11:54 2017
@@ -0,0 +1,393 @@
+/*
+ * 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.sling.maven.bundlesupport;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import javax.json.JsonArray;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.CharEncoding;
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.apache.sling.commons.osgi.ManifestHeader;
+import org.apache.sling.commons.osgi.ManifestHeader.Entry;
+
+/**
+ * Manages OSGi configurations for File System Resource Provider.
+ */
+class FsMountHelper {
+    
+    /** Header containing the sling initial content information. */
+    private static final String HEADER_INITIAL_CONTENT = "Sling-Initial-Content";
+    /** The fs resource provider factory. */
+    private static final String FS_FACTORY = "org.apache.sling.fsprovider.internal.FsResourceProvider";
+    /** Http header for content type. */
+    private static final String HEADER_CONTENT_TYPE = "Content-Type";
+    
+    private final Log log;
+    private final HttpClient httpClient;
+    private final MavenProject project;
+
+    public FsMountHelper(Log log, HttpClient httpClient, MavenProject project) {
+        this.log = log;
+        this.httpClient = httpClient;
+        this.project = project;
+    }
+
+    /**
+     * Add configurations to a running OSGi instance for initial content.
+     * @param targetURL The web console base url
+     * @param file The artifact (bundle)
+     * @throws MojoExecutionException
+     */
+    public void configureInstall(final String targetURL, final File file) throws MojoExecutionException {
+        // first, let's get the manifest and see if initial content is configured
+        ManifestHeader header = null;
+        try {
+            final Manifest mf = getManifest(file);
+            final String value = mf.getMainAttributes().getValue(HEADER_INITIAL_CONTENT);
+            if ( value == null ) {
+                log.debug("Bundle has no initial content - no file system provider config created.");
+                return;
+            }
+            header = ManifestHeader.parse(value);
+            if ( header == null || header.getEntries().length == 0 ) {
+                log.warn("Unable to parse header or header is empty: " + value);
+                return;
+            }
+        } catch (IOException ioe) {
+            throw new MojoExecutionException("Unable to read manifest from file " + file, ioe);
+        }
+
+        log.info("Trying to configure file system provider...");
+        // quick check if resources are configured
+        final List resources = project.getResources();
+        if ( resources == null || resources.size() == 0 ) {
+            throw new MojoExecutionException("No resources configured for this project.");
+        }
+        // now get current configurations
+        final Map<String,String[]> oldConfigs = getCurrentFileProviderConfigs(targetURL);
+
+        final Entry[] entries = header.getEntries();
+        for (final Entry entry : entries) {
+            String path = entry.getValue();
+            if ( path != null && !path.endsWith("/") ) {
+                path += "/";
+            }
+            // check if we should ignore this
+            final String ignoreValue = entry.getDirectiveValue("maven:mount");
+            if ( ignoreValue != null && ignoreValue.equalsIgnoreCase("false") ) {
+                log.debug("Ignoring " + path);
+                continue;
+            }
+            String installPath = entry.getDirectiveValue("path");
+            if ( installPath == null ) {
+                installPath = "/";
+            }
+            // search the path in the resources (usually this should be the first resource
+            // entry but this might be reconfigured
+            File dir = null;
+            final Iterator i = resources.iterator();
+            while ( dir == null && i.hasNext() ) {
+                final Resource rsrc = (Resource)i.next();
+                String child = path;
+                // if resource mapping defines a target path: remove target path from checked resource path
+                String targetPath = rsrc.getTargetPath();
+                if ( targetPath != null && !targetPath.endsWith("/") ) {
+                    targetPath = targetPath + "/";
+                }
+                if ( targetPath != null && path.startsWith(targetPath) ) {
+                    child = child.substring(targetPath.length());
+                }
+                dir = new File(rsrc.getDirectory(), child);
+                if ( !dir.exists() ) {
+                    dir = null;
+                }
+            }
+            if ( dir == null ) {
+                throw new MojoExecutionException("No resource entry found containing " + path);
+            }
+            // check for root mapping - which we don't support atm
+            if ( "/".equals(installPath) ) {
+                throw new MojoExecutionException("Mapping to root path not supported by fs provider at the moment. Please adapt your initial content configuration.");
+            }
+            log.info("Mapping " + dir + " to " + installPath);
+
+            // check if this is already configured
+            boolean found = false;
+            final Iterator<Map.Entry<String,String[]>> entryIterator = oldConfigs.entrySet().iterator();
+            while ( !found && entryIterator.hasNext() ) {
+                final Map.Entry<String,String[]> current = entryIterator.next();
+                final String[] value = current.getValue();
+                log.debug("Comparing " + dir.getAbsolutePath() + " with " + value[0] + " (" + value[1] + ")");
+                if ( dir.getAbsolutePath().equals(value[0]) ) {
+                    if ( installPath.equals(value[1]) ) {
+                        log.debug("Using existing configuration for " + dir + " and " + installPath);
+                        found = true;
+                    }
+                    else {
+                        // remove old config
+                        log.debug("Removing old configuration for " + value[0] + " and " + value[1]);
+                        removeConfiguration(targetURL, current.getKey().toString());
+                    }
+                    entryIterator.remove();
+                }
+            }
+            if ( !found ) {
+                log.debug("Adding new configuration for " + dir + " and " + installPath);
+                addConfiguration(targetURL, dir.getAbsolutePath(), installPath);
+            }
+        }
+        // finally remove old configs
+        final Iterator<Map.Entry<String,String[]>> entryIterator = oldConfigs.entrySet().iterator();
+        while ( entryIterator.hasNext() ) {
+            final Map.Entry<String,String[]> current = entryIterator.next();
+            final String[] value = current.getValue();
+            log.debug("Removing old configuration for " + value[0] + " and " + value[1]);
+            // remove old config
+            removeConfiguration(targetURL, current.getKey().toString());
+        }
+    }
+
+    /**
+     * Add configurations to a running OSGi instance for initial content.
+     * @param targetURL The web console base url
+     * @param file The artifact (bundle)
+     * @throws MojoExecutionException
+     */
+    public void configureUninstall(final String targetURL, final File file) throws MojoExecutionException {
+        log.info("Removing file system provider configurations...");
+
+        // now get current configurations
+        final Map oldConfigs = getCurrentFileProviderConfigs(targetURL);
+
+        final Iterator entryIterator = oldConfigs.entrySet().iterator();
+        while ( entryIterator.hasNext() ) {
+            final Map.Entry current = (Map.Entry) entryIterator.next();
+            final String[] value = (String[])current.getValue();
+            log.debug("Removing old configuration for " + value[0] + " and " + value[1]);
+            // remove old config
+            removeConfiguration(targetURL, current.getKey().toString());
+        }
+    }
+    
+    public void removeConfiguration(final String targetURL, final String pid) throws MojoExecutionException {
+        final String postUrl = targetURL  + "/configMgr/" + pid;
+        final PostMethod post = new PostMethod(postUrl);
+        post.addParameter("apply", "true");
+        post.addParameter("delete", "true");
+        try {
+            final int status = httpClient.executeMethod(post);
+            // we get a moved temporarily back from the configMgr plugin
+            if (status == HttpStatus.SC_MOVED_TEMPORARILY || status == HttpStatus.SC_OK) {
+                log.debug("Configuration removed.");
+            }
+            else {
+                log.error("Removing configuration failed, cause: "+ HttpStatus.getStatusText(status));
+            }
+        }
+        catch (HttpException ex) {
+            throw new MojoExecutionException("Removing configuration at " + postUrl
+                    + " failed, cause: " + ex.getMessage(), ex);
+        }
+        catch (IOException ex) {
+            throw new MojoExecutionException("Removing configuration at " + postUrl
+                    + " failed, cause: " + ex.getMessage(), ex);
+        }
+        finally {
+            post.releaseConnection();
+        }
+    }
+
+    /**
+     * Add a new configuration for the file system provider
+     * @throws MojoExecutionException
+     */
+    private void addConfiguration(final String targetURL, String dir, String path) throws MojoExecutionException {
+        final String postUrl = targetURL  + "/configMgr/" + FS_FACTORY;
+        final PostMethod post = new PostMethod(postUrl);
+        post.addParameter("apply", "true");
+        post.addParameter("factoryPid", FS_FACTORY);
+        post.addParameter("pid", "[Temporary PID replaced by real PID upon save]");
+        post.addParameter("provider.file", dir);
+        // save property value to both "provider.roots" and "provider.root" because the name has changed between fsresource 1.x and 2.x
+        post.addParameter("provider.root", path);
+        post.addParameter("provider.roots", path);
+        post.addParameter("propertylist", "provider.root,provider.roots,provider.file");
+        try {
+            final int status = httpClient.executeMethod(post);
+            // we get a moved temporarily back from the configMgr plugin
+            if (status == HttpStatus.SC_MOVED_TEMPORARILY || status == HttpStatus.SC_OK) {
+                log.info("Configuration created.");
+            }
+            else {
+                log.error(
+                    "Configuration failed, cause: "
+                        + HttpStatus.getStatusText(status));
+            }
+        }
+        catch (HttpException ex) {
+            throw new MojoExecutionException("Configuration on " + postUrl
+                    + " failed, cause: " + ex.getMessage(), ex);
+        }
+        catch (IOException ex) {
+            throw new MojoExecutionException("Configuration on " + postUrl
+                    + " failed, cause: " + ex.getMessage(), ex);
+        }
+        finally {
+            post.releaseConnection();
+        }
+    }
+
+    /**
+     * Return all file provider configs for this project
+     * @param targetURL The targetURL of the webconsole
+     * @return A map (may be empty) with the pids as keys and a string array
+     *         containing the path and the root
+     * @throws MojoExecutionException
+     */
+    public Map<String,String[]> getCurrentFileProviderConfigs(final String targetURL) throws MojoExecutionException {
+        log.debug("Getting current file provider configurations.");
+        final Map<String,String[]> result = new HashMap<>();
+        final String getUrl = targetURL  + "/configMgr/(service.factoryPid=" + FS_FACTORY + ").json";
+        final GetMethod get = new GetMethod(getUrl);
+
+        try {
+            final int status = httpClient.executeMethod(get);
+            if ( status == 200 ) {
+                String contentType = get.getResponseHeader(HEADER_CONTENT_TYPE).getValue();
+                int pos = contentType.indexOf(';');
+                if ( pos != -1 ) {
+                    contentType = contentType.substring(0, pos);
+                }
+                if ( !AbstractBundleInstallMojo.JSON_MIME_TYPE.equals(contentType) ) {
+                    log.debug("Response type from web console is not JSON, but " + contentType);
+                    throwWebConsoleTooOldException();
+                }
+                final String jsonText;
+                try (InputStream jsonResponse = get.getResponseBodyAsStream()) {
+                    jsonText = IOUtils.toString(jsonResponse, CharEncoding.UTF_8);
+                }
+                try {
+                    JsonArray array = JsonSupport.parseArray(jsonText);
+                    for(int i=0; i<array.size(); i++) {
+                        final JsonObject obj = array.getJsonObject(i);
+                        final String pid = obj.getString("pid");
+                        final JsonObject properties = obj.getJsonObject("properties");
+                        final String path = getConfigPropertyValue(properties, "provider.file");
+                        String roots = getConfigPropertyValue(properties, "provider.roots");
+                        if (roots == null) {
+                            roots = getConfigPropertyValue(properties, "provider.root");
+                        }
+                        if ( path != null && path.startsWith(this.project.getBasedir().getAbsolutePath()) && roots != null ) {
+                            log.debug("Found configuration with pid: " + pid + ", path: " + path + ", roots: " + roots);
+                            result.put(pid, new String[] {path, roots});
+                        }
+                    }
+                } catch (JsonException ex) {
+                    throw new MojoExecutionException("Reading configuration from " + getUrl
+                            + " failed, cause: " + ex.getMessage(), ex);
+                }
+            }
+        }
+        catch (HttpException ex) {
+            throw new MojoExecutionException("Reading configuration from " + getUrl
+                    + " failed, cause: " + ex.getMessage(), ex);
+        }
+        catch (IOException ex) {
+            throw new MojoExecutionException("Reading configuration from " + getUrl
+                    + " failed, cause: " + ex.getMessage(), ex);
+        }
+        finally {
+            get.releaseConnection();
+        }
+        return result;
+    }
+    
+    private String getConfigPropertyValue(JsonObject obj, String subKey) {
+        if (obj.containsKey(subKey)) {
+            JsonObject subObj = obj.getJsonObject(subKey);
+            if (subObj.containsKey("value")) {
+                return subObj.getString("value");
+            }
+            else if (subObj.containsKey("values")) {
+                JsonArray array = subObj.getJsonArray("values");
+                if (array.size() > 0) {
+                    // use only first property value from array
+                    return array.getString(0);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get the manifest from the File.
+     * @param bundleFile The bundle jar
+     * @return The manifest.
+     * @throws IOException
+     */
+    private Manifest getManifest(final File bundleFile) throws IOException {
+        JarFile file = null;
+        try {
+            file = new JarFile(bundleFile);
+            return file.getManifest();
+        }
+        finally {
+            if (file != null) {
+                try {
+                    file.close();
+                }
+                catch (IOException ex) {
+                    // ignore
+                }
+            }
+        }
+    }
+
+    /**
+     * Helper method to throw a meaningful exception for an outdated felix
+     * web console.
+     * @throws MojoExecutionException
+     */
+    private void throwWebConsoleTooOldException() throws MojoExecutionException {
+        throw new MojoExecutionException("The Apache Felix Web Console is too old to mount " +
+                "the initial content through file system provider configs. " +
+                "Either upgrade the web console or disable this feature.");
+    }
+
+}

Propchange: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountHelper.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Wed Mar  8 16:11:54 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java?rev=1785998&view=auto
==============================================================================
--- sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java (added)
+++ sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java Wed Mar  8 16:11:54 2017
@@ -0,0 +1,57 @@
+/*
+ * 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.sling.maven.bundlesupport;
+
+import java.io.File;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+
+/**
+ * Creates OSGi configurations for File System Resource provider.
+ */
+@Mojo(name = "fsmount", requiresProject = true)
+public class FsMountMojo extends AbstractBundlePostMojo {
+
+    /**
+     * The name of the generated JAR file.
+     */
+    @Parameter(property = "sling.file", defaultValue = "${project.build.directory}/${project.build.finalName}.jar", required = true)
+    private String bundleFileName;
+
+    /**
+     * The Maven project.
+     */
+    @Parameter(defaultValue = "${project}", required = true, readonly = true)
+    protected MavenProject project;
+    
+    @Override
+    public void execute() throws MojoExecutionException {
+        File file = new File(bundleFileName);
+        if(!file.exists()) {
+            getLog().info(file + " does not exist, skipping.");
+            return;
+        }
+        
+        FsMountHelper fsMountHelper = new FsMountHelper(getLog(), getHttpClient(), project);
+        fsMountHelper.configureInstall(getTargetURL(), file);
+    }
+
+}
\ No newline at end of file

Propchange: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Wed Mar  8 16:11:54 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java?rev=1785998&view=auto
==============================================================================
--- sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java (added)
+++ sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java Wed Mar  8 16:11:54 2017
@@ -0,0 +1,57 @@
+/*
+ * 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.sling.maven.bundlesupport;
+
+import java.io.File;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+
+/**
+ * Removes OSGi configurations for File System Resource provider.
+ */
+@Mojo(name = "fsunmount", requiresProject = true)
+public class FsUnMountMojo extends AbstractBundlePostMojo {
+
+    /**
+     * The name of the generated JAR file.
+     */
+    @Parameter(property = "sling.file", defaultValue = "${project.build.directory}/${project.build.finalName}.jar", required = true)
+    private String bundleFileName;
+
+    /**
+     * The Maven project.
+     */
+    @Parameter(defaultValue = "${project}", required = true, readonly = true)
+    protected MavenProject project;
+    
+    @Override
+    public void execute() throws MojoExecutionException {
+        File file = new File(bundleFileName);
+        if(!file.exists()) {
+            getLog().info(file + " does not exist, skipping.");
+            return;
+        }
+        
+        FsMountHelper fsMountHelper = new FsMountHelper(getLog(), getHttpClient(), project);
+        fsMountHelper.configureUninstall(getTargetURL(), file);
+    }
+
+}
\ No newline at end of file

Propchange: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Wed Mar  8 16:11:54 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain