You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2020/07/26 08:17:03 UTC

[jackrabbit-filevault] branch master updated: JCRVLT-419 allow to parameterize connection options (#92)

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/jackrabbit-filevault.git


The following commit(s) were added to refs/heads/master by this push:
     new 584f38c  JCRVLT-419 allow to parameterize connection options (#92)
584f38c is described below

commit 584f38c9b92d925e4967f0e0c07b626ceaf30c62
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Sun Jul 26 10:16:52 2020 +0200

    JCRVLT-419 allow to parameterize connection options (#92)
---
 parent/pom.xml                                     |   4 +-
 .../apache/jackrabbit/vault/cli/VaultFsApp.java    | 145 ++++++++++++++++++++-
 .../vault/util/console/AbstractApplication.java    |   2 +-
 vault-core/pom.xml                                 |  11 ++
 .../jackrabbit/vault/fs/api/RepositoryFactory.java |   7 +
 .../jackrabbit/vault/fs/api/package-info.java      |   2 +-
 .../jackrabbit/vault/util/RepositoryProvider.java  |  13 +-
 .../apache/jackrabbit/vault/util/package-info.java |   2 +-
 .../vault/davex/DAVExRepositoryFactory.java        |  12 +-
 vault-doc/src/site/markdown/rcp.md                 |  35 +++--
 vault-doc/src/site/markdown/usage.md               |  95 ++++++++------
 vault-rcp/bnd.bnd                                  |  15 ++-
 vault-rcp/pom.xml                                  |  19 ++-
 .../org/apache/jackrabbit/vault/rcp/RcpTask.java   |   3 +
 .../jackrabbit/vault/rcp/RcpTaskManager.java       |   7 +-
 .../vault/rcp/impl/ConnectionOptionsMixin.java     |  45 +++++++
 .../jackrabbit/vault/rcp/impl/RcpServlet.java      |  69 +++++++++-
 .../jackrabbit/vault/rcp/impl/RcpTaskImpl.java     |  23 +++-
 .../vault/rcp/impl/RcpTaskManagerImpl.java         |  32 ++---
 .../rcp/impl/WorkspaceFilterDeserializer.java      |   3 +-
 .../vault/rcp/impl/RcpTaskManagerImplTest.java     |  29 ++---
 vault-sync/pom.xml                                 |   2 +-
 22 files changed, 449 insertions(+), 126 deletions(-)

diff --git a/parent/pom.xml b/parent/pom.xml
index 55c33b2..6bc7cc6 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -50,7 +50,7 @@ Apache Jackrabbit FileVault is a project of the Apache Software Foundation.
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <jackrabbit.version>2.20.1</jackrabbit.version>
+        <jackrabbit.version>2.21.3</jackrabbit.version><!-- unstable because JCR-4536 is not available in a stable release yet -->
         <oak.version>1.30.0</oak.version>
         <slf4j.version>1.7.6</slf4j.version>
         <test.oak>false</test.oak>
@@ -186,6 +186,8 @@ Bundle-Category: jackrabbit
                     </executions>
                     <configuration>
                         <useMavenDependencies>true</useMavenDependencies>
+                        <!-- do not include any regular scopes (https://github.com/bndtools/bnd/blob/38ef85e389678370304846d6b09ffd31f9efb87d/biz.aQute.bnd.maven/src/aQute/bnd/maven/lib/resolve/Scope.java#L13), compare with https://github.com/bndtools/bnd/issues/4207 -->
+                        <scopes>distro</scopes>
                         <failOnChanges>false</failOnChanges><!-- reuse for multiple bundles which all require different minimum container -->
                         <writeOnChanges>false</writeOnChanges>
                     </configuration>
diff --git a/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java b/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java
index 8134a57..afba536 100644
--- a/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java
+++ b/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java
@@ -21,6 +21,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import javax.jcr.Credentials;
 import javax.jcr.Repository;
@@ -33,6 +34,7 @@ import org.apache.commons.cli2.Option;
 import org.apache.commons.cli2.builder.ArgumentBuilder;
 import org.apache.commons.cli2.builder.DefaultOptionBuilder;
 import org.apache.commons.cli2.builder.GroupBuilder;
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
 import org.apache.jackrabbit.vault.cli.extended.ExtendedOption;
 import org.apache.jackrabbit.vault.cli.extended.XDavEx;
 import org.apache.jackrabbit.vault.cli.extended.XJcrLog;
@@ -107,6 +109,18 @@ public class VaultFsApp extends AbstractApplication {
     //private Option optMountpoint;
     private Option optConfig;
     private Option optUpdateCreds;
+    // connection options
+    private Option optAllowSelfSignedCertificate;
+    private Option optDisableHostnameValidation;
+    private Option optConnectionTimeoutMs;
+    private Option optRequestTimeoutMs;
+    private Option optSocketTimeoutMs;
+    private Option optUseSystemProperties;
+    private Option optProxyHost;
+    private Option optProxyPort;
+    private Option optProxyProtocol;
+    private Option optProxyUsername;
+    private Option optProxyPassword;
 
     private ExtendedOption[] xOpts = new ExtendedOption[]{
             new XJcrLog(),
@@ -122,6 +136,7 @@ public class VaultFsApp extends AbstractApplication {
 
     private Console console;
 
+
     public static void main(String[] args) {
         new VaultFsApp().run(args);
     }
@@ -222,11 +237,6 @@ public class VaultFsApp extends AbstractApplication {
         return fs;
     }
 
-    @Override
-    public String getCopyrightLine() {
-        return "Copyright 2018 by Apache Software Foundation. See LICENSE.txt for more information.";
-    }
-
     protected void mount(String creds, String wsp, String root, String config,
                          String filter, boolean remount) {
         if (!isConnected()) {
@@ -392,8 +402,9 @@ public class VaultFsApp extends AbstractApplication {
             throw new ExecutionException("Already connected to " + getProperty(KEY_URI));
         } else {
             String uri = getProperty(KEY_DEFAULT_URI);
+            ConnectionOptions options = ConnectionOptions.fromServiceFactoryParameters(getEnv());
             try {
-                rep = repProvider.getRepository(new RepositoryAddress(uri));
+                rep = repProvider.getRepository(new RepositoryAddress(uri), options);
                 setProperty(KEY_URI, uri);
                 StringBuffer info = new StringBuffer();
                 info.append(rep.getDescriptor(Repository.REP_NAME_DESC)).append(' ');
@@ -604,7 +615,90 @@ public class VaultFsApp extends AbstractApplication {
                         .create()
                 )
                 .create();
-
+        optUseSystemProperties = new DefaultOptionBuilder()
+                .withLongName("useSystemProperties")
+                .withDescription("Evaluating the default Java system properties for connection settings.")
+                .create();
+        optAllowSelfSignedCertificate = new DefaultOptionBuilder()
+                .withLongName("allowSelfSignedCertificates")
+                .withDescription("Allows to connect to HTTPS repository urls whose certificate is self-signed.")
+                .create();
+        optDisableHostnameValidation = new DefaultOptionBuilder()
+                .withLongName("disableHostnameValidator")
+                .withDescription("Disables hostname validation for HTTPS repository urls.")
+                .create();
+        optConnectionTimeoutMs = new DefaultOptionBuilder()
+                .withLongName("connectionTimeoutMs")
+                .withDescription("The connection timeout in milliseconds.")
+                .withArgument(new ArgumentBuilder()
+                        .withMinimum(1)
+                        .withMaximum(1)
+                        .create()
+                )
+                .create();
+        optRequestTimeoutMs = new DefaultOptionBuilder()
+                .withLongName("requestTimeoutMs")
+                .withDescription("The request timeout in milliseconds.")
+                .withArgument(new ArgumentBuilder()
+                        .withMinimum(1)
+                        .withMaximum(1)
+                        .create()
+                )
+                .create();
+        optSocketTimeoutMs = new DefaultOptionBuilder()
+                .withLongName("socketTimeoutMs")
+                .withDescription("The socket timeout in milliseconds.")
+                .withArgument(new ArgumentBuilder()
+                        .withMinimum(1)
+                        .withMaximum(1)
+                        .create()
+                )
+                .create();
+        optProxyHost = new DefaultOptionBuilder()
+                .withLongName("proxyHost")
+                .withDescription("The host of the proxy to use.")
+                .withArgument(new ArgumentBuilder()
+                        .withMinimum(1)
+                        .withMaximum(1)
+                        .create()
+                )
+                .create();
+        optProxyPort = new DefaultOptionBuilder()
+                .withLongName("proxyPort")
+                .withDescription("The port where the proxy is running (requires proxyHost as well).")
+                .withArgument(new ArgumentBuilder()
+                        .withMinimum(1)
+                        .withMaximum(1)
+                        .create()
+                )
+                .create();
+        optProxyProtocol = new DefaultOptionBuilder()
+                .withLongName("proxyProtocol")
+                .withDescription("The protocol for which to use the proxy (requires proxyHost as well). If not set proxy is used for both HTTP and HTTPS.")
+                .withArgument(new ArgumentBuilder()
+                        .withMinimum(1)
+                        .withMaximum(1)
+                        .create()
+                )
+                .create();
+        optProxyUsername = new DefaultOptionBuilder()
+                .withLongName("proxyUsername")
+                .withDescription("The username to use for authentication at the proxy (requires proxyHost as well).")
+                .withArgument(new ArgumentBuilder()
+                        .withMinimum(1)
+                        .withMaximum(1)
+                        .create()
+                )
+                .create();
+        optProxyPassword = new DefaultOptionBuilder()
+                .withLongName("proxyPassword")
+                .withDescription("The password to use for authentication at the proxy (requires proxyUsername as well)")
+                .withArgument(new ArgumentBuilder()
+                        .withMinimum(1)
+                        .withMaximum(1)
+                        .create()
+                )
+                .create();
         // register extended options
         for (ExtendedOption x: xOpts) {
             gbuilder.withOption(x.getOption());
@@ -615,6 +709,13 @@ public class VaultFsApp extends AbstractApplication {
         gbuilder.withOption(optUpdateCreds);
         //gbuilder.withOption(optMountpoint);
         gbuilder.withOption(optConfig);
+        gbuilder.withOption(optUseSystemProperties);
+        gbuilder.withOption(optAllowSelfSignedCertificate);
+        gbuilder.withOption(optDisableHostnameValidation);
+        gbuilder.withOption(optConnectionTimeoutMs);
+        gbuilder.withOption(optRequestTimeoutMs);
+        gbuilder.withOption(optSocketTimeoutMs);
+        gbuilder.withOption(optProxyHost).withOption(optProxyPort).withOption(optProxyProtocol).withOption(optProxyUsername).withOption(optProxyPassword);
         return super.addApplicationOptions(gbuilder);
     }
 
@@ -659,8 +760,38 @@ public class VaultFsApp extends AbstractApplication {
         if (cl.getValue(optConfig) != null) {
             setProperty(KEY_DEFAULT_CONFIG_XML, (String) cl.getValue(optConfig));
         }
+        
+        parseConnectionOptions(cl);
+    }
+
+    private void parseConnectionOptions(CommandLine cl) {
+        ConnectionOptions.Builder builder = ConnectionOptions.builder();
+        builder.allowSelfSignedCertificates(cl.hasOption(optAllowSelfSignedCertificate));
+        builder.disableHostnameVerification(cl.hasOption(optDisableHostnameValidation));
+        builder.connectionTimeoutMs(Integer.parseInt(cl.getValue(optConnectionTimeoutMs, -1).toString()));
+        builder.requestTimeoutMs(Integer.parseInt(cl.getValue(optRequestTimeoutMs, -1).toString()));
+        builder.socketTimeoutMs(Integer.parseInt(cl.getValue(optSocketTimeoutMs, -1).toString()));
+        builder.useSystemProperties(cl.hasOption(optUseSystemProperties));
+        if (cl.getValue(optProxyHost) != null) {
+            builder.proxyHost(cl.getValue(optProxyHost).toString());
+            builder.proxyPort(Integer.parseInt(cl.getValue(optProxyPort, -1).toString()));
+            if (cl.getValue(optProxyProtocol) != null) {
+                builder.proxyProtocol(cl.getValue(optProxyProtocol).toString());
+            }
+            if (cl.getValue(optProxyUsername) != null) {
+                builder.proxyUsername(cl.getValue(optProxyUsername).toString());
+            }
+            if (cl.getValue(optProxyPassword) != null) {
+                builder.proxyPassword(cl.getValue(optProxyPassword).toString());
+            }
+        }
+        Map<String, String> options = builder.build().toServiceFactoryParameters();
+        for (Map.Entry<String, String> entry : options.entrySet()) {
+            setProperty(entry.getKey(), entry.getValue());
+        }
     }
 
+
     private static class PasswordPromptingCredentialsStore implements CredentialsStore {
 
         private CredentialsStore base;
diff --git a/vault-cli/src/main/java/org/apache/jackrabbit/vault/util/console/AbstractApplication.java b/vault-cli/src/main/java/org/apache/jackrabbit/vault/util/console/AbstractApplication.java
index f722911..894e4e1 100644
--- a/vault-cli/src/main/java/org/apache/jackrabbit/vault/util/console/AbstractApplication.java
+++ b/vault-cli/src/main/java/org/apache/jackrabbit/vault/util/console/AbstractApplication.java
@@ -79,7 +79,7 @@ public abstract class AbstractApplication {
     }
     
     public String getCopyrightLine() {
-        return "Copyright 2013 by Apache Software Foundation. See LICENSE.txt for more information.";
+        return "copyright 2013-2020 by Apache Software Foundation. See LICENSE.txt for more information.";
     }
     
     public String getVersionString() {
diff --git a/vault-core/pom.xml b/vault-core/pom.xml
index fe1c6e9..ae494b0 100644
--- a/vault-core/pom.xml
+++ b/vault-core/pom.xml
@@ -115,6 +115,11 @@
             <artifactId>jackrabbit-spi</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-spi2dav</artifactId>
+            <scope>provided</scope>
+        </dependency>
 
         <!-- JCR Stuff -->
         <dependency>
@@ -227,6 +232,12 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.derby</groupId>
+            <artifactId>derby</artifactId>
+            <version>10.14.2.0</version><!-- version used in jackrabbit-core -->
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.jackrabbit</groupId>
             <artifactId>oak-core</artifactId>
             <version>${oak.version}</version>
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/RepositoryFactory.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/RepositoryFactory.java
index c72a2cd..a95d36e 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/RepositoryFactory.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/RepositoryFactory.java
@@ -22,13 +22,20 @@ import java.util.Set;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
+import org.osgi.annotation.versioning.ProviderType;
+
 /**
  * {@code RepositoryProvider}...
  */
+@ProviderType
 public interface RepositoryFactory {
 
     public Set<String> getSupportedSchemes();
 
     public Repository createRepository(RepositoryAddress address)
             throws RepositoryException;
+    
+    public Repository createRepository(RepositoryAddress address, ConnectionOptions options)
+            throws RepositoryException;
 }
\ No newline at end of file
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java
index b841557..3995610 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-@Version("2.7.0")
+@Version("2.8.0")
 package org.apache.jackrabbit.vault.fs.api;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/RepositoryProvider.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/RepositoryProvider.java
index 6b37f04..7da3279 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/RepositoryProvider.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/RepositoryProvider.java
@@ -29,6 +29,7 @@ import java.util.Set;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
 import org.apache.jackrabbit.vault.fs.api.RepositoryFactory;
 import org.slf4j.Logger;
@@ -44,17 +45,21 @@ public class RepositoryProvider {
 
     private Map<RepositoryAddress, Repository> repos = new HashMap<RepositoryAddress, Repository>();
 
-    public Repository getRepository(RepositoryAddress address)
+    public Repository getRepository(RepositoryAddress address) throws RepositoryException {
+        return getRepository(address, null);
+    }
+
+    public Repository getRepository(RepositoryAddress address, ConnectionOptions options)
             throws RepositoryException {
         Repository rep = repos.get(address);
         if (rep == null) {
-            rep = createRepository(address);
+            rep = createRepository(address, options);
             repos.put(address, rep);
         }
         return rep;
     }
 
-    private Repository createRepository(RepositoryAddress address)
+    private Repository createRepository(RepositoryAddress address, ConnectionOptions options)
             throws RepositoryException {
         ServiceLoader<RepositoryFactory> loader = ServiceLoader.load(RepositoryFactory.class);
         Iterator<RepositoryFactory> iter = loader.iterator();
@@ -62,7 +67,7 @@ public class RepositoryProvider {
         while (iter.hasNext()) {
             RepositoryFactory fac = iter.next();
             supported.addAll(fac.getSupportedSchemes());
-            Repository rep = fac.createRepository(address);
+            Repository rep = fac.createRepository(address, options);
             if (rep != null) {
                 // wrap JCR logger
                 if (Boolean.getBoolean("jcrlog.sysout") || System.getProperty("jcrlog.file") != null) {
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/package-info.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/package-info.java
index 116eabc..feea434 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/package-info.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/package-info.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-@Version("2.5.0")
+@Version("2.6.0")
 package org.apache.jackrabbit.vault.util;
 
 import org.osgi.annotation.versioning.Version;
\ No newline at end of file
diff --git a/vault-davex/src/main/java/org/apache/jackrabbit/vault/davex/DAVExRepositoryFactory.java b/vault-davex/src/main/java/org/apache/jackrabbit/vault/davex/DAVExRepositoryFactory.java
index 458966d..ef38054 100644
--- a/vault-davex/src/main/java/org/apache/jackrabbit/vault/davex/DAVExRepositoryFactory.java
+++ b/vault-davex/src/main/java/org/apache/jackrabbit/vault/davex/DAVExRepositoryFactory.java
@@ -36,6 +36,7 @@ import org.apache.jackrabbit.jcr2spi.Jcr2spiRepositoryFactory;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
 import org.apache.jackrabbit.spi.commons.logging.WriterLogWriterProvider;
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
 import org.apache.jackrabbit.spi2davex.BatchReadConfig;
 import org.apache.jackrabbit.spi2davex.Spi2davexRepositoryServiceFactory;
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
@@ -67,8 +68,12 @@ public class DAVExRepositoryFactory implements RepositoryFactory {
         return SCHEMES;
     }
 
-    public Repository createRepository(RepositoryAddress address)
-            throws RepositoryException {
+    @Override
+    public Repository createRepository(RepositoryAddress address) throws RepositoryException {
+        return createRepository(address, null);
+    }
+
+    public Repository createRepository(RepositoryAddress address, ConnectionOptions connectionOptions) throws RepositoryException {
         if (!SCHEMES.contains(address.getSpecificURI().getScheme())) {
             return null;
         }
@@ -106,6 +111,9 @@ public class DAVExRepositoryFactory implements RepositoryFactory {
             if (workspace != null) {
                 parameters.put(Spi2davexRepositoryServiceFactory.PARAM_WORKSPACE_NAME_DEFAULT, workspace);
             }
+            if (connectionOptions != null) {
+                parameters.putAll(connectionOptions.toServiceFactoryParameters());
+            }
             System.out.printf("Connecting via JCR remoting to %s%n", address.getSpecificURI().toString());
             return new RepositoryFactoryImpl().getRepository(parameters);
         } catch (IOException e) {
diff --git a/vault-doc/src/site/markdown/rcp.md b/vault-doc/src/site/markdown/rcp.md
index 7def6f6..844abb3 100644
--- a/vault-doc/src/site/markdown/rcp.md
+++ b/vault-doc/src/site/markdown/rcp.md
@@ -60,15 +60,9 @@ example this regexp `\p{ASCII}*([^\p{ASCII}]\p{ASCII}*)+` excludes all paths con
 
 ### HTTP Proxy
 
-HTTP Proxy can be enabled using the default Java proxy settings, as per
+HTTP Proxy can be enabled using the system properties outlined at [Java proxy settings](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html).
 
-https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
-
-and
-
-https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/HttpClientBuilder.html#useSystemProperties()
-
-The system property is `jackrabbit.client.useSystemProperties` and needs to be set to `true`.
+For this to work in addition the system property `jackrabbit.client.useSystemProperties` needs to be set to `true`.
 
 #### Example:
 
@@ -149,7 +143,17 @@ Creates a new task.
 | resumeFrom   | \- | Source path to resume a prior aborted copy. Note that the algorithm simply skips all source nodes until the _resumeFrom_ path is found. It is necessary that the content structure of the source repository does not change in between runs, and that content already needs to be present in the detination location. |
 | excludes     | \- | Array of java regular expressions that exclude source paths. |
 | filter       | \- | Serialized [filter.xml](filter.html) specifing which repository areas to copy. Only used if `excludes` is not given. Make sure that the value is properly escaped. |
-
+| allowSelfSignedCertificate | \- | **true** to accept self-signed certificated. Only applicable if src URI starts with https. |
+| disableHostnameVerification | \- | **true** to disable host name verification against the certificate. Only applicable if src URI starts with https. |
+| connectionTimeoutMs | \- | The connection timeout in milliseconds. 0 for infinite, -1 for system default. |
+| requestTimeoutMs | \- | The request timeout in milliseconds. 0 for infinite, -1 for system default. |
+| socketTimeoutMs | \- | The socket timeout in milliseconds. 0 for infinite, -1 for system default. |
+| useSystemProperties | \- | **true** to use the java default system properties for connection settings. Further information at <https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/HttpClientBuilder.html> |
+| proxyHost | \- | The host name of the proxy to use. |
+| proxyPort | \- | The port of the proxy to use. Only applicable if `proxyHost` is set. |
+| proxyProtocol | \- | The protocol for which to use the proxy. Only applicable if `proxyHost` is set. Default (not set) means proxy is used for both HTTP and HTTPs. |
+| proxyUsername | \- | The username used for authentication at the proxy. Only applicable if `proxyHost` is set. |
+| proxyPassword | \- | The password used for authentication at the proxy. Only applicable if `proxyUsername ` is set. |
 
 ##### Example
     POST /system/jackrabbit/filevault/rcp HTTP/1.1
@@ -181,7 +185,7 @@ Creates a new task.
         "id": "test-id-1234"
     }
 #### Edit Task (POST)
-Edits an existing task. Almost al properties are optional. Unset properties are not modified!
+Edits an existing task. Almost al properties are optional. Unused properties are not modified!
 
 | Property     | Required | Comment |
 | ------------ | -------- | ------- |
@@ -198,6 +202,17 @@ Edits an existing task. Almost al properties are optional. Unset properties are
 | resumeFrom   | \- | Source path to resume a prior aborted copy. Note that the algorithm simply skips all source nodes until the _resumeFrom_ path is found. It is necessary that the content structure of the source repository does not change in between runs, and that content already needs to be present in the detination location. |
 | excludes     | \- | Array of java regular expressions that exclude source paths. |
 | filter       | \- | Serialized [filter.xml](filter.html) specifing which repository areas to copy. Only used if `excludes` is not given. Make sure that the value is properly escaped. |
+| allowSelfSignedCertificate | \- | **true** to accept self-signed certificated. Only applicable if src URI starts with https. |
+| disableHostnameVerification | \- | **true** to disable host name verification against the certificate. Only applicable if src URI starts with https. |
+| connectionTimeoutMs | \- | The connection timeout in milliseconds. 0 for infinite, -1 for system default. |
+| requestTimeoutMs | \- | The request timeout in milliseconds. 0 for infinite, -1 for system default. |
+| socketTimeoutMs | \- | The socket timeout in milliseconds. 0 for infinite, -1 for system default. |
+| useSystemProperties | \- | **true** to use the java default system properties for connection settings. Further information at <https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/client/HttpClientBuilder.html> |
+| proxyHost | \- | The host name of the proxy to use. |
+| proxyPort | \- | The port of the proxy to use. Only applicable if `proxyHost` is set. |
+| proxyProtocol | \- | The protocol for which to use the proxy. Only applicable if `proxyHost` is set. Default (not set) means proxy is used for both HTTP and HTTPs. |
+| proxyUsername | \- | The username used for authentication at the proxy. Only applicable if `proxyHost` is set. |
+| proxyPassword | \- | The password used for authentication at the proxy. Only applicable if `proxyUsername ` is set. |
 
 
 ##### Example
diff --git a/vault-doc/src/site/markdown/usage.md b/vault-doc/src/site/markdown/usage.md
index 65dcbb5..1b3aefa 100644
--- a/vault-doc/src/site/markdown/usage.md
+++ b/vault-doc/src/site/markdown/usage.md
@@ -27,49 +27,60 @@ Vault Console Tool
 ------------------
 The console tool is called `vlt` and has the following usage:
 
-    $vlt --help
+	$vlt --help
     
-    ----------------------------------------------------------------------------------------------
-    Jackrabbit FileVault [version 3.2.2] Copyright 2018 by Apache Software Foundation.
-    See LICENSE.txt for more information.
-    ----------------------------------------------------------------------------------------------
-    Usage:
-      vlt [options] <command> [arg1 [arg2 [arg3] ..]]
-    ----------------------------------------------------------------------------------------------
-    
-    Global options:
-      -Xjcrlog <arg>           Extended JcrLog options (omit argument for help)
-      -Xdavex <arg>            Extended JCR remoting options (omit argument for help)
-      --credentials <arg>      The default credentials to use
-      --update-credentials     if present the credentials-to-host list is updated in the
-                               ~/.vault/auth.xml
-      --config <arg>           The JcrFs config to use
-      -v (--verbose)           verbose output
-      -q (--quiet)             print as little as possible
-      --version                print the version information and exit
-      --log-level <level>      the log4j log level
-      -h (--help) <command>    print this help
-    Commands:
-      export                   Export the Vault filesystem
-      import                   Import a Vault filesystem
-      checkout (co)            Checkout a Vault file system
-      status (st)              Print the status of working copy files and directories.
-      update (up)              Bring changes from the repository into the working copy.
-      info                     Displays information about a local file.
-      commit (ci)              Send changes from your working copy to the repository.
-      revert (rev)             Restore pristine working copy file (undo most local edits).
-      resolved (res)           Remove 'conflicted' state on working copy files or directories.
-      propget (pg)             Print the value of a property on files or directories.
-      proplist (pl)            Print the properties on files or directories.
-      propset (ps)             Set the value of a property on files or directories.
-      add                      Put files and directories under version control.
-      delete (del,rm)          Remove files and directories from version control.
-      diff (di)                Display the differences between two paths.
-      rcp                      Remote copy of repository content.
-      sync                     Control vault sync service
-      format                   Formats vault docview files.
-      console                  Run an interactive console
-    ----------------------------------------------------------------------------------------------
+	----------------------------------------------------------------------------------------------------------------------------------
+	Jackrabbit FileVault [version 3.4.5] copyright 2013-2020 by Apache Software Foundation. See LICENSE.txt for more information.
+	----------------------------------------------------------------------------------------------------------------------------------
+	Usage:
+	  vlt [options] <command> [arg1 [arg2 [arg3] ..]]
+	----------------------------------------------------------------------------------------------------------------------------------
+	
+	Global options:
+	  -Xjcrlog <arg>                   Extended JcrLog options (omit argument for help)
+	  -Xdavex <arg>                    Extended JCR remoting options (omit argument for help)
+	  --credentials <arg>              The default credentials to use
+	  --update-credentials             if present the credentials-to-host list is updated in the ~/.vault/auth.xml
+	  --config <arg>                   The JcrFs config to use
+	  --useSystemProperties            Evaluating the default Java system properties for connection settings.
+	  --allowSelfSignedCertificates    Allows to connect to HTTPS repository urls whose certificate is self-signed.
+	  --disableHostnameValidator       Disables hostname validation for HTTPS repository urls.
+	  --connectionTimeoutMs <arg>      The connection timeout in milliseconds.
+	  --requestTimeoutMs <arg>         The request timeout in milliseconds.
+	  --socketTimeoutMs <arg>          The socket timeout in milliseconds.
+	  --proxyHost <arg>                The host of the proxy to use.
+	  --proxyPort <arg>                The port where the proxy is running (requires proxyHost as well).
+	  --proxyProtocol <arg>            The protocol for which to use the proxy (requires proxyHost as well). If not set proxy is used
+	                                   for both HTTP and HTTPS.
+	  --proxyUsername <arg>            The username to use for authentication at the proxy (requires proxyHost as well).
+	  --proxyPassword <arg>            The password to use for authentication at the proxy (requires proxyUsername as well)
+	  -v (--verbose)                   verbose output
+	  -q (--quiet)                     print as little as possible
+	  --version                        print the version information and exit
+	  --log-level <level>              the log4j log level
+	  -h (--help) <command>            print this help
+	Commands:
+	  export                           Export the Vault filesystem
+	  import                           Import a Vault filesystem
+	  checkout (co)                    Checkout a Vault file system
+	  status (st)                      Print the status of working copy files and directories.
+	  update (up)                      Bring changes from the repository into the working copy.
+	  info                             Displays information about a local file.
+	  commit (ci)                      Send changes from your working copy to the repository.
+	  revert (rev)                     Restore pristine working copy file (undo most local edits).
+	  resolved (res)                   Remove 'conflicted' state on working copy files or directories.
+	  propget (pg)                     Print the value of a property on files or directories.
+	  proplist (pl)                    Print the properties on files or directories.
+	  propset (ps)                     Set the value of a property on files or directories.
+	  add                              Put files and directories under version control.
+	  delete (del,rm)                  Remove files and directories from version control.
+	  diff (di)                        Display the differences between two paths.
+	  rcp                              Remote copy of repository content.
+	  sync                             Control vault sync service
+	  format                           Formats vault docview files.
+	  console                          Run an interactive console
+	----------------------------------------------------------------------------------------------------------------------------------
+
 
 Checkout
 --------
diff --git a/vault-rcp/bnd.bnd b/vault-rcp/bnd.bnd
index d8fbac4..3dd73ce 100644
--- a/vault-rcp/bnd.bnd
+++ b/vault-rcp/bnd.bnd
@@ -12,10 +12,13 @@
 #  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.
-
-# due to the non-backwards compatible change https://issues.apache.org/jira/browse/JCR-4067 make compatible also with newer versions
-Import-Package: org.apache.jackrabbit.webdav.client.methods;version="[1.1,3)", *
 -includeresource: @vault-davex-[0-9.]*(-SNAPSHOT)?.jar,\
-                  @jackrabbit-spi2dav-[0-9.]*.jar,\
-                  @jackrabbit-jcr-client-[0-9.]*.jar,\
-                  @jackrabbit-jcr2spi-[0-9.]*.jar
\ No newline at end of file
+                  @jackrabbit-webdav-[0-9.]*(-SNAPSHOT)?.jar,\
+                  @jackrabbit-spi-[0-9.]*(-SNAPSHOT)?.jar,\
+                  @jackrabbit-spi-commons-[0-9.]*(-SNAPSHOT)?.jar,\
+                  @jackrabbit-spi2dav-[0-9.]*(-SNAPSHOT)?.jar,\
+                  @jackrabbit-jcr-client-[0-9.]*(-SNAPSHOT)?.jar,\
+                  @jackrabbit-jcr2spi-[0-9.]*(-SNAPSHOT)?.jar
+-conditionalpackage: org.apache.jackrabbit.util,org.apache.jackrabbit.api.security
+# make sure to only export the relevant packages (https://github.com/bndtools/bnd/issues/4219)
+-exportcontents: org.apache.jackrabbit.vault.rcp
\ No newline at end of file
diff --git a/vault-rcp/pom.xml b/vault-rcp/pom.xml
index 1e1d8ae..6019e64 100644
--- a/vault-rcp/pom.xml
+++ b/vault-rcp/pom.xml
@@ -35,8 +35,6 @@
     <description>OSGi bundle containing the Jackrabbit FileVault RCP Manager used for copying (parts of) a remote repository to the local one</description>
 
     <properties>
-        <!-- downgrade dependencies to make compatible with the minimum supported version -->
-        <jackrabbit.version>2.14.0</jackrabbit.version>
         <!-- http://maven.apache.org/ref/3.6.3/maven-model-builder/index.html#Inheritance_Assembly -->
         <project.directory>vault-rcp</project.directory>
     </properties>
@@ -180,7 +178,7 @@
             <scope>provided</scope>
         </dependency>
 
-        <!-- the following dependencies are no bundles and therefore must be embedded -->
+        <!-- include all relevant parts to be installable also on older distributions (having older Jackrabbit bundles) -->
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
             <artifactId>jackrabbit-jcr2spi</artifactId>
@@ -193,10 +191,25 @@
         </dependency>
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-spi</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-spi-commons</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
             <artifactId>jackrabbit-spi2dav</artifactId>
             <scope>compile</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.jackrabbit</groupId>
+            <artifactId>jackrabbit-webdav</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.jackrabbit.vault</groupId>
             <artifactId>vault-davex</artifactId>
             <version>${project.version}</version>
diff --git a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/RcpTask.java b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/RcpTask.java
index 6e9b516..399378c 100644
--- a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/RcpTask.java
+++ b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/RcpTask.java
@@ -21,6 +21,7 @@ import java.util.List;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
 import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
 import org.apache.jackrabbit.vault.util.RepositoryCopier;
@@ -68,4 +69,6 @@ public interface RcpTask {
      */
     WorkspaceFilter getFilter();
 
+    ConnectionOptions getConnectionOptions();
+
 }
\ No newline at end of file
diff --git a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/RcpTaskManager.java b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/RcpTaskManager.java
index e17853c..c6ce102 100644
--- a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/RcpTaskManager.java
+++ b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/RcpTaskManager.java
@@ -21,6 +21,7 @@ import java.util.Map;
 
 import javax.jcr.Credentials;
 
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
 import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
 import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
@@ -38,14 +39,14 @@ public interface RcpTaskManager {
 
     boolean removeTask(String taskId);
 
-    RcpTask addTask(RepositoryAddress src, Credentials srcCreds, String dst, String id, WorkspaceFilter srcFilter, @Nullable Boolean recursive);
+    RcpTask addTask(RepositoryAddress src, ConnectionOptions connectionOptions, Credentials srcCreds, String dst, String id, WorkspaceFilter srcFilter, @Nullable Boolean recursive);
 
-    RcpTask addTask(RepositoryAddress src, Credentials srcCreds, String dst, String id, List<String> excludes, @Nullable Boolean recursive)
+    RcpTask addTask(RepositoryAddress src, ConnectionOptions connectionOptions, Credentials srcCreds, String dst, String id, List<String> excludes, @Nullable Boolean recursive)
             throws ConfigurationException;
 
     void setSourceCredentials(@NotNull String taskId, Credentials srcCreds);
 
-    RcpTask editTask(@NotNull String taskId, @Nullable RepositoryAddress src, @Nullable Credentials srcCreds, @Nullable String dst,
+    RcpTask editTask(@NotNull String taskId, @Nullable RepositoryAddress src, @Nullable ConnectionOptions connectionOptions, @Nullable Credentials srcCreds, @Nullable String dst,
             @Nullable List<String> excludes, @Nullable WorkspaceFilter srcFilter, @Nullable Boolean recursive)
             throws ConfigurationException;
 
diff --git a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/ConnectionOptionsMixin.java b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/ConnectionOptionsMixin.java
new file mode 100644
index 0000000..2d8c875
--- /dev/null
+++ b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/ConnectionOptionsMixin.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.vault.rcp.impl;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+// Don't call any functions when serializing or deserializing.
+// Only look at the class variables of any visibility (including private)
+@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE,
+        isGetterVisibility = JsonAutoDetect.Visibility.NONE,
+        setterVisibility = JsonAutoDetect.Visibility.NONE,
+        creatorVisibility = JsonAutoDetect.Visibility.NONE,
+        fieldVisibility = JsonAutoDetect.Visibility.ANY)
+public abstract class ConnectionOptionsMixin {
+    @JsonCreator
+    public ConnectionOptionsMixin(
+            @JsonProperty("useSystemProperties")boolean isUseSystemPropertes, 
+            @JsonProperty("maxConnections")int maxConnections, 
+            @JsonProperty("allowSelfSignedCertificates")boolean isAllowSelfSignedCertificates, 
+            @JsonProperty("disableHostnameVerification") boolean isDisableHostnameVerification, 
+            @JsonProperty("connectionTimeoutMs") int connectionTimeoutMs, 
+            @JsonProperty("requestTimeoutMs") int requestTimeoutMs, 
+            @JsonProperty("socketTimeoutMs") int socketTimeoutMs, 
+            @JsonProperty("proxyHost") String proxyHost, 
+            @JsonProperty("proxyPort") int proxyPort, 
+            @JsonProperty("proxyProtocol") String proxyProtocol, 
+            @JsonProperty("proxyUsername") String proxyUsername, 
+            @JsonProperty("proxyPassword") String proxyPassword) {}
+}
diff --git a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpServlet.java b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpServlet.java
index ec3b738..4a64d88 100644
--- a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpServlet.java
+++ b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpServlet.java
@@ -31,6 +31,7 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
 import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
 import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
@@ -75,6 +76,19 @@ public class RcpServlet extends SlingAllMethodsServlet {
     public static final String PARAM_EXCLUDES = "excludes";
     public static final String PARAM_RESUME_FROM = "resumeFrom";
     public static final String PARAM_FILTER = "filter";
+    // connection options
+    public static final String PARAM_ALLOW_SELF_SIGNED_CERTIFICATE = "allowSelfSignedCertificate";
+    public static final String PARAM_DISABLE_HOSTNAME_VERIFICATION = "disableHostnameVerification";
+    public static final String PARAM_CONNECTION_TIMEOUT_MS = "connectionTimeoutMs";
+    public static final String PARAM_REQUEST_TIMEOUT_MS = "requestTimeoutMs";
+    public static final String PARAM_SOCKET_TIMEOUT_MS = "socketTimeoutMs";
+    public static final String PARAM_USE_SYSTEM_PROPERTIES = "useSystemProperties";
+    public static final String PARAM_PROXY_HOST = "proxyHost";
+    public static final String PARAM_PROXY_PORT = "proxyPort";
+    public static final String PARAM_PROXY_PROTOCOL = "proxyProtocol";
+    public static final String PARAM_PROXY_USERNAME = "proxyUsername";
+    public static final String PARAM_PROXY_PASSWORD = "proxyPassword";
+    
 
     /**
      * default logger
@@ -138,8 +152,8 @@ public class RcpServlet extends SlingAllMethodsServlet {
         final String id = data.optString(PARAM_ID, null);;
         try {
             // --------------------------------------------------------------------------------------------< create >---
-            if ("create".equals(cmd) || "edit".equals(cmd)) {
-                boolean isEdit = "edit".equals(cmd);
+            boolean isEdit = "edit".equals(cmd);
+            if (isEdit || "create".equals(cmd)) {
                 if (isEdit) {
                     if (id == null || id.length() == 0) {
                         throw new IllegalArgumentException("Need task id.");
@@ -168,6 +182,33 @@ public class RcpServlet extends SlingAllMethodsServlet {
                 if (data.has(PARAM_RECURSIVE)) {
                     recursive = data.optBoolean(PARAM_RECURSIVE, false);
                 }
+
+                ConnectionOptions.Builder connectionOptionsBuilder = ConnectionOptions.builder();
+                connectionOptionsBuilder.useSystemProperties(data.optBoolean(PARAM_USE_SYSTEM_PROPERTIES));
+                connectionOptionsBuilder.allowSelfSignedCertificates(data.optBoolean(PARAM_ALLOW_SELF_SIGNED_CERTIFICATE));
+                connectionOptionsBuilder.disableHostnameVerification(data.optBoolean(PARAM_DISABLE_HOSTNAME_VERIFICATION));
+                int connectionTimeoutMs = data.optInt(PARAM_CONNECTION_TIMEOUT_MS, -1);
+                connectionOptionsBuilder.connectionTimeoutMs(connectionTimeoutMs);
+                int requestTimeoutMs = data.optInt(PARAM_REQUEST_TIMEOUT_MS, -1);
+                connectionOptionsBuilder.requestTimeoutMs(requestTimeoutMs);
+                int socketTimeoutMs = data.optInt(PARAM_SOCKET_TIMEOUT_MS, -1);
+                connectionOptionsBuilder.socketTimeoutMs(socketTimeoutMs);
+
+                if (data.has(PARAM_PROXY_HOST)) {
+                    connectionOptionsBuilder.proxyHost(data.getString(PARAM_PROXY_HOST));
+                    if (data.has(PARAM_PROXY_PORT)) {
+                        connectionOptionsBuilder.proxyPort(data.getInt(PARAM_PROXY_PORT));
+                    }
+                    if (data.has(PARAM_PROXY_PROTOCOL)) {
+                        connectionOptionsBuilder.proxyProtocol(data.getString(PARAM_PROXY_PROTOCOL));
+                    }
+                    if (data.has(PARAM_PROXY_USERNAME)) {
+                        connectionOptionsBuilder.proxyUsername(data.getString(PARAM_PROXY_USERNAME));
+                        if (data.has(PARAM_PROXY_PASSWORD)) {
+                            connectionOptionsBuilder.proxyPassword(data.getString(PARAM_PROXY_PASSWORD));
+                        }
+                    }
+                }
                 if (data.has(PARAM_EXCLUDES)) {
                     List<String> excludeList = new LinkedList<>();
                     JSONArray excludes = data.getJSONArray(PARAM_EXCLUDES);
@@ -175,9 +216,9 @@ public class RcpServlet extends SlingAllMethodsServlet {
                         excludeList.add(excludes.getString(idx));
                     }
                     if (isEdit) {
-                        task = taskMgr.editTask(id, address, creds, dst, excludeList, null, recursive);
+                        task = taskMgr.editTask(id, address, connectionOptionsBuilder.build(), creds, dst, excludeList, null, recursive);
                     } else {
-                        task = taskMgr.addTask(address, creds, dst, id, excludeList, recursive);
+                        task = taskMgr.addTask(address, connectionOptionsBuilder.build(), creds, dst, id, excludeList, recursive);
                     }
                 } else {
                     final WorkspaceFilter filter;
@@ -189,9 +230,9 @@ public class RcpServlet extends SlingAllMethodsServlet {
                         filter = null;
                     }
                     if (isEdit) {
-                        task = taskMgr.editTask(id, address, creds, dst, null, filter, recursive);
+                        task = taskMgr.editTask(id, address, connectionOptionsBuilder.build(), creds, dst, null, filter, recursive);
                     } else {
-                        task = taskMgr.addTask(address, creds, dst, id, filter, recursive);
+                        task = taskMgr.addTask(address, connectionOptionsBuilder.build(), creds, dst, id, filter, recursive);
                     }
                 }
 
@@ -335,6 +376,22 @@ public class RcpServlet extends SlingAllMethodsServlet {
                 w.key(RcpServlet.PARAM_FILTER).value(rcpTask.getFilter().getSourceAsString());
             }
         }
+        w.key(PARAM_USE_SYSTEM_PROPERTIES).value(rcpTask.getConnectionOptions().isUseSystemPropertes());
+        w.key(PARAM_DISABLE_HOSTNAME_VERIFICATION).value(rcpTask.getConnectionOptions().isDisableHostnameVerification());
+        w.key(PARAM_ALLOW_SELF_SIGNED_CERTIFICATE).value(rcpTask.getConnectionOptions().isAllowSelfSignedCertificates());
+        w.key(PARAM_CONNECTION_TIMEOUT_MS).value(rcpTask.getConnectionOptions().getConnectionTimeoutMs());
+        w.key(PARAM_REQUEST_TIMEOUT_MS).value(rcpTask.getConnectionOptions().getRequestTimeoutMs());
+        w.key(PARAM_SOCKET_TIMEOUT_MS).value(rcpTask.getConnectionOptions().getSocketTimeoutMs());
+        if (rcpTask.getConnectionOptions().getProxyHost() != null) {
+            w.key(PARAM_PROXY_HOST).value(rcpTask.getConnectionOptions().getProxyHost());
+            w.key(PARAM_PROXY_PORT).value(rcpTask.getConnectionOptions().getProxyPort());
+            if (rcpTask.getConnectionOptions().getProxyProtocol() != null) {
+                w.key(PARAM_PROXY_HOST).value(rcpTask.getConnectionOptions().getProxyProtocol());
+            }
+            if (rcpTask.getConnectionOptions().getProxyUsername() != null) {
+                w.key(PARAM_PROXY_USERNAME).value(rcpTask.getConnectionOptions().getProxyUsername());
+            }
+        }
         w.key("status").object();
         w.key(RcpServlet.PARAM_STATE).value(rcpTask.getResult().getState().name());
         w.key("currentPath").value(rcpTask.getRcp().getCurrentPath());
diff --git a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskImpl.java b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskImpl.java
index 147d6df..64b4ba1 100644
--- a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskImpl.java
+++ b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskImpl.java
@@ -26,6 +26,7 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
 import org.apache.jackrabbit.vault.davex.DAVExRepositoryFactory;
 import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
 import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
@@ -85,6 +86,8 @@ public class RcpTaskImpl implements Runnable, RcpTask {
 
     WorkspaceFilter filter;
 
+    private final ConnectionOptions connectionOptions;
+
     private static final class ResultImpl implements RcpTask.Result {
 
         private final State state;
@@ -111,14 +114,14 @@ public class RcpTaskImpl implements Runnable, RcpTask {
         }
     }
 
-    public RcpTaskImpl(ClassLoader classLoader, RepositoryAddress src, Credentials srcCreds, String dst, String id, List<String> excludes,
+    public RcpTaskImpl(ClassLoader classLoader, RepositoryAddress src, ConnectionOptions connectionOptions, Credentials srcCreds, String dst, String id, List<String> excludes,
             @Nullable Boolean recursive) throws ConfigurationException {
-        this(classLoader, src, srcCreds, dst, id, createFilterForExcludes(excludes), recursive);
+        this(classLoader, src, connectionOptions, srcCreds, dst, id, createFilterForExcludes(excludes), recursive);
         this.excludes = excludes;
     }
 
     @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
-    public RcpTaskImpl(@JsonProperty("classLoader") ClassLoader dynLoader, @JsonProperty("source") RepositoryAddress src, @JsonProperty("srcCreds") Credentials srcCreds, @JsonProperty("destination") String dst, @JsonProperty("id") String id, @JsonProperty("filter") WorkspaceFilter srcFilter,
+    public RcpTaskImpl(@JsonProperty("classLoader") ClassLoader dynLoader, @JsonProperty("source") RepositoryAddress src, @JsonProperty("connectionOptions") ConnectionOptions connectionOptions, @JsonProperty("srcCreds") Credentials srcCreds, @JsonProperty("destination") String dst, @JsonProperty("id") String id, @JsonProperty("filter") WorkspaceFilter srcFilter,
             @JsonProperty("recursive") @Nullable Boolean recursive) {
         this.src = src;
         this.dst = dst;
@@ -130,12 +133,14 @@ public class RcpTaskImpl implements Runnable, RcpTask {
         this.filter = srcFilter;
         initTransientData();
         this.classLoader = dynLoader;
+        this.connectionOptions = connectionOptions;
     }
 
     // additional constructor for editing existing tasks, all arguments are optional except the first one
-    public RcpTaskImpl(@NotNull RcpTaskImpl oldTask, @Nullable RepositoryAddress src, @Nullable Credentials srcCreds, @Nullable String dst, @Nullable List<String> excludes, @Nullable WorkspaceFilter srcFilter,
+    public RcpTaskImpl(@NotNull RcpTaskImpl oldTask, @Nullable RepositoryAddress src, @Nullable ConnectionOptions connectionOptions, @Nullable Credentials srcCreds, @Nullable String dst, @Nullable List<String> excludes, @Nullable WorkspaceFilter srcFilter,
             @Nullable Boolean recursive) {
         this.src = src != null ? src : oldTask.src;
+        this.connectionOptions = connectionOptions != null ? connectionOptions : oldTask.connectionOptions;
         this.dst = dst != null ? dst : oldTask.dst;
         this.srcCreds = srcCreds != null ? srcCreds : oldTask.srcCreds;
         this.id = oldTask.id;
@@ -225,7 +230,7 @@ public class RcpTaskImpl implements Runnable, RcpTask {
 
     @Override
     public boolean start(Session session) throws RepositoryException {
-        if (result.getState() != Result.State.NEW) {
+        if (result.getState() == Result.State.RUNNING || result.getState() == Result.State.STOPPING) {
             throw new IllegalStateException("Unable to start task " + id + ". wrong state = " + result.getState());
         }
         // clone session
@@ -248,7 +253,7 @@ public class RcpTaskImpl implements Runnable, RcpTask {
         DAVExRepositoryFactory factory = new DAVExRepositoryFactory();
         Repository srcRepo;
         try {
-            srcRepo = factory.createRepository(src);
+            srcRepo = factory.createRepository(src, connectionOptions);
         } catch (RepositoryException e) {
             log.error("Error while retrieving src repository {}: {}", src, e.toString());
             throw e;
@@ -275,6 +280,7 @@ public class RcpTaskImpl implements Runnable, RcpTask {
             rcp.copy(srcSession, src.getPath(), dstSession, dst, recursive);
             result = new ResultImpl(Result.State.ENDED);
         } catch (Throwable e) {
+            log.error("Error while executing RCP task {}", getId(), e);
             result = new ResultImpl(Result.State.ENDED, e);
         }
         // todo: notify manager that we ended.
@@ -290,6 +296,11 @@ public class RcpTaskImpl implements Runnable, RcpTask {
         return src;
     }
 
+    @Override
+    public ConnectionOptions getConnectionOptions() {
+        return connectionOptions;
+    }
+
     Credentials getSourceCredentials() {
         return srcCreds;
     }
diff --git a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskManagerImpl.java b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskManagerImpl.java
index 117e652..0de2691 100644
--- a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskManagerImpl.java
+++ b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskManagerImpl.java
@@ -35,13 +35,13 @@ import javax.jcr.Credentials;
 import javax.jcr.RepositoryException;
 import javax.jcr.SimpleCredentials;
 
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
 import org.apache.jackrabbit.vault.fs.api.WorkspaceFilter;
 import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
 import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
 import org.apache.jackrabbit.vault.rcp.RcpTask;
 import org.apache.jackrabbit.vault.rcp.RcpTaskManager;
-import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.framework.BundleContext;
@@ -85,8 +85,6 @@ public class RcpTaskManagerImpl implements RcpTaskManager {
     /** default logger */
     private static final Logger log = LoggerFactory.getLogger(RcpTaskManagerImpl.class);
 
-    private final DynamicClassLoaderManager dynLoaderMgr;
-
     SortedMap<String, RcpTaskImpl> tasks;
 
     private final File dataFile;
@@ -99,8 +97,7 @@ public class RcpTaskManagerImpl implements RcpTaskManager {
     private String serializedTasks;
 
     @Activate
-    public RcpTaskManagerImpl(BundleContext bundleContext, @Reference DynamicClassLoaderManager dynLoaderMgr,
-            @Reference ConfigurationAdmin configurationAdmin, Map <String, Object> newConfigProperties) {
+    public RcpTaskManagerImpl(BundleContext bundleContext, @Reference ConfigurationAdmin configurationAdmin, Map <String, Object> newConfigProperties) {
         mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);
         mapper.addMixIn(RepositoryAddress.class, RepositoryAddressMixin.class);
         SimpleModule module = new SimpleModule();
@@ -108,8 +105,7 @@ public class RcpTaskManagerImpl implements RcpTaskManager {
         module.addDeserializer(WorkspaceFilter.class, new WorkspaceFilterDeserializer());
         mapper.registerModule(module);
         mapper.addMixIn(SimpleCredentials.class, SimpleCredentialsMixin.class);
-
-        this.dynLoaderMgr = dynLoaderMgr;
+        mapper.addMixIn(ConnectionOptions.class, ConnectionOptionsMixin.class);
         this.dataFile = bundleContext.getDataFile(TASKS_DATA_FILE_NAME);
         Configuration configuration;
         try {
@@ -118,6 +114,7 @@ public class RcpTaskManagerImpl implements RcpTaskManager {
         } catch (IOException e) {
             log.error("Could not restore previous tasks", e);
             configuration = null;
+            tasks = new TreeMap<>();
         }
         this.configuration = configuration;
     }
@@ -135,7 +132,7 @@ public class RcpTaskManagerImpl implements RcpTaskManager {
     void modified(Map <String, Object> newConfigProperties) throws IOException {
         // might be triggered internally or externally
         // only external events are relevant
-        if (!serializedTasks.equals(newConfigProperties.get(PROP_TASKS_SERIALIZATION))) {
+        if (serializedTasks == null || !serializedTasks.equals(newConfigProperties.get(PROP_TASKS_SERIALIZATION))) {
             log.info("Detected external properties change");
             tasks = loadTasks((String) newConfigProperties.get(PROP_TASKS_SERIALIZATION), null);
         }
@@ -174,6 +171,8 @@ public class RcpTaskManagerImpl implements RcpTaskManager {
             if (!entry.getKey().equals(entry.getValue().getId())) {
                 throw new IllegalArgumentException("Id of entry " + entry.getKey() + " does not match its task id " + entry.getValue().getId());
             }
+            // set classloader to use for retrieving the RepositoryImpl
+            entry.getValue().setClassLoader(getClassLoaderForRepositoryFactory());
         }
     }
 
@@ -243,24 +242,24 @@ public class RcpTaskManagerImpl implements RcpTaskManager {
     }
 
     @Override
-    public RcpTask addTask(RepositoryAddress src, Credentials srcCreds, String dst, String id, List<String> excludes, @Nullable Boolean recursive)
+    public RcpTask addTask(RepositoryAddress src, ConnectionOptions connectionOptions, Credentials srcCreds, String dst, String id, List<String> excludes, @Nullable Boolean recursive)
             throws ConfigurationException {
         if (id != null && id.length() > 0 && tasks.containsKey(id)) {
             throw new IllegalArgumentException("Task with id " + id + " already exists.");
         }
-        RcpTaskImpl task = new RcpTaskImpl(getDynamicClassLoader(), src, srcCreds, dst, id, excludes, recursive);
+        RcpTaskImpl task = new RcpTaskImpl(getClassLoaderForRepositoryFactory(), src, connectionOptions, srcCreds, dst, id, excludes, recursive);
         tasks.put(task.getId(), task);
         persistTasks();
         return task;
     }
 
     @Override
-    public RcpTask addTask(RepositoryAddress src, Credentials srcCreds, String dst, String id, WorkspaceFilter srcFilter,
+    public RcpTask addTask(RepositoryAddress src, ConnectionOptions connectionOptions, Credentials srcCreds, String dst, String id, WorkspaceFilter srcFilter,
             @Nullable Boolean recursive) {
         if (id != null && id.length() > 0 && tasks.containsKey(id)) {
             throw new IllegalArgumentException("Task with id " + id + " already exists.");
         }
-        RcpTaskImpl task = new RcpTaskImpl(getDynamicClassLoader(), src, srcCreds, dst, id, srcFilter, recursive);
+        RcpTaskImpl task = new RcpTaskImpl(getClassLoaderForRepositoryFactory(), src, connectionOptions, srcCreds, dst, id, srcFilter, recursive);
         tasks.put(task.getId(), task);
         persistTasks();
         return task;
@@ -268,13 +267,13 @@ public class RcpTaskManagerImpl implements RcpTaskManager {
 
     
     @Override
-    public RcpTask editTask(@NotNull String taskId, @Nullable RepositoryAddress src, @Nullable Credentials srcCreds, @Nullable String dst, @Nullable List<String> excludes,
+    public RcpTask editTask(@NotNull String taskId, @Nullable RepositoryAddress src, @Nullable ConnectionOptions connectionOptions, @Nullable Credentials srcCreds, @Nullable String dst, @Nullable List<String> excludes,
             @Nullable WorkspaceFilter srcFilter, @Nullable Boolean recursive) throws ConfigurationException {
         RcpTaskImpl oldTask = tasks.get(taskId);
         if (oldTask == null) {
             throw new IllegalArgumentException("No such task with id='" + taskId + "'");
         }
-        return new RcpTaskImpl(oldTask, src, srcCreds, dst, excludes, srcFilter, recursive);
+        return new RcpTaskImpl(oldTask, src, connectionOptions, srcCreds, dst, excludes, srcFilter, recursive);
     }
 
     @Override
@@ -298,7 +297,8 @@ public class RcpTaskManagerImpl implements RcpTaskManager {
         persistTasksCredentials();
     }
 
-    protected ClassLoader getDynamicClassLoader() {
-        return dynLoaderMgr.getDynamicClassLoader();
+    protected ClassLoader getClassLoaderForRepositoryFactory() {
+        // everything is embedded in the current bundle, therefore just take the bundle classloader
+        return this.getClass().getClassLoader();
     }
 }
\ No newline at end of file
diff --git a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/WorkspaceFilterDeserializer.java b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/WorkspaceFilterDeserializer.java
index 68d7a09..a2ac3f9 100644
--- a/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/WorkspaceFilterDeserializer.java
+++ b/vault-rcp/src/main/java/org/apache/jackrabbit/vault/rcp/impl/WorkspaceFilterDeserializer.java
@@ -30,6 +30,7 @@ import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.JsonToken;
 import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 import com.fasterxml.jackson.databind.exc.InvalidFormatException;
 
@@ -57,7 +58,7 @@ public class WorkspaceFilterDeserializer extends StdDeserializer<WorkspaceFilter
         try (InputStream input = new ByteArrayInputStream(filterXml.getBytes(StandardCharsets.UTF_8))) {
             filter.load(input);
         } catch (ConfigurationException e) {
-            throw new InvalidFormatException("Invalid filter", p.getCurrentLocation(), filterXml, DefaultWorkspaceFilter.class);
+            throw JsonMappingException.from(p, "Invalid filter", e);
         }
         p.nextToken();
         return filter;
diff --git a/vault-rcp/src/test/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskManagerImplTest.java b/vault-rcp/src/test/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskManagerImplTest.java
index 8ad6ff3..a2eb8ec 100644
--- a/vault-rcp/src/test/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskManagerImplTest.java
+++ b/vault-rcp/src/test/java/org/apache/jackrabbit/vault/rcp/impl/RcpTaskManagerImplTest.java
@@ -32,11 +32,11 @@ import javax.jcr.SimpleCredentials;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.jackrabbit.spi2dav.ConnectionOptions;
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
 import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
 import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
 import org.apache.jackrabbit.vault.rcp.RcpTask;
-import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.hamcrest.Description;
 import org.hamcrest.Matchers;
 import org.hamcrest.TypeSafeMatcher;
@@ -64,12 +64,6 @@ public class RcpTaskManagerImplTest {
     BundleContext mockBundleContext;
 
     @Mock
-    DynamicClassLoaderManager mockClassLoaderManager;
-
-    @Mock
-    ClassLoader mockClassLoader;
-
-    @Mock
     ConfigurationAdmin mockConfigurationAdmin;
 
     @Mock
@@ -91,7 +85,6 @@ public class RcpTaskManagerImplTest {
                 return new File(folder.getRoot(),name);
             }
         });
-        Mockito.when(mockClassLoaderManager.getDynamicClassLoader()).thenReturn(mockClassLoader);
         configProperties = null;
         Mockito.when(mockConfigurationAdmin.getConfiguration(Mockito.anyString())).thenReturn(mockConfiguration);
         Mockito.doAnswer(new Answer<Void>() {
@@ -102,7 +95,7 @@ public class RcpTaskManagerImplTest {
             }
             
         }).when(mockConfiguration).updateIfDifferent(Mockito.any());
-        taskManager = new RcpTaskManagerImpl(mockBundleContext, mockClassLoaderManager, mockConfigurationAdmin, Collections.emptyMap());
+        taskManager = new RcpTaskManagerImpl(mockBundleContext, mockConfigurationAdmin, Collections.emptyMap());
     }
 
     @Test 
@@ -111,12 +104,14 @@ public class RcpTaskManagerImplTest {
         try (InputStream input = this.getClass().getResourceAsStream("/filter.xml")) {
             filter.load(input);
         }
-        RcpTaskImpl taskOld = (RcpTaskImpl)taskManager.addTask(new RepositoryAddress("http://localhost:4502"), new SimpleCredentials("testUser", "pw".toCharArray()), "/target/path", "2", Arrays.asList("exclude1", "exclude2"), false);
-        RcpTaskImpl taskNew = (RcpTaskImpl)taskManager.editTask(taskOld.getId(), null, null, null, null, null, null);
+        ConnectionOptions.Builder connectionOptionsBuilder = ConnectionOptions.builder();
+        connectionOptionsBuilder.proxyHost("proxyHost");
+        RcpTaskImpl taskOld = (RcpTaskImpl)taskManager.addTask(new RepositoryAddress("http://localhost:4502"), connectionOptionsBuilder.build(), new SimpleCredentials("testUser", "pw".toCharArray()), "/target/path", "2", Arrays.asList("exclude1", "exclude2"), false);
+        RcpTaskImpl taskNew = (RcpTaskImpl)taskManager.editTask(taskOld.getId(), null, null, null, null, null, null, null);
         Assert.assertThat(taskNew, new TaskMatcher(taskOld));
         
         RepositoryAddress newSource = new RepositoryAddress("http://localhost:4503");
-        taskNew = (RcpTaskImpl)taskManager.editTask(taskOld.getId(), newSource, null, null, null, null, null);
+        taskNew = (RcpTaskImpl)taskManager.editTask(taskOld.getId(), newSource, null, null, null, null, null, null);
         Assert.assertThat(taskNew, Matchers.not(new TaskMatcher(taskOld)));
         Assert.assertEquals(newSource, taskNew.getSource());
     }
@@ -127,12 +122,16 @@ public class RcpTaskManagerImplTest {
         try (InputStream input = this.getClass().getResourceAsStream("/filter.xml")) {
             filter.load(input);
         }
-        taskManager.addTask(new RepositoryAddress("http://localhost:4502"), new SimpleCredentials("testUser", "pw".toCharArray()), "/target/path", "2", Arrays.asList("exclude1", "exclude2"), false);
-        taskManager.addTask(new RepositoryAddress("http://localhost:8080"), new SimpleCredentials("testUser3", "pw3".toCharArray()), "/target/path5", "3", filter, true);
+        ConnectionOptions.Builder connectionOptionsBuilder = ConnectionOptions.builder();
+        connectionOptionsBuilder.allowSelfSignedCertificates(true);
+        connectionOptionsBuilder.disableHostnameVerification(false);
+        connectionOptionsBuilder.socketTimeoutMs(100);
+        taskManager.addTask(new RepositoryAddress("http://localhost:4502"), connectionOptionsBuilder.build(), new SimpleCredentials("testUser", "pw".toCharArray()), "/target/path", "2", Arrays.asList("exclude1", "exclude2"), false);
+        taskManager.addTask(new RepositoryAddress("http://localhost:8080"), connectionOptionsBuilder.build(), new SimpleCredentials("testUser3", "pw3".toCharArray()), "/target/path5", "3", filter, true);
         taskManager.deactivate();
         Assert.assertNotNull("The tasks should have been persisted here but are not!", configProperties);
         // convert to Map
-        RcpTaskManagerImpl taskManager2 = new RcpTaskManagerImpl(mockBundleContext, mockClassLoaderManager, mockConfigurationAdmin, RcpTaskManagerImpl.createMapFromDictionary(configProperties));
+        RcpTaskManagerImpl taskManager2 = new RcpTaskManagerImpl(mockBundleContext, mockConfigurationAdmin, RcpTaskManagerImpl.createMapFromDictionary(configProperties));
         // how to get list ordered by id?
         Assert.assertThat(taskManager.tasks.values(), new TaskCollectionMatcher(taskManager2.tasks.values()));
     }
diff --git a/vault-sync/pom.xml b/vault-sync/pom.xml
index d4c6019..7be64b0 100644
--- a/vault-sync/pom.xml
+++ b/vault-sync/pom.xml
@@ -81,7 +81,7 @@
         <dependency>
             <groupId>org.apache.jackrabbit.vault</groupId>
             <artifactId>org.apache.jackrabbit.vault</artifactId>
-            <version>3.4.5-SNAPSHOT</version>
+            <version>3.1.38</version><!-- minimum version this bundle is compatible with -->
         </dependency>
 
         <!-- JCR Stuff -->