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 14:07:21 UTC
[sling-maven-plugin] branch master updated: SLING-11522 fix mount goals (#14)
This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-maven-plugin.git
The following commit(s) were added to refs/heads/master by this push:
new d3c5e20 SLING-11522 fix mount goals (#14)
d3c5e20 is described below
commit d3c5e20c1cc86e89c2e8e297de5e22b8eebad171
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Sat Aug 13 16:07:17 2022 +0200
SLING-11522 fix mount goals (#14)
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);
}
/**