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 2021/06/22 12:59:54 UTC

[jackrabbit-filevault] branch master updated: JCRVLT-246 fix Sonarcloud.io blocker issues (#150)

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 601bb39  JCRVLT-246 fix Sonarcloud.io blocker issues (#150)
601bb39 is described below

commit 601bb39b7f18208060151c684cba1f549d8cc823
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Tue Jun 22 14:59:49 2021 +0200

    JCRVLT-246 fix Sonarcloud.io blocker issues (#150)
    
    * fix major bugs
    * fix blocker vulnerabilities by disabling access to external entities
    during XML parsing
    * ignore cipher-related issues
---
 .../jackrabbit/vault/cli/CmdCheckoutCli.java       |  11 +-
 .../org/apache/jackrabbit/vault/cli/CmdDump.java   |  18 ++-
 .../apache/jackrabbit/vault/cli/CmdExportCli.java  |  10 +-
 .../vault/util/console/platform/CmdLs.java         |   8 +-
 .../jackrabbit/vault/fs/PropertyValueArtifact.java |  18 ++-
 .../jackrabbit/vault/fs/VaultFileInputStream.java  |  57 +++------
 .../vault/fs/config/DefaultWorkspaceFilter.java    |  10 +-
 .../vault/fs/config/SimpleCredentialsConfig.java   |   4 +-
 .../vault/fs/impl/io/DocViewAnalyzer.java          |   5 +-
 .../vault/fs/impl/io/DocViewSAXFormatter.java      |   6 +-
 .../vault/fs/impl/io/FileArtifactHandler.java      |   3 +
 .../vault/fs/impl/io/GenericArtifactHandler.java   |   3 +
 .../jackrabbit/vault/fs/io/AbstractExporter.java   |   2 +-
 .../jackrabbit/vault/fs/io/DocViewFormat.java      |  11 +-
 .../apache/jackrabbit/vault/fs/io/JarExporter.java |  14 +-
 .../apache/jackrabbit/vault/fs/io/JcrExporter.java |   7 +-
 .../jackrabbit/vault/fs/io/PlatformExporter.java   |  26 ++--
 .../jackrabbit/vault/fs/io/ZipStreamArchive.java   |   4 +-
 .../vault/packaging/impl/JcrPackageImpl.java       | 141 +++++++++++----------
 .../packaging/impl/JcrPackageManagerImpl.java      |  14 +-
 .../registry/impl/JcrPackageRegistry.java          |  27 ++--
 .../apache/jackrabbit/vault/util/DocViewNode.java  |   7 +-
 .../jackrabbit/vault/util/InputStreamPump.java     |   5 +-
 .../jackrabbit/vault/util/LineInputStream.java     |   2 +-
 .../jackrabbit/vault/util/RepositoryCopier.java    |   3 +-
 .../org/apache/jackrabbit/vault/util/Text.java     |  39 +++---
 .../jackrabbit/vault/rcp/impl/RcpTaskImpl.java     |   1 +
 .../apache/jackrabbit/vault/sync/impl/SyncLog.java |  10 +-
 .../vault/sync/impl/VaultSyncServiceImpl.java      |   2 +
 .../spi/impl/AdvancedFilterValidator.java          |   3 +-
 .../spi/impl/AdvancedFilterValidatorFactory.java   |   6 +-
 .../apache/jackrabbit/vault/vlt/actions/Info.java  |   8 +-
 32 files changed, 251 insertions(+), 234 deletions(-)

diff --git a/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdCheckoutCli.java b/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdCheckoutCli.java
index d1246fb..69b68b2 100644
--- a/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdCheckoutCli.java
+++ b/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdCheckoutCli.java
@@ -50,6 +50,7 @@ public class CmdCheckoutCli extends AbstractVaultCommand {
     private Argument argJcrPath;
     private Argument argMountpoint;
 
+    @Override
     protected void doExecute(VaultFsConsoleExecutionContext ctx, CommandLine cl)
             throws Exception {
         throw new ExecutionException("internal error. command not supported in console");
@@ -65,19 +66,15 @@ public class CmdCheckoutCli extends AbstractVaultCommand {
         if (localPath == null) {
             localPath = jcrPath;
             jcrPath = null;
-        }
+        } 
         if (jcrPath == null) {
             jcrPath = addr.getPath();
             addr = addr.resolve("/");
         }
         if (localPath == null) {
-            if (jcrPath == null) {
-                localPath = Text.getName(addr.toString());
-            } else {
-                localPath = Text.getName(jcrPath);
-            }
+            localPath = Text.getName(jcrPath);
         }
-        if (jcrPath == null || jcrPath.length() == 0 || !jcrPath.startsWith("/")) {
+        if (jcrPath.length() == 0 || !jcrPath.startsWith("/")) {
             throw new ExecutionException("JCR path needs to be absolute: " + jcrPath);
         }
         File localFile = app.getPlatformFile(localPath, false);
diff --git a/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdDump.java b/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdDump.java
index 0d36704..4a23d40 100644
--- a/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdDump.java
+++ b/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdDump.java
@@ -18,7 +18,9 @@
 package org.apache.jackrabbit.vault.cli;
 
 import java.io.File;
+import java.io.InputStream;
 import java.io.PrintWriter;
+import java.nio.file.Files;
 
 import org.apache.commons.cli2.Argument;
 import org.apache.commons.cli2.CommandLine;
@@ -28,8 +30,6 @@ import org.apache.commons.cli2.builder.CommandBuilder;
 import org.apache.commons.cli2.builder.DefaultOptionBuilder;
 import org.apache.commons.cli2.builder.GroupBuilder;
 import org.apache.commons.cli2.option.Command;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
 import org.apache.jackrabbit.vault.fs.api.DumpContext;
 import org.apache.jackrabbit.vault.fs.api.Dumpable;
 import org.apache.jackrabbit.vault.fs.api.VaultFileSystem;
@@ -59,16 +59,14 @@ public class CmdDump extends AbstractJcrFsCommand {
                     file = ctx.getVaultFsApp().getPlatformFile(path, false);
                 }
                 if (cl.hasOption(optConfig)) {
-                    IOUtils.copy(
-                        fs.getConfig().getSource(),
-                        FileUtils.openOutputStream(file)
-                    );
+                    try (InputStream input = fs.getConfig().getSource()) {
+                        Files.copy(input, file.toPath());
+                    }
                     VaultFsApp.log.info("VaultFs config written to {}", file.getPath());
                 } else {
-                    IOUtils.copy(
-                        fs.getWorkspaceFilter().getSource(),
-                        FileUtils.openOutputStream(file)
-                    );
+                    try (InputStream input = fs.getWorkspaceFilter().getSource()) {
+                        Files.copy(input, file.toPath());
+                    }
                     VaultFsApp.log.info("VaultFs workspace filter written to {}", file.getPath());
                 }
             } else {
diff --git a/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdExportCli.java b/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdExportCli.java
index 8488015..d2f3430 100644
--- a/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdExportCli.java
+++ b/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdExportCli.java
@@ -18,8 +18,8 @@
 package org.apache.jackrabbit.vault.cli;
 
 import java.io.File;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
 
 import org.apache.commons.cli2.Argument;
 import org.apache.commons.cli2.CommandLine;
@@ -29,13 +29,13 @@ import org.apache.commons.cli2.builder.CommandBuilder;
 import org.apache.commons.cli2.builder.DefaultOptionBuilder;
 import org.apache.commons.cli2.builder.GroupBuilder;
 import org.apache.commons.cli2.option.Command;
+import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
 import org.apache.jackrabbit.vault.fs.api.VaultFile;
 import org.apache.jackrabbit.vault.fs.io.AbstractExporter;
 import org.apache.jackrabbit.vault.fs.io.JarExporter;
 import org.apache.jackrabbit.vault.fs.io.PlatformExporter;
 import org.apache.jackrabbit.vault.util.DefaultProgressListener;
-import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.vault.vlt.VltContext;
 
 /**
@@ -44,7 +44,7 @@ import org.apache.jackrabbit.vault.vlt.VltContext;
  */
 public class CmdExportCli extends AbstractVaultCommand {
 
-    static final SimpleDateFormat FMT = new SimpleDateFormat("yyyyMMddHHmmss");
+    static final DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
 
     private Option optType;
     private Option optPrune;
@@ -76,7 +76,7 @@ public class CmdExportCli extends AbstractVaultCommand {
                 localPath = Text.getName(jcrPath);
             }
             if (type.equals("jar")) {
-                localPath += "-" + FMT.format(new Date()) + ".jar";
+                localPath += "-" + FMT.format(Instant.now()) + ".jar";
             } else {
 
             }
diff --git a/vault-cli/src/main/java/org/apache/jackrabbit/vault/util/console/platform/CmdLs.java b/vault-cli/src/main/java/org/apache/jackrabbit/vault/util/console/platform/CmdLs.java
index c0ec143..40333ec 100644
--- a/vault-cli/src/main/java/org/apache/jackrabbit/vault/util/console/platform/CmdLs.java
+++ b/vault-cli/src/main/java/org/apache/jackrabbit/vault/util/console/platform/CmdLs.java
@@ -18,8 +18,8 @@ package org.apache.jackrabbit.vault.util.console.platform;
 
 import java.io.File;
 import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
 
 import org.apache.commons.cli2.CommandLine;
 import org.apache.commons.cli2.Option;
@@ -40,7 +40,7 @@ import org.apache.jackrabbit.vault.util.console.util.Table;
  */
 public class CmdLs extends AbstractConsoleCommand {
 
-    private static final SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy MMM dd HH:mm");
+    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy MMM dd HH:mm");
 
     // format flags
     private static int F_FLAG_TIME = 0x01;
@@ -160,7 +160,7 @@ public class CmdLs extends AbstractConsoleCommand {
             }
             Table.Row r = t.createRow();
             if ((flags & F_FLAG_TIME) > 0) {
-                r.addCol(dateFmt.format(new Date(f.lastModified())));
+                r.addCol(DATE_FMT.format(Instant.ofEpochMilli(f.lastModified())));
             }
             if ((flags & F_FLAG_SIZE) > 0) {
                 r.addCol(String.valueOf(f.length()), true);
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/PropertyValueArtifact.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/PropertyValueArtifact.java
index 5dd9498..5120a88 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/PropertyValueArtifact.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/PropertyValueArtifact.java
@@ -167,7 +167,7 @@ public class PropertyValueArtifact extends AbstractArtifact implements ExportArt
             tmpFile.setLastModified(getLastModified());
             tmpFile.deleteOnExit();
             try (FileOutputStream out = new FileOutputStream(tmpFile);
-                 InputStream in = getValue().getStream()) {
+                 InputStream in = getValue().getBinary().getStream()) {
                 IOUtils.copy(in, out);
             }
         }
@@ -296,37 +296,44 @@ public class PropertyValueArtifact extends AbstractArtifact implements ExportArt
                     throw new IOException("Stream already closed.");
                 }
                 try {
-                    stream = getValue().getStream();
+                    stream = getValue().getBinary().getStream();
                 } catch (RepositoryException e) {
                     throw new IOException("Error while opening stream: " + e.toString());
                 }
             }
         }
+
+        @Override
         public int read() throws IOException {
             assertOpen();
             return stream.read();
         }
 
+        @Override
         public int read(byte[] b) throws IOException {
             assertOpen();
             return stream.read(b);
         }
 
+        @Override
         public int read(byte[] b, int off, int len) throws IOException {
             assertOpen();
             return stream.read(b, off, len);
         }
 
+        @Override
         public long skip(long n) throws IOException {
             assertOpen();
             return stream.skip(n);
         }
 
+        @Override
         public int available() throws IOException {
             assertOpen();
             return stream.available();
         }
 
+        @Override
         public void close() throws IOException {
             try {
                 if (stream != null) {
@@ -338,7 +345,8 @@ public class PropertyValueArtifact extends AbstractArtifact implements ExportArt
             }
         }
 
-        public void mark(int readlimit) {
+        @Override
+        public synchronized void mark(int readlimit) {
             try {
                 assertOpen();
             } catch (IOException e) {
@@ -347,11 +355,13 @@ public class PropertyValueArtifact extends AbstractArtifact implements ExportArt
             stream.mark(readlimit);
         }
 
-        public void reset() throws IOException {
+        @Override
+        public synchronized void reset() throws IOException {
             assertOpen();
             stream.reset();
         }
 
+        @Override
         public boolean markSupported() {
             try {
                 assertOpen();
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/VaultFileInputStream.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/VaultFileInputStream.java
index 201476a..6d9e7f6 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/VaultFileInputStream.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/VaultFileInputStream.java
@@ -17,11 +17,11 @@
 
 package org.apache.jackrabbit.vault.fs;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 
 import javax.jcr.RepositoryException;
 
@@ -48,7 +48,7 @@ public class VaultFileInputStream extends InputStream {
     /**
      * Temp file for spooling
      */
-    private File tmpFile;
+    private Path tmpFile;
 
     /**
      * Creates a new input stream on the given file. If the file is a
@@ -66,81 +66,62 @@ public class VaultFileInputStream extends InputStream {
             if (a.getPreferredAccess() == AccessType.STREAM) {
                 base = a.getInputStream();
             } else {
-                tmpFile = File.createTempFile("vltfs", ".spool");
-                try (FileOutputStream out = new FileOutputStream(tmpFile)) {
+                tmpFile = Files.createTempFile("vltfs", ".spool");
+                try (OutputStream out = Files.newOutputStream(tmpFile)) {
                     a.spool(out);
                 }
-                base = new FileInputStream(tmpFile);
+                base = Files.newInputStream(tmpFile);
             }
         } catch (RepositoryException e) {
             throw new IOException(e.toString());
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public int read() throws IOException {
         return base.read();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public int read(byte[] b) throws IOException {
         return base.read(b);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public int read(byte[] b, int off, int len) throws IOException {
         return base.read(b, off, len);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public long skip(long n) throws IOException {
         return base.skip(n);
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public int available() throws IOException {
         return base.available();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public void close() throws IOException {
         base.close();
         if (tmpFile != null) {
-            tmpFile.delete();
-            tmpFile.deleteOnExit();
+            Files.delete(tmpFile);;
             tmpFile = null;
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void mark(int readlimit) {
+    @Override
+    public synchronized void mark(int readlimit) {
         base.mark(readlimit);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public void reset() throws IOException {
+    @Override
+    public synchronized void reset() throws IOException {
         base.reset();
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    @Override
     public boolean markSupported() {
         return base.markSupported();
     }
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java
index 02047e0..beb2521 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/DefaultWorkspaceFilter.java
@@ -655,15 +655,9 @@ public class DefaultWorkspaceFilter implements Dumpable, WorkspaceFilter {
             return false;
         if (importMode != other.importMode)
             return false;
-        if (nodesFilterSets == null) {
-            if (other.nodesFilterSets != null)
-                return false;
-        } else if (!nodesFilterSets.equals(other.nodesFilterSets))
+        if (!nodesFilterSets.equals(other.nodesFilterSets))
             return false;
-        if (propsFilterSets == null) {
-            if (other.propsFilterSets != null)
-                return false;
-        } else if (!propsFilterSets.equals(other.propsFilterSets))
+        if (!propsFilterSets.equals(other.propsFilterSets))
             return false;
         if (referenceFilterSets == null) {
             if (other.referenceFilterSets != null)
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/SimpleCredentialsConfig.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/SimpleCredentialsConfig.java
index 925cdd3..b183f85 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/SimpleCredentialsConfig.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/config/SimpleCredentialsConfig.java
@@ -114,8 +114,9 @@ public class SimpleCredentialsConfig extends CredentialsConfig {
      * {@link #decrypt(String) decrypted} again.
      *
      * @param s string to encrypt
-     * @return the encrypted string with a "{AES}" prefix.
+     * @return the encrypted string with a "{DES}" prefix.
      */
+    @SuppressWarnings({"java:S5547", "java:S5542"}) // DES is not secure but we are storing the keys anyways with the encrypted password, so it doesn't really matter
     private static String encrypt(String s) {
         try {
             SecretKey key = KeyGenerator.getInstance("DES").generateKey();
@@ -144,6 +145,7 @@ public class SimpleCredentialsConfig extends CredentialsConfig {
      * @param s the data to decrypt
      * @return the string or {@code null} if an internal error occurred
      */
+    @SuppressWarnings({"java:S5547", "java:S5542"}) // DES is not secure but we are storing the keys anyways with the encrypted password, so it doesn't really matter
     private static String decrypt(String s) {
         if (s == null || !s.startsWith(PREFIX)) {
             return s;
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewAnalyzer.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewAnalyzer.java
index 78b3ba5..68b5dac 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewAnalyzer.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewAnalyzer.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import javax.jcr.NamespaceException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.xml.XMLConstants;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
@@ -30,9 +31,9 @@ import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
 import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.vault.fs.io.DocViewAnalyzerListener;
 import org.apache.jackrabbit.vault.util.RejectingEntityDefaultHandler;
-import org.apache.jackrabbit.util.Text;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.Attributes;
@@ -98,6 +99,8 @@ public class DocViewAnalyzer extends RejectingEntityDefaultHandler implements Na
             factory.setNamespaceAware(true);
             factory.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
             SAXParser parser = factory.newSAXParser();
+            parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+            parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
             parser.parse(source, handler);
         } catch (ParserConfigurationException e) {
             throw new IllegalStateException(e);
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXFormatter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXFormatter.java
index 3cb252f..6dfbb19 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXFormatter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXFormatter.java
@@ -227,8 +227,8 @@ public class DocViewSAXFormatter implements AggregateWalkListener {
     @Override
     public void onChildren(Node node, int level) throws RepositoryException {
         String label = Text.getName(node.getPath());
-        String elemName;
-        if (level == 0 || node.getDepth() == 0) {
+        final String elemName;
+        if (level == 0) {
             // root node needs a name
             elemName = jcrRoot;
         } else {
@@ -248,7 +248,7 @@ public class DocViewSAXFormatter implements AggregateWalkListener {
             } else {
                 writer.writeStartElement(qName.getLocalName());
             }
-            if (elemName == jcrRoot) {
+            if (level == 0) {
                 startNamespaceDeclarations();
             }
             for (Property prop: props) {
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FileArtifactHandler.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FileArtifactHandler.java
index 10d5773..46839d6 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FileArtifactHandler.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FileArtifactHandler.java
@@ -28,6 +28,7 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.NodeType;
+import javax.xml.XMLConstants;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
@@ -235,6 +236,8 @@ public class FileArtifactHandler extends AbstractArtifactHandler  {
                             factory.setNamespaceAware(true);
                             factory.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
                             SAXParser parser = factory.newSAXParser();
+                            parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+                            parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
                             parser.parse(file.getInputSource(), handler);
                             info.merge(handler.getInfo());
                         } catch (ParserConfigurationException e) {
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/GenericArtifactHandler.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/GenericArtifactHandler.java
index e133ac9..4af46b7 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/GenericArtifactHandler.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/GenericArtifactHandler.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
+import javax.xml.XMLConstants;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
@@ -97,6 +98,8 @@ public class GenericArtifactHandler extends AbstractArtifactHandler {
                 factory.setNamespaceAware(true);
                 factory.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
                 SAXParser parser = factory.newSAXParser();
+                parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+                parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
                 parser.parse(source, handler);
                 info.merge(handler.getInfo());
             } catch (ParserConfigurationException e) {
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractExporter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractExporter.java
index 6bd4d86..48f89d4 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractExporter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AbstractExporter.java
@@ -419,7 +419,7 @@ public abstract class AbstractExporter implements AutoCloseable {
             throws RepositoryException, IOException;
 
     /**
-     * <p>The specified stream remains open after this method returns.
+     * <p>The specified stream is automatically closed after this method returns or throws an exception.
      * @param in
      * @param relPath
      * @throws IOException
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewFormat.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewFormat.java
index 6669630..36fd943 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewFormat.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewFormat.java
@@ -41,7 +41,9 @@ import java.util.zip.CheckedInputStream;
 import java.util.zip.CheckedOutputStream;
 import java.util.zip.Checksum;
 
+import javax.xml.XMLConstants;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 import javax.xml.stream.FactoryConfigurationError;
 import javax.xml.stream.XMLStreamException;
@@ -144,13 +146,16 @@ public class DocViewFormat {
                 // cannot use XMlStreamReader due to comment handling:
                 // https://stackoverflow.com/questions/15792007/why-does-xmlstreamreader-staxsource-strip-comments-from-xml
                 TransformerFactory tf = TransformerFactory.newInstance();
-                tf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
+                tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+                tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
                 SAXSource saxSource = new SAXSource(new InputSource(in));
                 SAXParserFactory sf = SAXParserFactory.newInstance();
                 sf.setNamespaceAware(true);
                 sf.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
-                sf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
-                saxSource.setXMLReader(new NormalizingSaxFilter(sf.newSAXParser().getXMLReader()));
+                SAXParser parser = sf.newSAXParser();
+                parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+                parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+                saxSource.setXMLReader(new NormalizingSaxFilter(parser.getXMLReader()));
                 Transformer t = tf.newTransformer();
                 StAXResult result = new StAXResult(writer);
                 t.transform(saxSource, result);
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JarExporter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JarExporter.java
index b898372..857d136 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JarExporter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JarExporter.java
@@ -202,11 +202,15 @@ public class JarExporter extends AbstractExporter {
 
     public void writeFile(InputStream in, String relPath) throws IOException {
         // The file input stream to be written is assumed to be compressible
-        ZipEntry e = new ZipEntry(relPath);
-        exportInfo.update(ExportInfo.Type.ADD, e.getName());
-        jOut.putNextEntry(e);
-        IOUtils.copy(in, jOut);
-        jOut.closeEntry();
+        try {
+            ZipEntry e = new ZipEntry(relPath);
+            exportInfo.update(ExportInfo.Type.ADD, e.getName());
+            jOut.putNextEntry(e);
+            IOUtils.copy(in, jOut);
+            jOut.closeEntry();
+        } finally {
+            in.close();
+        }
     }
 
     public void write(ZipFile zip, ZipEntry entry) throws IOException {
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JcrExporter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JcrExporter.java
index 8e32b88..766de2d 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JcrExporter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JcrExporter.java
@@ -168,11 +168,10 @@ public class JcrExporter extends AbstractExporter {
                 content.setProperty(JcrConstants.JCR_MIMETYPE, "application/octet-stream");
             }
             b.dispose();
-            in.close();
         } catch (RepositoryException e) {
-            IOException io = new IOException("Error while writing file " + relPath);
-            io.initCause(e);
-            throw io;
+            throw new IOException("Error while writing file " + relPath, e);
+        } finally {
+            in.close();
         }
     }
 
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/PlatformExporter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/PlatformExporter.java
index 02f74e9..aedca94 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/PlatformExporter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/PlatformExporter.java
@@ -22,6 +22,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.Files;
 
 import javax.jcr.RepositoryException;
 
@@ -159,19 +160,20 @@ public class PlatformExporter extends AbstractExporter {
     }
 
     public void writeFile(InputStream in, String relPath) throws IOException {
-        File local = new File(localParent, relPath);
-        if (!local.getParentFile().exists()) {
-            mkdirs(local.getParentFile());
-        }
-        if (local.exists()) {
-            exportInfo.update(ExportInfo.Type.UPDATE, local.getPath());
-        } else {
-            exportInfo.update(ExportInfo.Type.ADD, local.getPath());
+        try {
+            File local = new File(localParent, relPath);
+            if (!local.getParentFile().exists()) {
+                mkdirs(local.getParentFile());
+            }
+            if (local.exists()) {
+                exportInfo.update(ExportInfo.Type.UPDATE, local.getPath());
+            } else {
+                exportInfo.update(ExportInfo.Type.ADD, local.getPath());
+            }
+            Files.copy(in, local.toPath());
+        } finally {
+            in.close();
         }
-        OutputStream out = new FileOutputStream(local);
-        IOUtils.copy(in, out);
-        in.close();
-        out.close();
     }
 
     private void mkdirs(File dir) throws IOException {
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/ZipStreamArchive.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/ZipStreamArchive.java
index 3a38ffc..a8cd148 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/ZipStreamArchive.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/ZipStreamArchive.java
@@ -407,12 +407,12 @@ public class ZipStreamArchive extends AbstractArchive {
         }
 
         @Override
-        public void mark(int readlimit) {
+        public synchronized void mark(int readlimit) {
             mark = pos;
         }
 
         @Override
-        public void reset() throws IOException {
+        public synchronized void reset() throws IOException {
             pos = mark;
         }
 
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java
index c8fdf66..3dd99dc 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageImpl.java
@@ -307,19 +307,19 @@ public class JcrPackageImpl implements JcrPackage {
                 MemoryArchive archive = new MemoryArchive(false);
                 try (InputStream in = getData().getBinary().getStream()) {
                     archive.run(in);
+                    // workaround for shallow packages that don't have a meta-inf anymore (JCRVLT-188)
+                    Properties props = archive.getMetaInf().getProperties();
+                    if (props == null || props.isEmpty()) {
+                        JcrPackageDefinition def = getDefinition();
+                        if (def != null) {
+                            ((DefaultMetaInf) archive.getMetaInf()).setProperties(def.getMetaInf().getProperties());
+                        }
+                    }
+                    pack = new ZipVaultPackage(archive, true);
                 } catch (Exception e) {
                     archive.close();
                     throw new IOException("Error while reading stream", e);
                 }
-                // workaround for shallow packages that don't have a meta-inf anymore (JCRVLT-188)
-                Properties props = archive.getMetaInf().getProperties();
-                if (props == null || props.isEmpty()) {
-                    JcrPackageDefinition def = getDefinition();
-                    if (def != null) {
-                        ((DefaultMetaInf) archive.getMetaInf()).setProperties(def.getMetaInf().getProperties());
-                    }
-                }
-                pack = new ZipVaultPackage(archive, true);
             } else {
                 File tmpFile = File.createTempFile("vaultpack", ".zip");
                 Binary bin = getData().getBinary();
@@ -752,53 +752,59 @@ public class JcrPackageImpl implements JcrPackage {
         if (def == null) {
             return;
         }
-        List<Dependency> unresolved = new LinkedList<Dependency>();
-        List<RegisteredPackage> uninstalled = new LinkedList<RegisteredPackage>();
-        for (Dependency dep: def.getDependencies()) {
-            // resolve to installed and uninstalled packages
-            PackageId id = mgr.resolve(dep, false);
-            if (id == null) {
-                unresolved.add(dep);
-            } else {
-                RegisteredPackage pack = (RegisteredPackage) mgr.open(id);
-                if (pack != null && !pack.isInstalled()) {
+        List<Dependency> unresolved = new LinkedList<>();
+        List<RegisteredPackage> uninstalled = new LinkedList<>();
+        try {
+            for (Dependency dep: def.getDependencies()) {
+                // resolve to installed and uninstalled packages
+                PackageId id = mgr.resolve(dep, false);
+                if (id == null) {
                     unresolved.add(dep);
-                    uninstalled.add(pack);
+                } else {
+                    RegisteredPackage pack = mgr.open(id);
+                    if (pack != null && !pack.isInstalled()) {
+                        unresolved.add(dep);
+                        uninstalled.add(pack);
+                    }
                 }
             }
-        }
-        // if non unresolved, then we're good
-        if (unresolved.size() == 0) {
-            return;
-        }
-        // if the package is not installed at all, abort for required and strict handling
-        if ((opts.getDependencyHandling() == DependencyHandling.STRICT && unresolved.size() > 0)
-                || (opts.getDependencyHandling() == DependencyHandling.REQUIRED && unresolved.size() > uninstalled.size())) {
-            String msg = String.format("Refusing to install package %s. required dependencies missing: %s", def.getId(), unresolved);
-            log.error(msg);
-            throw new DependencyException(msg);
-        }
-
-        for (RegisteredPackage pack: uninstalled) {
-            if (pack.isInstalled()) {
-                continue;
+            // if non unresolved, then we're good
+            if (unresolved.isEmpty()) {
+                return;
+            }
+            // if the package is not installed at all, abort for required and strict handling
+            if ((opts.getDependencyHandling() == DependencyHandling.STRICT && unresolved.size() > 0)
+                    || (opts.getDependencyHandling() == DependencyHandling.REQUIRED && unresolved.size() > uninstalled.size())) {
+                String msg = String.format("Refusing to install package %s. required dependencies missing: %s", def.getId(), unresolved);
+                log.error(msg);
+                throw new DependencyException(msg);
             }
-            PackageId packageId = pack.getId();
-            if (processed.contains(packageId)) {
-                if (opts.getDependencyHandling() == DependencyHandling.BEST_EFFORT) {
+    
+            for (RegisteredPackage pack: uninstalled) {
+                if (pack.isInstalled()) {
                     continue;
                 }
-                String msg = String.format("Unable to install package %s. dependency has as cycling reference to %s", def.getId(), packageId);
-                log.error(msg);
-                throw new CyclicDependencyException(msg);
+                PackageId packageId = pack.getId();
+                if (processed.contains(packageId)) {
+                    if (opts.getDependencyHandling() == DependencyHandling.BEST_EFFORT) {
+                        continue;
+                    }
+                    String msg = String.format("Unable to install package %s. dependency has as cycling reference to %s", def.getId(), packageId);
+                    log.error(msg);
+                    throw new CyclicDependencyException(msg);
+                }
+                if (pack instanceof JcrRegisteredPackage) {
+                    JcrPackage jcrPackage = ((JcrRegisteredPackage)pack).getJcrPackage();
+                    ((JcrPackageImpl)jcrPackage).extract(processed, opts, createSnapshot, replaceSnapshot);
+                } else {
+                    String msg = String.format("Unable to install package %s. dependency not found in JcrPackageRegistry %s", def.getId(), packageId);
+                    log.error(msg);
+                    throw new DependencyException(msg);
+                }
             }
-            if (pack instanceof JcrRegisteredPackage) {
-                JcrPackage jcrPackage = ((JcrRegisteredPackage)pack).getJcrPackage();
-                ((JcrPackageImpl)jcrPackage).extract(processed, opts, createSnapshot, replaceSnapshot);
-            } else {
-                String msg = String.format("Unable to install package %s. dependency not found in JcrPackageRegistry %s", def.getId(), packageId);
-                log.error(msg);
-                throw new DependencyException(msg);
+        } finally {
+            for (RegisteredPackage pack: uninstalled) {
+                pack.close();
             }
         }
     }
@@ -890,22 +896,27 @@ public class JcrPackageImpl implements JcrPackage {
         String parentPath = Text.getRelativeParent(path, 1);
         Node folder = packMgr.mkdir(parentPath, true);
         JcrPackage snap = mgr.createNew(folder, id, null, true);
-        JcrPackageDefinitionImpl snapDef = (JcrPackageDefinitionImpl) snap.getDefinition();
-        snapDef.setId(id, false);
-        snapDef.setFilter(filter, false);
-        snapDef.set(JcrPackageDefinition.PN_DESCRIPTION, "Snapshot of package " + myDef.getId().toString(), false);
-        if (acHandling == null) {
-            snapDef.set(JcrPackageDefinition.PN_AC_HANDLING, myDef.get(JcrPackageDefinition.PN_AC_HANDLING), false);
-        } else {
-            snapDef.set(JcrPackageDefinition.PN_AC_HANDLING, acHandling.name(), false);
-        }
-        if (opts.getListener() != null) {
-            opts.getListener().onMessage(ProgressTrackerListener.Mode.TEXT, "Creating snapshot for package " + myDef.getId(), "");
+        try {
+            JcrPackageDefinitionImpl snapDef = (JcrPackageDefinitionImpl) snap.getDefinition();
+            snapDef.setId(id, false);
+            snapDef.setFilter(filter, false);
+            snapDef.set(JcrPackageDefinition.PN_DESCRIPTION, "Snapshot of package " + myDef.getId().toString(), false);
+            if (acHandling == null) {
+                snapDef.set(JcrPackageDefinition.PN_AC_HANDLING, myDef.get(JcrPackageDefinition.PN_AC_HANDLING), false);
+            } else {
+                snapDef.set(JcrPackageDefinition.PN_AC_HANDLING, acHandling.name(), false);
+            }
+            if (opts.getListener() != null) {
+                opts.getListener().onMessage(ProgressTrackerListener.Mode.TEXT, "Creating snapshot for package " + myDef.getId(), "");
+            }
+            packMgr.assemble(snap.getNode(), snapDef, opts.getListener());
+            log.debug("Creating snapshot for {} completed.", id);
+            mgr.dispatch(PackageEvent.Type.SNAPSHOT, id, null);
+            return snap;
+        } catch (RepositoryException|PackageException|IOException e) {
+            snap.close();
+            throw e;
         }
-        packMgr.assemble(snap.getNode(), snapDef, opts.getListener());
-        log.debug("Creating snapshot for {} completed.", id);
-        mgr.dispatch(PackageEvent.Type.SNAPSHOT, id, null);
-        return snap;
     }
 
     /**
@@ -936,6 +947,8 @@ public class JcrPackageImpl implements JcrPackage {
             JcrPackageImpl snap = new JcrPackageImpl(mgr, packNode);
             if (snap.isValid()) {
                 return snap;
+            } else {
+                snap.close();
             }
         }
         return null;
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java
index b7bef1d..0096d2b 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/impl/JcrPackageManagerImpl.java
@@ -62,7 +62,6 @@ import org.apache.jackrabbit.vault.packaging.registry.PackageRegistry;
 
 import org.apache.jackrabbit.vault.packaging.registry.impl.AbstractPackageRegistry;
 import org.apache.jackrabbit.vault.packaging.registry.impl.JcrPackageRegistry;
-import org.apache.jackrabbit.vault.packaging.registry.impl.JcrRegisteredPackage;
 import org.apache.jackrabbit.vault.util.JcrConstants;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -124,13 +123,7 @@ public class JcrPackageManagerImpl extends PackageManagerImpl implements JcrPack
      */
     @Override
     public JcrPackage open(PackageId id) throws RepositoryException {
-        try {
-            //noinspection resource
-            JcrRegisteredPackage pkg = (JcrRegisteredPackage) registry.open(id);
-            return pkg == null ? null : pkg.getJcrPackage();
-        } catch (IOException e) {
-            throw unwrapRepositoryException(e);
-        }
+        return registry.openJcrPackage(id);
     }
 
     /**
@@ -590,10 +583,11 @@ public class JcrPackageManagerImpl extends PackageManagerImpl implements JcrPack
                             }
                         }
                         pack.close();
-                    } else if (child.hasNodes() && !shallow){
-                        listPackages(child, packages, filter, built, false);
                     } else {
                         pack.close();
+                        if (child.hasNodes() && !shallow) {
+                            listPackages(child, packages, filter, built, false);
+                        }
                     }
                 } catch (RepositoryException e) {
                     pack.close();
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java
index 0c5ac0f..4100659 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/packaging/registry/impl/JcrPackageRegistry.java
@@ -255,6 +255,12 @@ public class JcrPackageRegistry extends AbstractPackageRegistry {
         }
     }
 
+    @Nullable
+    public JcrPackage openJcrPackage(@NotNull PackageId id) throws RepositoryException {
+        Node node = getPackageNode(id);
+        return node == null ? null : open(node, false);
+    }
+
     @Override
     public boolean contains(@NotNull PackageId id) throws IOException {
         try {
@@ -288,15 +294,20 @@ public class JcrPackageRegistry extends AbstractPackageRegistry {
      */
     public JcrPackage open(Node node, boolean allowInvalid) throws RepositoryException {
         JcrPackage pack = new JcrPackageImpl(this, node);
-        if (pack.isValid()) {
-            return pack;
-        } else if (allowInvalid
-                && node.isNodeType(JcrConstants.NT_HIERARCHYNODE)
-                && node.hasProperty(JcrConstants.JCR_CONTENT + "/" + JcrConstants.JCR_DATA)) {
-            return pack;
-        } else {
+        try {
+            if (pack.isValid()) {
+                return pack;
+            } else if (allowInvalid
+                    && node.isNodeType(JcrConstants.NT_HIERARCHYNODE)
+                    && node.hasProperty(JcrConstants.JCR_CONTENT + "/" + JcrConstants.JCR_DATA)) {
+                return pack;
+            } else {
+                pack.close();
+                return null;
+            }
+        } catch (RepositoryException e) {
             pack.close();
-            return null;
+            throw e;
         }
     }
 
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java
index 3df4f54..a7a7b90 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java
@@ -103,7 +103,7 @@ public class DocViewNode {
         result = prime * result + Arrays.hashCode(mixins);
         result = prime * result + ((name == null) ? 0 : name.hashCode());
         result = prime * result + ((primary == null) ? 0 : primary.hashCode());
-        result = prime * result + ((props == null) ? 0 : props.hashCode());
+        result = prime * result + props.hashCode();
         result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
         return result;
     }
@@ -134,10 +134,7 @@ public class DocViewNode {
                 return false;
         } else if (!primary.equals(other.primary))
             return false;
-        if (props == null) {
-            if (other.props != null)
-                return false;
-        } else if (!props.equals(other.props))
+        if (!props.equals(other.props))
             return false;
         if (uuid == null) {
             if (other.uuid != null)
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/InputStreamPump.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/InputStreamPump.java
index b776692..da473b9 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/InputStreamPump.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/InputStreamPump.java
@@ -141,6 +141,7 @@ public class InputStreamPump extends InputStream {
             pumpThread.join();
             in.close();
         } catch (InterruptedException e) {
+            pumpThread.interrupt();
             throw new IOException(e);
         }
         if (error != null) {
@@ -149,11 +150,11 @@ public class InputStreamPump extends InputStream {
     }
 
     @Override
-    public void mark(int readlimit) {
+    public synchronized void mark(int readlimit) {
     }
 
     @Override
-    public void reset() throws IOException {
+    public synchronized void reset() throws IOException {
     }
 
     @Override
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/LineInputStream.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/LineInputStream.java
index f8e2871..ef2c0d0 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/LineInputStream.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/LineInputStream.java
@@ -82,7 +82,7 @@ public class LineInputStream extends InputStream {
         if (read(one) == -1) {
             return -1;
         }
-        return one[0];
+        return one[0] & 0xFF;
     }
 
     public int read(byte b[], int off, int len) throws IOException {
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/RepositoryCopier.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/RepositoryCopier.java
index 06c8590..6f57b2b 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/RepositoryCopier.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/RepositoryCopier.java
@@ -489,7 +489,8 @@ public class RepositoryCopier {
                     try {
                         Thread.sleep(throttle * 1000);
                     } catch (InterruptedException e) {
-                        // ignore
+                        log.warn("Interrupted while waiting", e);
+                        Thread.currentThread().interrupt();
                     }
                 }
             } catch (RepositoryException e) {
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/Text.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/Text.java
index 4b24a47..7e69379 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/util/Text.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/util/Text.java
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.vault.util;
 
 import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
@@ -402,31 +403,27 @@ public class Text {
      *                                        escape character
      */
     public static String unescape(String string, char escape)  {
-        try {
-            byte[] utf8 = string.getBytes("utf-8");
+        byte[] utf8 = string.getBytes(StandardCharsets.UTF_8);
 
-            // Check whether escape occurs at invalid position
-            if ((utf8.length >= 1 && utf8[utf8.length - 1] == escape) ||
-                (utf8.length >= 2 && utf8[utf8.length - 2] == escape)) {
-                throw new IllegalArgumentException("Premature end of escape sequence at end of input");
-            }
+        // Check whether escape occurs at invalid position
+        if ((utf8.length >= 1 && utf8[utf8.length - 1] == escape) ||
+            (utf8.length >= 2 && utf8[utf8.length - 2] == escape)) {
+            throw new IllegalArgumentException("Premature end of escape sequence at end of input");
+        }
 
-            ByteArrayOutputStream out = new ByteArrayOutputStream(utf8.length);
-            for (int k = 0; k < utf8.length; k++) {
-                byte b = utf8[k];
-                if (b == escape) {
-                    out.write((decodeDigit(utf8[++k]) << 4) + decodeDigit(utf8[++k]));
-                }
-                else {
-                    out.write(b);
-                }
+        ByteArrayOutputStream out = new ByteArrayOutputStream(utf8.length);
+        for (int k = 0; k < utf8.length; k++) {
+            byte b = utf8[k];
+            if (b == escape) {
+                out.write((decodeDigit(utf8[++k]) << 4) & 0xff + decodeDigit(utf8[++k]) & 0xff);
+            }
+            else {
+                out.write(b);
             }
-
-            return new String(out.toByteArray(), "utf-8");
-        }
-        catch (UnsupportedEncodingException e) {
-            throw new InternalError(e.toString());
         }
+
+        return new String(out.toByteArray(), StandardCharsets.UTF_8);
+        
     }
 
     /**
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 678834f..c8bf670 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
@@ -203,6 +203,7 @@ public class RcpTaskImpl implements Runnable, RcpTask {
                     thread.join(10000);
                 } catch (InterruptedException e) {
                     log.error("Error while waiting for thread: " + thread.getName(), e);
+                    thread.interrupt();
                 }
                 if (thread.isAlive()) {
                     // try to interrupt the thread
diff --git a/vault-sync/src/main/java/org/apache/jackrabbit/vault/sync/impl/SyncLog.java b/vault-sync/src/main/java/org/apache/jackrabbit/vault/sync/impl/SyncLog.java
index 51dda20..edb5d5a 100644
--- a/vault-sync/src/main/java/org/apache/jackrabbit/vault/sync/impl/SyncLog.java
+++ b/vault-sync/src/main/java/org/apache/jackrabbit/vault/sync/impl/SyncLog.java
@@ -19,8 +19,8 @@ package org.apache.jackrabbit.vault.sync.impl;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,7 +35,7 @@ public class SyncLog {
      */
     private static final Logger log = LoggerFactory.getLogger(SyncLog.class);
 
-    private static SimpleDateFormat dateFmt = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss ");
+    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss ");
 
     private final File logFile;
 
@@ -48,13 +48,13 @@ public class SyncLog {
         log.info("{}", msg);
 
         StringBuilder line = new StringBuilder();
-        line.append(dateFmt.format(new Date()));
+        line.append(DATE_FMT.format(Instant.now()));
         line.append(msg);
         line.append("\n");
         try (FileWriter writer = new FileWriter(logFile, true)) {
             writer.write(line.toString());
         } catch (IOException e) {
-            log.error("Unable to update log file: {}", e);
+            log.error("Unable to update log file: {}", logFile, e);
         }
     }
 }
\ No newline at end of file
diff --git a/vault-sync/src/main/java/org/apache/jackrabbit/vault/sync/impl/VaultSyncServiceImpl.java b/vault-sync/src/main/java/org/apache/jackrabbit/vault/sync/impl/VaultSyncServiceImpl.java
index a727cab..b3d0152 100644
--- a/vault-sync/src/main/java/org/apache/jackrabbit/vault/sync/impl/VaultSyncServiceImpl.java
+++ b/vault-sync/src/main/java/org/apache/jackrabbit/vault/sync/impl/VaultSyncServiceImpl.java
@@ -156,6 +156,7 @@ public class VaultSyncServiceImpl implements EventListener, Runnable {
                 fsCheckThread.join();
             } catch (InterruptedException e) {
                 log.warn("error while waiting for thread to terminate", e);
+                fsCheckThread.interrupt();
             }
             fsCheckThread = null;
         }
@@ -187,6 +188,7 @@ public class VaultSyncServiceImpl implements EventListener, Runnable {
                     waitCondition.await(checkDelay, TimeUnit.MILLISECONDS);
                 } catch (InterruptedException e) {
                     log.warn("interrupted while waiting.");
+                    Thread.currentThread().interrupt();
                 }
             }
         } finally {
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/AdvancedFilterValidator.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/AdvancedFilterValidator.java
index 1826759..5f22015 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/AdvancedFilterValidator.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/AdvancedFilterValidator.java
@@ -37,7 +37,9 @@ import java.util.stream.Collectors;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+
 import org.apache.commons.lang3.StringUtils;
+import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.vault.fs.api.FilterSet.Entry;
 import org.apache.jackrabbit.vault.fs.api.PathFilter;
 import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
@@ -48,7 +50,6 @@ import org.apache.jackrabbit.vault.fs.filter.DefaultPathFilter;
 import org.apache.jackrabbit.vault.packaging.PackageInfo;
 import org.apache.jackrabbit.vault.util.Constants;
 import org.apache.jackrabbit.vault.util.DocViewNode;
-import org.apache.jackrabbit.util.Text;
 import org.apache.jackrabbit.vault.validation.ValidationViolation;
 import org.apache.jackrabbit.vault.validation.impl.util.ValidationMessageErrorHandler;
 import org.apache.jackrabbit.vault.validation.spi.DocumentViewXmlValidator;
diff --git a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/AdvancedFilterValidatorFactory.java b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/AdvancedFilterValidatorFactory.java
index 1b021de..b45b9b5 100644
--- a/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/AdvancedFilterValidatorFactory.java
+++ b/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/impl/AdvancedFilterValidatorFactory.java
@@ -27,7 +27,6 @@ import java.util.Set;
 
 import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.Source;
 import javax.xml.transform.stream.StreamSource;
 import javax.xml.validation.Schema;
@@ -83,15 +82,14 @@ public final class AdvancedFilterValidatorFactory implements ValidatorFactory {
             if (xsdInput == null) {
                 throw new IllegalStateException("Can not load filter.xsd");
             }
-            factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+            factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+            factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
             // optionally adjust locale, https://stackoverflow.com/a/18745978
             if (locale != null) {
                 factory.setAttribute("http://apache.org/xml/properties/locale", locale);
             }
         } catch (SAXException e) {
             throw new IOException("Could not parse input as xml", e);
-        } catch (ParserConfigurationException e) {
-            throw new IllegalStateException("Could not instantiate DOM parser", e);
         }
         return factory;
     }
diff --git a/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Info.java b/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Info.java
index 4a309c4..0a8c5a6 100644
--- a/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Info.java
+++ b/vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/actions/Info.java
@@ -19,8 +19,8 @@ package org.apache.jackrabbit.vault.vlt.actions;
 
 import java.io.File;
 import java.io.PrintStream;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 
 import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
@@ -63,7 +63,7 @@ public class Info extends BaseAction {
         out.println();
     }
 
-    private static final SimpleDateFormat dateFmt = new SimpleDateFormat("dd MMM yyyy HH:mm:ss");
+    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("dd MMM yyyy HH:mm:ss");
 
     private static void print(PrintStream out, String name, VltEntryInfo info) {
         if (info == null) {
@@ -71,7 +71,7 @@ public class Info extends BaseAction {
         }
         out.printf("%s: %s, %s, %d, %s%n",
                 name,
-                dateFmt.format(new Date(info.getDate())),
+                DATE_FMT.format(Instant.ofEpochMilli(info.getDate())),
                 info.getContentType(),
                 info.getSize(),
                 info.getMd5()