You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2022/08/13 13:34:28 UTC

[sling-maven-plugin] 01/01: SLING-11522 fix mount goals

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch bugfix/fix-mount-goals
in repository https://gitbox.apache.org/repos/asf/sling-maven-plugin.git

commit 6d0394556b11d89b5edc99a6d3edae3df21ee858
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Sat Aug 13 15:34:22 2022 +0200

    SLING-11522 fix mount goals
    
    add ITs for mount and validate goals
    improve logging
---
 src/it/fs-mount-test/invoker.properties            |  17 +++
 src/it/fs-mount-test/pom.xml                       | 115 +++++++++++++++++++++
 .../src/main/webapp/app-root/example.txt           |  19 ++++
 src/it/fs-mount-test/verify.groovy                 |  22 ++++
 src/it/validate-test/invoker.properties            |  18 ++++
 src/it/validate-test/pom.xml                       |  73 +++++++++++++
 .../validate-test/src/main/resources/invalid.json  |   3 +
 src/it/validate-test/verify.groovy                 |  22 ++++
 .../bundlesupport/AbstractBundleInstallMojo.java   |   4 +-
 .../bundlesupport/AbstractBundleRequestMojo.java   |  26 ++++-
 .../maven/bundlesupport/BundlePrerequisite.java    |   7 +-
 .../maven/bundlesupport/BundleUninstallMojo.java   |   2 +-
 .../sling/maven/bundlesupport/FsMountMojo.java     |  27 ++++-
 .../sling/maven/bundlesupport/FsUnMountMojo.java   |   6 +-
 .../ResponseCodeEnforcingResponseHandler.java      |  85 +++++++++++++++
 .../deploy/method/WebDavPutDeployMethod.java       |  29 ------
 .../fsresource/FileVaultXmlMounter.java            |  24 +++--
 .../bundlesupport/fsresource/FsMountHelper.java    |  89 ++++++++++------
 .../fsresource/FsResourceConfiguration.java        |  31 ++++--
 .../fsresource/SlingInitialContentMounter.java     |  30 +++---
 20 files changed, 540 insertions(+), 109 deletions(-)

diff --git a/src/it/fs-mount-test/invoker.properties b/src/it/fs-mount-test/invoker.properties
new file mode 100644
index 0000000..84e0a98
--- /dev/null
+++ b/src/it/fs-mount-test/invoker.properties
@@ -0,0 +1,17 @@
+# 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.
+invoker.goals=install -Dsling.urlSuffix=/system/console
\ No newline at end of file
diff --git a/src/it/fs-mount-test/pom.xml b/src/it/fs-mount-test/pom.xml
new file mode 100644
index 0000000..f8c59dd
--- /dev/null
+++ b/src/it/fs-mount-test/pom.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.sling</groupId>
+    <artifactId>example-pom</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <build>
+        <resources>
+            <!-- copy webapp resources to SLING-INF/app-root -->
+            <resource>
+                <directory>src/main/webapp</directory>
+                <targetPath>SLING-INF</targetPath>
+                <filtering>false</filtering>
+            </resource>
+        </resources>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <version>3.3.0</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>3.10.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>2.22.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-install-plugin</artifactId>
+                    <version>3.0.1</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>3.3.0</version>
+                <executions>
+                    <execution>
+                        <id>copy</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>io.wcm</groupId>
+                                    <artifactId>io.wcm.caconfig.editor</artifactId>
+                                    <version>1.8.0</version>
+                                    <outputDirectory>${project.build.directory}</outputDirectory>
+                                    <destFileName>ca-config-editor.jar</destFileName>
+                                </artifactItem>
+                            </artifactItems>
+                            <!-- other configurations here -->
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>@project.groupId@</groupId>
+                <artifactId>@project.artifactId@</artifactId>
+                <version>@project.version@</version>
+                <executions>
+                    <execution>
+                        <id>fsmount</id>
+                        <goals>
+                            <goal>fsmount</goal>
+                        </goals>
+                        <phase>install</phase>
+                    </execution>
+                    <execution>
+                        <id>fsunmount</id>
+                        <goals>
+                            <goal>fsunmount</goal>
+                        </goals>
+                        <phase>install</phase>
+                    </execution>
+                </executions>
+                <configuration>
+                    <!-- try a bundle with Sling Initial content -->
+                    <bundleFileName>${project.build.directory}/ca-config-editor.jar</bundleFileName>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/src/it/fs-mount-test/src/main/webapp/app-root/example.txt b/src/it/fs-mount-test/src/main/webapp/app-root/example.txt
new file mode 100644
index 0000000..99ca447
--- /dev/null
+++ b/src/it/fs-mount-test/src/main/webapp/app-root/example.txt
@@ -0,0 +1,19 @@
+<!--
+    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.
+-->
+Dummy file
\ No newline at end of file
diff --git a/src/it/fs-mount-test/verify.groovy b/src/it/fs-mount-test/verify.groovy
new file mode 100644
index 0000000..e488cd4
--- /dev/null
+++ b/src/it/fs-mount-test/verify.groovy
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+String buildLog = new File(basedir, 'build.log').text
+
+assert buildLog.contains('[INFO] Added new configuration for resource path /apps/wcm-io/caconfig/editor to server')
+assert buildLog.contains('[INFO] Removed configuration for resource path /apps/wcm-io/caconfig/editor')
diff --git a/src/it/validate-test/invoker.properties b/src/it/validate-test/invoker.properties
new file mode 100644
index 0000000..abd4d0a
--- /dev/null
+++ b/src/it/validate-test/invoker.properties
@@ -0,0 +1,18 @@
+# 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.
+invoker.goals=install
+invoker.buildResult=failure
\ No newline at end of file
diff --git a/src/it/validate-test/pom.xml b/src/it/validate-test/pom.xml
new file mode 100644
index 0000000..6bc4be2
--- /dev/null
+++ b/src/it/validate-test/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.sling</groupId>
+    <artifactId>example-pom</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <version>3.3.0</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>3.10.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>2.22.1</version>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-install-plugin</artifactId>
+                    <version>3.0.1</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        
+        <plugins>
+            <plugin>
+                <groupId>@project.groupId@</groupId>
+                <artifactId>@project.artifactId@</artifactId>
+                <version>@project.version@</version>
+                <executions>
+                    <execution>
+                        <id>validate</id>
+                        <goals>
+                            <goal>validate</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <!-- try a bundle with Sling Initial content -->
+                    <bundleFileName>${project.build.directory}/ca-config-editor.jar</bundleFileName>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/src/it/validate-test/src/main/resources/invalid.json b/src/it/validate-test/src/main/resources/invalid.json
new file mode 100644
index 0000000..3bd37ee
--- /dev/null
+++ b/src/it/validate-test/src/main/resources/invalid.json
@@ -0,0 +1,3 @@
+{
+  some test: "test"
+}
\ No newline at end of file
diff --git a/src/it/validate-test/verify.groovy b/src/it/validate-test/verify.groovy
new file mode 100644
index 0000000..c145f94
--- /dev/null
+++ b/src/it/validate-test/verify.groovy
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+String buildLog = new File(basedir, 'build.log').text
+
+assert buildLog.contains('invalid.json [2:4]: Invalid JSON: Unexpected character \'s\' (Codepoint: 115). Reason is [[Expected structural character or digit or \'t\' or \'n\' or \'f\' or \'-\']]')
+assert buildLog.contains('validate (validate) on project example-pom: Validated 1 file(s), found 1 failures. -> [Help 1]')
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java b/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java
index e6c3bb2..385bd67 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java
@@ -160,8 +160,8 @@ abstract class AbstractBundleInstallMojo extends AbstractBundleRequestMojo {
         }
     }
     
-    protected void configure(CloseableHttpClient httpClient, final URI targetURL, final File file) throws MojoExecutionException {
-        new SlingInitialContentMounter(getLog(), httpClient, project).mount(targetURL, file);
+    protected void configure(CloseableHttpClient httpClient, final URI consoleTargetURL, final File file) throws MojoExecutionException {
+        new SlingInitialContentMounter(getLog(), httpClient, getRequestConfigBuilder(), project).mount(consoleTargetURL, file);
     }
 
     /**
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleRequestMojo.java b/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleRequestMojo.java
index 8203640..9517807 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleRequestMojo.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleRequestMojo.java
@@ -92,6 +92,23 @@ abstract class AbstractBundleRequestMojo extends AbstractMojo {
     @Parameter(property = "sling.failOnError", defaultValue = "true", required = true)
     protected boolean failOnError;
 
+    /**
+     * HTTP connection timeout (in seconds). Determines the timeout until a new connection is fully established.
+     * This may also include transport security negotiation exchanges
+     * such as {@code SSL} or {@code TLS} protocol negotiation).
+     * @since 3.0.0
+     */
+    @Parameter(property = "sling.httpConnectTimeoutSec", defaultValue = "10")
+    private int httpConnectTimeoutSec;
+
+    /**
+     * HTTP response timeout (in seconds). Determines the timeout until arrival of a response from the opposite
+     * endpoint.
+     * @since 3.0.0
+     */
+    @Parameter(property = "sling.httpResponseTimeoutSec", defaultValue = "60")
+    private int httpResponseTimeoutSec;
+
     /**
      * Returns the symbolic name of the given bundle. If the
      * <code>jarFile</code> does not contain a manifest with a
@@ -191,14 +208,17 @@ abstract class AbstractBundleRequestMojo extends AbstractMojo {
         // restrict to the Sling URL only
         final HttpHost target = new HttpHost(getTargetURL().getScheme(), getTargetURL().getHost(), getTargetURL().getPort());
 
-        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(Timeout.ofSeconds(5)).build();
-        
         return HttpClients.custom()
-                .setDefaultRequestConfig(requestConfig)
+                .setDefaultRequestConfig(getRequestConfigBuilder().build())
                 .addRequestInterceptorFirst(new PreemptiveBasicAuthInterceptor(basicAuth, target, getLog()))
                 .build();
     }
 
+    protected RequestConfig.Builder getRequestConfigBuilder() {
+        return RequestConfig.custom()
+            .setConnectTimeout(Timeout.ofSeconds(httpConnectTimeoutSec))
+            .setResponseTimeout(Timeout.ofSeconds(httpResponseTimeoutSec));
+    }
 
     private static final class PreemptiveBasicAuthInterceptor implements HttpRequestInterceptor {
 
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/BundlePrerequisite.java b/src/main/java/org/apache/sling/maven/bundlesupport/BundlePrerequisite.java
index a6afbef..a976ab2 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/BundlePrerequisite.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/BundlePrerequisite.java
@@ -129,7 +129,12 @@ public final class BundlePrerequisite {
                 return this.version;
             }
         }
-        
+
+        @Override
+        public String toString() {
+            return "Bundle [groupId=" + groupId + ", artifactId=" + artifactId + ", version=" + version + ", symbolicName=" + symbolicName
+                    + "]";
+        }
     }
 
 }
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/BundleUninstallMojo.java b/src/main/java/org/apache/sling/maven/bundlesupport/BundleUninstallMojo.java
index 3d17b05..2721437 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/BundleUninstallMojo.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/BundleUninstallMojo.java
@@ -114,7 +114,7 @@ public class BundleUninstallMojo extends AbstractBundleInstallMojo {
 
     @Override
     protected void configure(CloseableHttpClient httpClient, final URI targetURL, final File file) throws MojoExecutionException {
-        new SlingInitialContentMounter(getLog(), httpClient, project).unmount(targetURL);
+        new SlingInitialContentMounter(getLog(), httpClient, getRequestConfigBuilder(), project).unmount(targetURL);
     }
     
 }
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java b/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java
index a2dcac7..6109f1c 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/FsMountMojo.java
@@ -22,15 +22,18 @@ import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import javax.json.JsonArray;
 import javax.json.JsonException;
 import javax.json.JsonObject;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.hc.client5.http.HttpResponseException;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
 import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.core5.http.HttpStatus;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
@@ -50,6 +53,8 @@ import org.apache.sling.maven.bundlesupport.fsresource.SlingInitialContentMounte
 /**
  * Create OSGi configurations for the
  * <a href="https://sling.apache.org/documentation/bundles/accessing-filesystem-resources-extensions-fsresource.html">Apache Sling File System Resource Provider</a>.
+ * In case a bundle file is provided via {@link AbstractFsMountMojo#bundleFileName} the configuration for its <a href="https://sling.apache.org/documentation/bundles/content-loading-jcr-contentloader.html#initial-content-loading">initial content</a> is created.
+ * Otherwise it tries to detect a FileVault XML layout within {@link AbstractFsMountMojo#fileVaultJcrRootFile} or the project's base directory and potentially creates a configuration for each path in the package's {@code filter.xml}. 
  * @since 2.2.0
  */
 @Mojo(name = "fsmount", requiresProject = true)
@@ -164,12 +169,12 @@ public class FsMountMojo extends AbstractFsMountMojo {
 
     @Override
     protected void configureSlingInitialContent(CloseableHttpClient httpClient, final URI targetUrl, final File bundleFile) throws MojoExecutionException {
-        new SlingInitialContentMounter(getLog(), getHttpClient(), project).mount(targetUrl, bundleFile);
+        new SlingInitialContentMounter(getLog(), getHttpClient(), getRequestConfigBuilder(), project).mount(targetUrl, bundleFile);
     }
 
     @Override
     protected void configureFileVaultXml(CloseableHttpClient httpClient, URI targetUrl, File jcrRootFile, File filterXmlFile) throws MojoExecutionException {
-        new FileVaultXmlMounter(getLog(), httpClient, project).mount(targetUrl, jcrRootFile, filterXmlFile);
+        new FileVaultXmlMounter(getLog(), httpClient, getRequestConfigBuilder(), project).mount(targetUrl, jcrRootFile, filterXmlFile);
     }
 
     @Override
@@ -198,6 +203,8 @@ public class FsMountMojo extends AbstractFsMountMojo {
                     deployBundle(httpClient, bundle, targetUrl);
                 }
                 break;
+            } else {
+                throw new MojoExecutionException("Target server does not meet prerequisites for this goal. Haven't found the necessary bundles: " + bundlePrerequisite.getPreconditions().stream().map(BundlePrerequisite.Bundle::toString).collect(Collectors.joining(", ")));
             }
         }
     }
@@ -208,7 +215,10 @@ public class FsMountMojo extends AbstractFsMountMojo {
                 getLog().debug("Bundle " + bundle.getSymbolicName() + " " + bundle.getOsgiVersion() + " (or higher) already installed.");
                 return;
             }
-            
+        } catch(IOException e) {
+            throw new MojoExecutionException("Error getting installation status of " + bundle + " via " + targetUrl + ": " + e.getMessage(), e);
+        }
+        try {
             getLog().info("Installing Bundle " + bundle.getSymbolicName() + " " + bundle.getOsgiVersion() + " to "
                         + targetUrl + " via " + deploymentMethod);
             
@@ -255,11 +265,12 @@ public class FsMountMojo extends AbstractFsMountMojo {
      * @throws MojoExecutionException
      */
     private String getBundleInstalledVersion(CloseableHttpClient httpClient, final String bundleSymbolicName, final URI targetUrl) throws IOException {
-        final URI getUrl = targetUrl.resolve( "/bundles/" + bundleSymbolicName + ".json");
+        final URI getUrl = targetUrl.resolve( "/system/console/bundles/" + bundleSymbolicName + ".json");
+        getLog().debug("Get bundle data via request to " + getUrl);
         final HttpGet get = new HttpGet(getUrl);
 
-        final String jsonText = httpClient.execute(get, new BasicHttpClientResponseHandler());
         try {
+            final String jsonText = httpClient.execute(get, new BasicHttpClientResponseHandler());
             JsonObject response = JsonSupport.parseObject(jsonText);
             JsonArray data = response.getJsonArray("data");
             if (!data.isEmpty()) {
@@ -270,6 +281,12 @@ public class FsMountMojo extends AbstractFsMountMojo {
         } catch (JsonException ex) {
             throw new IOException("Reading bundle data from " + getUrl
                     + " failed, cause: " + ex.getMessage(), ex);
+        } catch (HttpResponseException e) {
+            // accept 404 response
+            if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
+                return null;
+            }
+            throw e;
         }
         // no version detected, bundle is not installed
         return null;
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java b/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java
index 962887d..2d5aae5 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/FsUnMountMojo.java
@@ -29,6 +29,8 @@ import org.apache.sling.maven.bundlesupport.fsresource.SlingInitialContentMounte
 /**
  * Remove OSGi configurations for the 
  * <a href="https://sling.apache.org/documentation/bundles/accessing-filesystem-resources-extensions-fsresource.html">Apache Sling File System Resource Provider</a>.
+ * In case a bundle file is provided via {@link AbstractFsMountMojo#bundleFileName} the configuration for its <a href="https://sling.apache.org/documentation/bundles/content-loading-jcr-contentloader.html#initial-content-loading">initial content</a> is removed.
+ * Otherwise it tries to detect a FileVault XML layout within {@link AbstractFsMountMojo#fileVaultJcrRootFile} or the project's base directory and potentially removes the configurations for each path in the package's {@code filter.xml}. 
  * @since 2.2.0
  */
 @Mojo(name = "fsunmount", requiresProject = true)
@@ -36,12 +38,12 @@ public class FsUnMountMojo extends AbstractFsMountMojo {
 
     @Override
     protected void configureSlingInitialContent(CloseableHttpClient httpClient, final URI targetUrl, final File bundleFile) throws MojoExecutionException {
-        new SlingInitialContentMounter(getLog(), httpClient, project).unmount(targetUrl);
+        new SlingInitialContentMounter(getLog(), httpClient, getRequestConfigBuilder(), project).unmount(targetUrl);
     }
 
     @Override
     protected void configureFileVaultXml(CloseableHttpClient httpClient, URI targetUrl, File jcrRootFile, File filterXmlFile) throws MojoExecutionException {
-        new FileVaultXmlMounter(getLog(), httpClient, project).unmount(targetUrl, jcrRootFile, filterXmlFile);
+        new FileVaultXmlMounter(getLog(), httpClient, getRequestConfigBuilder(), project).unmount(targetUrl, jcrRootFile, filterXmlFile);
     }
 
     @Override
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/deploy/method/ResponseCodeEnforcingResponseHandler.java b/src/main/java/org/apache/sling/maven/bundlesupport/deploy/method/ResponseCodeEnforcingResponseHandler.java
new file mode 100644
index 0000000..2f56f26
--- /dev/null
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/deploy/method/ResponseCodeEnforcingResponseHandler.java
@@ -0,0 +1,85 @@
+/*
+ * 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.deploy.method;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.HttpResponseException;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHeaders;
+import org.apache.hc.core5.http.io.HttpClientResponseHandler;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+
+/**
+ * Throws {@link HttpResponseException} for all response codes except for the accepted ones.
+ * In addition optionally checks for a certain content type and content of the response.
+ * Returns the response code if all checks pass.
+ *
+ */
+public final class ResponseCodeEnforcingResponseHandler implements HttpClientResponseHandler<Integer> {
+
+    private final List<Integer> allowedCodes;
+    private final String expectedContentType; // may be null
+    private final Predicate<String> responseStringPredicate; // may be null
+
+    public ResponseCodeEnforcingResponseHandler(Integer... allowedCodes) {
+        this(null, allowedCodes);
+    }
+
+    public ResponseCodeEnforcingResponseHandler(String expectedContentType, Integer... allowedCodes) {
+        this(expectedContentType, null, allowedCodes);
+    }
+
+    public ResponseCodeEnforcingResponseHandler(String expectedContentType, Predicate<String> responseStringPredicate, Integer... allowedCodes) {
+        this.expectedContentType = expectedContentType;
+        this.responseStringPredicate = responseStringPredicate;
+        this.allowedCodes = Arrays.asList(allowedCodes);
+    }
+
+    @Override
+    public Integer handleResponse(ClassicHttpResponse response) throws HttpException, IOException {
+        final HttpEntity entity = response.getEntity();
+        try {
+            if (responseStringPredicate != null) {
+                String responseContent = EntityUtils.toString(entity);
+                if (!responseStringPredicate.test(responseContent)) {
+                    throw new ClientProtocolException("Unexpected response content returned: " + responseContent);
+                }
+            }
+            if (!allowedCodes.contains(response.getCode())) {
+                throw new HttpResponseException(response.getCode(), "Unexpected response code " + response.getCode() + ": " + response.getReasonPhrase());
+            }
+            String actualContentType = Optional.ofNullable(response.getHeader(HttpHeaders.CONTENT_TYPE)).map(Header::getValue).orElse(null);
+            if (expectedContentType != null && expectedContentType.equals(actualContentType)) {
+                throw new ClientProtocolException("Unexpected content type returned, expected " + expectedContentType + " but was " + actualContentType);
+            }
+        } finally {
+            EntityUtils.consume(entity);
+        }
+        return response.getCode();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/deploy/method/WebDavPutDeployMethod.java b/src/main/java/org/apache/sling/maven/bundlesupport/deploy/method/WebDavPutDeployMethod.java
index 0e96a94..de3877a 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/deploy/method/WebDavPutDeployMethod.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/deploy/method/WebDavPutDeployMethod.java
@@ -21,7 +21,6 @@ package org.apache.sling.maven.bundlesupport.deploy.method;
 import java.io.File;
 import java.io.IOException;
 import java.net.URI;
-import java.util.Arrays;
 import java.util.List;
 
 import org.apache.hc.client5.http.HttpResponseException;
@@ -29,13 +28,8 @@ import org.apache.hc.client5.http.classic.methods.HttpDelete;
 import org.apache.hc.client5.http.classic.methods.HttpHead;
 import org.apache.hc.client5.http.classic.methods.HttpPut;
 import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
-import org.apache.hc.core5.http.ClassicHttpResponse;
 import org.apache.hc.core5.http.ContentType;
-import org.apache.hc.core5.http.HttpEntity;
-import org.apache.hc.core5.http.HttpException;
 import org.apache.hc.core5.http.HttpStatus;
-import org.apache.hc.core5.http.io.HttpClientResponseHandler;
-import org.apache.hc.core5.http.io.entity.EntityUtils;
 import org.apache.hc.core5.http.io.entity.FileEntity;
 import org.apache.sling.maven.bundlesupport.deploy.DeployContext;
 import org.apache.sling.maven.bundlesupport.deploy.DeployMethod;
@@ -83,29 +77,6 @@ public class WebDavPutDeployMethod implements DeployMethod {
         // this never returns a body
     }
 
-    /**
-     * Throws {@link HttpResponseException} for all response codes except for the accepted ones.
-     * Returns the response code otherwise.
-     *
-     */
-    private static final class ResponseCodeEnforcingResponseHandler implements HttpClientResponseHandler<Integer> {
-
-        private final List<Integer> allowedCodes;
-        public ResponseCodeEnforcingResponseHandler(Integer... allowedCodes) {
-            this.allowedCodes = Arrays.asList(allowedCodes);
-        }
-
-        @Override
-        public Integer handleResponse(ClassicHttpResponse response) throws HttpException, IOException {
-            final HttpEntity entity = response.getEntity();
-            EntityUtils.consume(entity);
-            if (!allowedCodes.contains(response.getCode())) {
-                throw new HttpResponseException(response.getCode(), "Unexpected response code " + response.getCode() + ": " + response.getReasonPhrase());
-            }
-            return null;
-        }
-    }
-
     private void performMkCol(URI uri, DeployContext context) throws IOException {
         WebDavMkCol mkCol = new WebDavMkCol(uri);
         String response = context.getHttpClient().execute(mkCol, new BasicHttpClientResponseHandler());
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FileVaultXmlMounter.java b/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FileVaultXmlMounter.java
index e1c5cd3..1c32f56 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FileVaultXmlMounter.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FileVaultXmlMounter.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
 import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
 import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
@@ -42,19 +43,19 @@ public final class FileVaultXmlMounter {
     private final Log log;
     private final FsMountHelper helper;
 
-    public FileVaultXmlMounter(Log log, CloseableHttpClient httpClient, MavenProject project) {
+    public FileVaultXmlMounter(Log log, CloseableHttpClient httpClient, RequestConfig.Builder requestConfigBuilder, MavenProject project) {
         this.log = log;
-        this.helper = new FsMountHelper(log, httpClient, project);
+        this.helper = new FsMountHelper(log, httpClient, requestConfigBuilder, project);
     }
 
     /**
      * Add configurations to a running OSGi instance for FileVault XML
-     * @param targetUrl The web console base url
+     * @param consoleTargetUrl The web console base url
      * @param jcrRootFile jcr_root directory
      * @param filterXmlFile FileVault Filter XML file
      * @throws MojoExecutionException Exception
      */
-    public void mount(final URI targetUrl, final File jcrRootFile, final File filterXmlFile) throws MojoExecutionException {
+    public void mount(final URI consoleTargetUrl, final File jcrRootFile, final File filterXmlFile) throws MojoExecutionException {
         log.info("Trying to configure file system provider...");
 
         // create config for each path defined in filter
@@ -63,29 +64,30 @@ public final class FileVaultXmlMounter {
         for (PathFilterSet filterSet : workspaceFilter.getFilterSets()) {
             cfgs.add(new FsResourceConfiguration()
                     .fsMode(FsMode.FILEVAULT_XML)
-                    .contentRootDir(jcrRootFile.getAbsolutePath())
-                    .providerRootPath(filterSet.getRoot())
+                    .fsRootPath(jcrRootFile.getAbsoluteFile())
+                    .resourceRootPath(filterSet.getRoot())
                     .fileVaultFilterXml(filterXmlFile.getAbsolutePath()));
+            log.info("Created new configuration for resource path " + filterSet.getRoot());
         }
      
         if (!cfgs.isEmpty()) {
-            helper.addConfigurations(targetUrl, cfgs);
+            helper.addConfigurations(consoleTargetUrl, cfgs);
         }
     }
     
     /**
      * Remove configurations to a running OSGi instance for FileVault XML
-     * @param targetUrl The web console base url
+     * @param consoleTargetUrl The web console base url
      * @param jcrRootFile jcr_root directory
      * @param filterXmlFile FileVault Filter XML file
      * @throws MojoExecutionException Exception
      */
-    public void unmount(final URI targetUrl, final File jcrRootFile, final File filterXmlFile) throws MojoExecutionException {
+    public void unmount(final URI consoleTargetUrl, final File jcrRootFile, final File filterXmlFile) throws MojoExecutionException {
         log.info("Removing file system provider configurations...");
 
         // remove all current configs for this project
-        final Map<String,FsResourceConfiguration> oldConfigs = helper.getCurrentConfigurations(targetUrl);
-        helper.removeConfigurations(targetUrl, oldConfigs);
+        final Map<String,FsResourceConfiguration> oldConfigs = helper.getCurrentConfigurations(consoleTargetUrl);
+        helper.removeConfigurations(consoleTargetUrl, oldConfigs);
     }
         
     private WorkspaceFilter getWorkspaceFilter(final File filterXmlFile) throws MojoExecutionException {
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FsMountHelper.java b/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FsMountHelper.java
index d9412b8..bb88efa 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FsMountHelper.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FsMountHelper.java
@@ -18,6 +18,7 @@
  */
 package org.apache.sling.maven.bundlesupport.fsresource;
 
+import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayList;
@@ -26,18 +27,23 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
+import javax.json.Json;
 import javax.json.JsonArray;
 import javax.json.JsonException;
 import javax.json.JsonObject;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.hc.client5.http.HttpResponseException;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
 import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
-import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.client5.http.protocol.HttpClientContext;
+import org.apache.hc.core5.http.HttpStatus;
 import org.apache.hc.core5.http.NameValuePair;
 import org.apache.hc.core5.http.ProtocolException;
 import org.apache.hc.core5.http.io.entity.EntityUtils;
@@ -46,6 +52,7 @@ import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.apache.sling.maven.bundlesupport.JsonSupport;
+import org.apache.sling.maven.bundlesupport.deploy.method.ResponseCodeEnforcingResponseHandler;
 
 /**
  * Manages OSGi configurations for File System Resource Provider.
@@ -66,11 +73,13 @@ final class FsMountHelper {
         
     private final Log log;
     private final CloseableHttpClient httpClient;
+    private final RequestConfig.Builder requestConfigBuilder;
     private final MavenProject project;
 
-    public FsMountHelper(Log log, CloseableHttpClient httpClient, MavenProject project) {
+    public FsMountHelper(Log log, CloseableHttpClient httpClient, RequestConfig.Builder requestConfigBuilder, MavenProject project) {
         this.log = log;
         this.httpClient = httpClient;
+        this.requestConfigBuilder = requestConfigBuilder;
         this.project = project;
     }
     
@@ -81,7 +90,7 @@ final class FsMountHelper {
         final Map<String,FsResourceConfiguration> oldConfigs = getCurrentConfigurations(targetUrl);
 
         for (FsResourceConfiguration cfg : cfgs) {
-            log.info("Mapping " + cfg.getContentRootDir() + " to " + cfg.getProviderRootPath());
+            log.debug("Found mapping " + cfg.getFsRootPath() + " to " + cfg.getResourceRootPath());
             
             // check if this is already configured
             boolean found = false;
@@ -89,23 +98,24 @@ final class FsMountHelper {
             while ( !found && entryIterator.hasNext() ) {
                 final Map.Entry<String,FsResourceConfiguration> current = entryIterator.next();
                 final FsResourceConfiguration oldcfg = current.getValue();
-                log.debug("Comparing " + oldcfg.getContentRootDir() + " with " + oldcfg);
-                if (StringUtils.equals(oldcfg.getContentRootDir(), oldcfg.getContentRootDir())) {
+                log.debug("Comparing " + oldcfg.getFsRootPath() + " with " + oldcfg);
+                if (Objects.equals(oldcfg.getFsRootPath(), cfg.getFsRootPath())) {
                     if (cfg.equals(oldcfg)) {
-                        log.debug("Using existing configuration for " + cfg.getContentRootDir() + " and " + cfg.getProviderRootPath());
+                        log.info("Using existing configuration for " + cfg.getFsRootPath() + " mounted at " + cfg.getResourceRootPath());
                         found = true;
                     }
                     else {
                         // remove old config
-                        log.debug("Removing old configuration for " + oldcfg);
+                        log.info("Removing old configuration for " + oldcfg);
                         removeConfiguration(targetUrl, current.getKey());
                     }
                     entryIterator.remove();
                 }
             }
             if ( !found ) {
-                log.debug("Adding new configuration for " + cfg.getContentRootDir() + " and " + cfg.getProviderRootPath());
+                log.debug("Adding new configuration for " + cfg.getFsRootPath() + " mounted at " + cfg.getResourceRootPath());
                 addConfiguration(targetUrl, cfg);
+                log.info("Added new configuration for resource path "+ cfg.getResourceRootPath() + " to server");
             }
         }
         
@@ -116,13 +126,19 @@ final class FsMountHelper {
     /**
      * Add a new configuration for the file system provider
      */
-    private void addConfiguration(final URI targetUrl, FsResourceConfiguration cfg) throws MojoExecutionException {
-        final URI postUrl = targetUrl.resolve("/configMgr/" + FS_FACTORY);
+    private void addConfiguration(final URI consoleTargetUrl, FsResourceConfiguration cfg) throws MojoExecutionException {
+        final URI postUrl = consoleTargetUrl.resolve("configMgr/" + FS_FACTORY);
         final HttpPost post = new HttpPost(postUrl);
         List<NameValuePair> params = new ArrayList<>();
         params.add(new BasicNameValuePair("apply", "true"));
         params.add(new BasicNameValuePair("factoryPid", FS_FACTORY));
-        params.add(new BasicNameValuePair("pid", "[Temporary PID replaced by real PID upon save]"));
+        /*
+         * The pid parameter is mandatory but is replaced with another value upon save() for factories
+         * For that it must have the magic value from
+         * https://github.com/apache/felix-dev/blob/6603d69977f4cea8b9b9dd2faf5d320906b43368/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigurationUtil.java#L36
+         * This value is also used for performing a redirect and is no valid URI, therefore disable redirect handling
+         */
+        params.add(new BasicNameValuePair("pid", "[Temporary PID replaced by real PID upon save]")); // this is replaced with a generated one, upon save, still this is used for the redirect
         Map<String,String> props = toMap(cfg);
         for (Map.Entry<String,String> entry : props.entrySet()) {
             params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
@@ -130,9 +146,14 @@ final class FsMountHelper {
         params.add(new BasicNameValuePair("propertylist", StringUtils.join(props.keySet(), ",")));
         post.setEntity(new UrlEncodedFormEntity(params));
         
+        // do not follow redirects
+        RequestConfig requestConfig = requestConfigBuilder.setRedirectsEnabled(false).build();
+        HttpClientContext httpContext = HttpClientContext.create();
+        httpContext.setRequestConfig(requestConfig);
         try {
-            String response = httpClient.execute(post, new BasicHttpClientResponseHandler());
-            log.debug("Configuration created: " + response);
+            // accept also 302
+            httpClient.execute(post, httpContext, new ResponseCodeEnforcingResponseHandler(HttpStatus.SC_MOVED_TEMPORARILY));
+            log.debug("New configuration created POST to " + postUrl);
         }
         catch (IOException ex) {
             throw new MojoExecutionException("Configuration on " + postUrl + " failed, cause: " + ex.getMessage(), ex);
@@ -144,13 +165,13 @@ final class FsMountHelper {
         if (cfg.getFsMode() != null) {
             props.put(PROPERTY_FSMODE, cfg.getFsMode().name());
         }
-        if (cfg.getContentRootDir() != null) {
-            props.put(PROPERTY_PATH, cfg.getContentRootDir());
+        if (cfg.getFsRootPath() != null) {
+            props.put(PROPERTY_PATH, cfg.getFsRootPath().toString());
         }
-        if (cfg.getProviderRootPath() != null) {
+        if (cfg.getResourceRootPath() != null) {
             // save property value to both "provider.roots" and "provider.root" because the name has changed between fsresource 1.x and 2.x
-            props.put(PROPERTY_ROOT, cfg.getProviderRootPath());
-            props.put(PROPERTY_ROOTS, cfg.getProviderRootPath());
+            props.put(PROPERTY_ROOT, cfg.getResourceRootPath());
+            props.put(PROPERTY_ROOTS, cfg.getResourceRootPath());
         }
         if (cfg.getInitialContentImportOptions() != null) {
             props.put(PROPERTY_INITIAL_CONTENT_IMPORT_OPTIONS, cfg.getInitialContentImportOptions());
@@ -169,14 +190,15 @@ final class FsMountHelper {
             log.debug("Removing configuration for " + current.getValue());
             // remove old config
             removeConfiguration(targetUrl, current.getKey());
+            log.info("Removed configuration for resource path " + current.getValue().getResourceRootPath() + " (PID: " + current.getKey() + ") from server");
         }
     }
 
     /**
      * Remove configuration.
      */
-    private void removeConfiguration(final URI targetUrl, final String pid) throws MojoExecutionException {
-        final URI postUrl = targetUrl.resolve("/configMgr/" + pid);
+    private void removeConfiguration(final URI consoleTargetUrl, final String pid) throws MojoExecutionException {
+        final URI postUrl = consoleTargetUrl.resolve("configMgr/" + pid);
         final HttpPost post = new HttpPost(postUrl);
         List<NameValuePair> params = new ArrayList<>();
         params.add(new BasicNameValuePair("apply", "true"));
@@ -184,9 +206,11 @@ final class FsMountHelper {
         post.setEntity(new UrlEncodedFormEntity(params));
        
         try {
-            String response = httpClient.execute(post, new BasicHttpClientResponseHandler());
-            // we get a moved temporarily back from the configMgr plugin
-            log.debug("Configuration removed: " + response);
+            JsonObject expectedJsonResponse = Json.createObjectBuilder().add("status", true).build();
+            // https://github.com/apache/felix-dev/blob/6603d69977f4cea8b9b9dd2faf5d320906b43368/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigManager.java#L145
+            httpClient.execute(post, new ResponseCodeEnforcingResponseHandler("application/json", 
+                    response ->  JsonSupport.parseObject(response).equals(expectedJsonResponse),
+                    HttpStatus.SC_OK));
         }
         catch (IOException ex) {
             throw new MojoExecutionException("Removing configuration at " + postUrl
@@ -196,19 +220,19 @@ final class FsMountHelper {
 
     /**
      * Return all file provider configs for this project
-     * @param targetUrl The targetUrl of the webconsole
+     * @param consoleTargetUrl The web console base url
      * @return A map (may be empty) with the pids as keys and the configurations as values
      * @throws MojoExecutionException
      */
-    public Map<String,FsResourceConfiguration> getCurrentConfigurations(final URI targetUrl) throws MojoExecutionException {
-        log.debug("Getting current file provider configurations.");
+    public Map<String,FsResourceConfiguration> getCurrentConfigurations(final URI consoleTargetUrl) throws MojoExecutionException {
         final Map<String,FsResourceConfiguration> result = new HashMap<>();
-        final URI getUrl = targetUrl.resolve("/configMgr/(service.factoryPid=" + FS_FACTORY + ").json");
+        final URI getUrl = consoleTargetUrl.resolve("configMgr/(service.factoryPid=" + FS_FACTORY + ").json");
+        log.debug("Getting current file provider configurations via GET from " + getUrl);
         final HttpGet get = new HttpGet(getUrl);
 
         try (CloseableHttpResponse response = httpClient.execute(get)) {
             final int status = response.getCode();
-            if ( status == 200 ) {
+            if ( status == HttpStatus.SC_OK ) {
                 String contentType = response.getHeader(HEADER_CONTENT_TYPE).getValue();
                 int pos = contentType.indexOf(';');
                 if ( pos != -1 ) {
@@ -238,18 +262,23 @@ final class FsMountHelper {
                         if (path != null && path.startsWith(this.project.getBasedir().getAbsolutePath()) && root != null) {
                             FsResourceConfiguration cfg = new FsResourceConfiguration()
                                     .fsMode(fsmode)
-                                    .providerRootPath(path)
-                                    .contentRootDir(root)
+                                    .resourceRootPath(root)
+                                    .fsRootPath(new File(path))
                                     .initialContentImportOptions(initialContentImportOptions)
                                     .fileVaultFilterXml(fileVaultFilterXml);
                             log.debug("Found configuration with pid: " + pid + ", " + cfg);
                             result.put(pid, cfg);
                         }
                     }
+                    if (array.isEmpty()) {
+                        log.info("Found no existing configurations for factory PID " + FS_FACTORY);
+                    }
                 } catch (JsonException ex) {
                     throw new MojoExecutionException("Reading configuration from " + getUrl
                             + " failed, cause: " + ex.getMessage(), ex);
                 }
+            } else {
+                throw new HttpResponseException(response.getCode(), "Unexpected status code " + response.getCode() + ": " + response.getReasonPhrase());
             }
         }
         catch (IOException | ProtocolException ex) {
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FsResourceConfiguration.java b/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FsResourceConfiguration.java
index 3a81408..2202c6c 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FsResourceConfiguration.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/FsResourceConfiguration.java
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.maven.bundlesupport.fsresource;
 
+import java.io.File;
+
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -27,8 +29,8 @@ import org.apache.commons.lang3.builder.ToStringStyle;
 class FsResourceConfiguration {
 
     private FsMode fsMode;
-    private String providerRootPath;
-    private String contentRootDir;
+    private String resourceRootPath; // absolute resource path
+    private File fsRootPath; // absolute filesystem path
     private String initialContentImportOptions;
     private String fileVaultFilterXml;
 
@@ -49,25 +51,29 @@ class FsResourceConfiguration {
         return this;
     }
 
-    public String getProviderRootPath() {
-        return providerRootPath;
+    public String getResourceRootPath() {
+        return resourceRootPath;
     }
-    public FsResourceConfiguration providerRootPath(String value) {
-        this.providerRootPath = value;
+    public FsResourceConfiguration resourceRootPath(String value) {
+        this.resourceRootPath = value;
         return this;
     }
 
-    public String getContentRootDir() {
-        return contentRootDir;
+    public File getFsRootPath() {
+        return fsRootPath;
     }
-    public FsResourceConfiguration contentRootDir(String value) {
-        this.contentRootDir = value;
+    public FsResourceConfiguration fsRootPath(File value) {
+        if (!value.isAbsolute()) {
+            throw new IllegalArgumentException("The given filesystem path must be absolute");
+        }
+        this.fsRootPath = value;
         return this;
     }
 
     public String getInitialContentImportOptions() {
         return initialContentImportOptions;
     }
+
     public FsResourceConfiguration initialContentImportOptions(String value) {
         this.initialContentImportOptions = value;
         return this;
@@ -76,19 +82,22 @@ class FsResourceConfiguration {
     public String getStringVaultFilterXml() {
         return fileVaultFilterXml;
     }
+
     public FsResourceConfiguration fileVaultFilterXml(String value) {
         this.fileVaultFilterXml = value;
         return this;
     }
-    
+
     @Override
     public int hashCode() {
         return HashCodeBuilder.reflectionHashCode(this);
     }
+
     @Override
     public boolean equals(Object obj) {
         return EqualsBuilder.reflectionEquals(this, obj);
     }
+
     @Override
     public String toString() {
         return ToStringBuilder.reflectionToString(this, ToStringStyle.NO_CLASS_NAME_STYLE);
diff --git a/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/SlingInitialContentMounter.java b/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/SlingInitialContentMounter.java
index fb340a4..1e6d6d3 100644
--- a/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/SlingInitialContentMounter.java
+++ b/src/main/java/org/apache/sling/maven/bundlesupport/fsresource/SlingInitialContentMounter.java
@@ -29,6 +29,7 @@ import java.util.jar.JarFile;
 import java.util.jar.Manifest;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
 import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -49,19 +50,19 @@ public final class SlingInitialContentMounter {
     private final MavenProject project;
     private final FsMountHelper helper;
 
-    public SlingInitialContentMounter(Log log, CloseableHttpClient httpClient, MavenProject project) {
+    public SlingInitialContentMounter(Log log, CloseableHttpClient httpClient, RequestConfig.Builder requestConfigBuilder, MavenProject project) {
         this.log = log;
         this.project = project;
-        this.helper = new FsMountHelper(log, httpClient, project);
+        this.helper = new FsMountHelper(log, httpClient, requestConfigBuilder, project);
     }
 
     /**
      * Add configurations to a running OSGi instance for initial content.
-     * @param targetUrl The web console base url
+     * @param consoleTargetUrl The web console base url
      * @param bundleFile The artifact (bundle)
      * @throws MojoExecutionException Exception
      */
-    public void mount(final URI targetUrl, final File bundleFile) throws MojoExecutionException {
+    public void mount(final URI consoleTargetUrl, final File bundleFile) throws MojoExecutionException {
         // first, let's get the manifest and see if initial content is configured
         ManifestHeader header = null;
         try {
@@ -82,7 +83,7 @@ public final class SlingInitialContentMounter {
 
         log.info("Trying to configure file system provider...");
         // quick check if resources are configured
-        final List resources = project.getResources();
+        final List<Resource> resources = project.getResources();
         if ( resources == null || resources.size() == 0 ) {
             throw new MojoExecutionException("No resources configured for this project.");
         }
@@ -107,7 +108,7 @@ public final class SlingInitialContentMounter {
             // 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();
+            final Iterator<Resource> i = resources.iterator();
             while ( dir == null && i.hasNext() ) {
                 final Resource rsrc = (Resource)i.next();
                 String child = path;
@@ -116,6 +117,7 @@ public final class SlingInitialContentMounter {
                 if ( targetPath != null && !targetPath.endsWith("/") ) {
                     targetPath = targetPath + "/";
                 }
+                log.debug("Checking if project resource '" + rsrc.getDirectory() + "' with target path '" + targetPath + "' is a potential mount point for " + path + " ..." );
                 if ( targetPath != null && path != null && path.startsWith(targetPath) ) {
                     child = child.substring(targetPath.length());
                 }
@@ -145,30 +147,30 @@ public final class SlingInitialContentMounter {
                 }
                 importOptions.append("ignoreImportProviders:=\"" + ignoreImportProvidersValue + "\"");
             }
-            
             cfgs.add(new FsResourceConfiguration()
                     .fsMode(FsMode.INITIAL_CONTENT)
-                    .contentRootDir(dir.getAbsolutePath())
-                    .providerRootPath(installPath)
+                    .fsRootPath(dir.getAbsoluteFile())
+                    .resourceRootPath(installPath)
                     .initialContentImportOptions(importOptions.toString()));
+            log.info("Created new configuration for resource path " + installPath);
         }
 
         if (!cfgs.isEmpty()) {
-            helper.addConfigurations(targetUrl, cfgs);
+            helper.addConfigurations(consoleTargetUrl, cfgs);
         }
     }
 
     /**
      * Remove configurations from a running OSGi instance for initial content.
-     * @param targetUrl The web console base url (up to the parent resource of the affected bundle)
+     * @param consoleTargetUrl The web console base url
      * @throws MojoExecutionException Exception
      */
-    public void unmount(final URI targetUrl) throws MojoExecutionException {
+    public void unmount(final URI consoleTargetUrl) throws MojoExecutionException {
         log.info("Removing file system provider configurations...");
 
         // remove all current configs for this project
-        final Map<String,FsResourceConfiguration> oldConfigs = helper.getCurrentConfigurations(targetUrl);
-        helper.removeConfigurations(targetUrl, oldConfigs);
+        final Map<String,FsResourceConfiguration> oldConfigs = helper.getCurrentConfigurations(consoleTargetUrl);
+        helper.removeConfigurations(consoleTargetUrl, oldConfigs);
     }
     
     /**