You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2018/01/09 05:24:08 UTC
svn commit: r1820625 - in /jackrabbit/commons/filevault/trunk/vault-core/src:
main/java/org/apache/jackrabbit/vault/fs/impl/io/
main/java/org/apache/jackrabbit/vault/fs/io/
test/java/org/apache/jackrabbit/vault/fs/io/
test/resources/org/apache/jackrabb...
Author: tripod
Date: Tue Jan 9 05:24:07 2018
New Revision: 1820625
URL: http://svn.apache.org/viewvc?rev=1820625&view=rev
Log:
JCRVLT-257 ZipException: invalid code lengths set (closes #20)
Added:
jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/JarExporterTest.java
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/.content.xml
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/.content.xml
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/.content.xml
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/asf_logo.png
Modified:
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/CompressionUtil.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JarExporter.java
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/CompressionUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/CompressionUtil.java?rev=1820625&r1=1820624&r2=1820625&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/CompressionUtil.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/CompressionUtil.java Tue Jan 9 05:24:07 2018
@@ -16,11 +16,17 @@
*/
package org.apache.jackrabbit.vault.fs.impl.io;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
import javax.annotation.Nonnull;
import javax.jcr.RepositoryException;
@@ -43,6 +49,11 @@ public final class CompressionUtil {
private static final Logger log = LoggerFactory.getLogger(CompressionUtil.class);
/**
+ * If set to true the compression level can be changed for individual jar entries, otherwise false.
+ */
+ public static final boolean ENV_SUPPORTS_COMPRESSION_LEVEL_CHANGE = checkEnvironmentSupportsCompressionSwitch();
+
+ /**
* Minimum length to run the auto-detection algorithm in Byte.
*/
private static final long MIN_AUTO_DETECTION_LENGTH = 115 * 1024;
@@ -185,4 +196,49 @@ public final class CompressionUtil {
return len * r < 438 * len;
}
+ /**
+ * Check if writing a JarOutputStream supports switching the compression level for individual
+ * JarEntries. There are known issues with recent zlib versions and java which might result in broken
+ * packages being exported, when they contain already compressed binary entries according to CompressionUtil.
+ * <p/>
+ * for more information see:
+ * https://issues.apache.org/jira/browse/JCRVLT-257
+ * https://github.com/madler/zlib/issues/305
+ *
+ * @return {@code true} if the environment supports switching compression levels
+ */
+ private static boolean checkEnvironmentSupportsCompressionSwitch() {
+ Throwable exception = null;
+ ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
+ byte[] nullBytes = new byte[1024 * 1024];
+ try (ZipOutputStream zipOut = new ZipOutputStream(byteArrayOut)) {
+ zipOut.setLevel(Deflater.BEST_SPEED);
+ zipOut.putNextEntry(new ZipEntry("deflated.bin"));
+ zipOut.write(nullBytes);
+ zipOut.closeEntry();
+ zipOut.putNextEntry(new ZipEntry("stored.bin"));
+ zipOut.setLevel(Deflater.BEST_COMPRESSION);
+ zipOut.write(nullBytes);
+ zipOut.closeEntry();
+ } catch (Throwable e) {
+ exception = e;
+ }
+ if (exception == null) {
+ try (ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(byteArrayOut.toByteArray()))) {
+ for (int i = 0; i < 2; i++) {
+ zipIn.getNextEntry();
+ while (zipIn.read(nullBytes) >= 0) {
+ }
+ }
+ } catch (Throwable e) {
+ exception = e;
+ }
+ }
+
+ if (exception != null) {
+ log.info("The current environment doesn't support switching compression level for individual JarEntries, see JCRVLT-257");
+ return false;
+ }
+ return true;
+ }
}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JarExporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JarExporter.java?rev=1820625&r1=1820624&r2=1820625&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JarExporter.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/JarExporter.java Tue Jan 9 05:24:07 2018
@@ -164,7 +164,9 @@ public class JarExporter extends Abstrac
throws RepositoryException, IOException {
ZipEntry e = new ZipEntry(getPlatformFilePath(file, relPath));
Artifact a = file.getArtifact();
- boolean compress = compressedLevel || CompressionUtil.isCompressible(a) >= 0;
+ boolean compress = compressedLevel
+ || !CompressionUtil.ENV_SUPPORTS_COMPRESSION_LEVEL_CHANGE
+ || CompressionUtil.isCompressible(a) >= 0;
if (!compress) {
jOut.setLevel(NO_COMPRESSION);
}
@@ -209,7 +211,8 @@ public class JarExporter extends Abstrac
public void write(ZipFile zip, ZipEntry entry) throws IOException {
track("A", entry.getName());
- if (!compressedLevel) {
+ boolean changeCompressionLevel = !compressedLevel && CompressionUtil.ENV_SUPPORTS_COMPRESSION_LEVEL_CHANGE;
+ if (changeCompressionLevel) {
// The entry to be written is assumed to be incompressible
jOut.setLevel(NO_COMPRESSION);
}
@@ -224,7 +227,7 @@ public class JarExporter extends Abstrac
in.close();
}
jOut.closeEntry();
- if (!compressedLevel) {
+ if (changeCompressionLevel) {
jOut.setLevel(level);
}
}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/JarExporterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/JarExporterTest.java?rev=1820625&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/JarExporterTest.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/JarExporterTest.java Tue Jan 9 05:24:07 2018
@@ -0,0 +1,121 @@
+/*
+ * 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.fs.io;
+
+import static java.util.zip.Deflater.BEST_COMPRESSION;
+import static java.util.zip.Deflater.BEST_SPEED;
+import static java.util.zip.Deflater.NO_COMPRESSION;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.zip.ZipException;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.vault.fs.api.AccessType;
+import org.apache.jackrabbit.vault.fs.api.Artifact;
+import org.apache.jackrabbit.vault.fs.api.SerializationType;
+import org.apache.jackrabbit.vault.fs.api.VaultFile;
+import org.junit.Test;
+
+public class JarExporterTest {
+
+ /**
+ * This test verifies that writing entries that can be compressed together with entries that are already compressed according to
+ * {@link org.apache.jackrabbit.vault.fs.impl.io.CompressionUtil} to the same file does result in a readable jar.
+ * <p/>
+ * There are certain environments that don't support changing the compression level for individual entries due to defects in the jdk
+ * and breaking changes made in recent zlib versions.
+ *
+ * @link https://issues.apache.org/jira/browse/JCRVLT-257
+ * @link https://github.com/madler/zlib/issues/305
+ */
+ @Test
+ public void testEntriesWithSuppressedCompression() throws RepositoryException, IOException {
+ Mocks m = new Mocks("org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression");
+ for (int level : new int[] { NO_COMPRESSION, BEST_COMPRESSION, BEST_SPEED }) {
+ File target = File.createTempFile("testEntriesWithSuppressedCompression", ".zip", null);
+ ZipStreamArchive archive = null;
+ try {
+ JarExporter exporter = new JarExporter(target, level);
+ exporter.open();
+ exporter.writeFile(m.mockFile(".content.xml", "application/xml"), null);
+ exporter.writeFile(m.mockFile("content/.content.xml", "application/xml"), null);
+ exporter.writeFile(m.mockFile("content/dam/.content.xml", "application/xml"), null);
+ // export a file that according to org.apache.jackrabbit.vault.fs.impl.io.CompressionUtil should not be compressed
+ exporter.writeFile(m.mockFile("content/dam/asf_logo.png", "image/png"), null);
+ exporter.close();
+ // now read the zip file
+ archive = new ZipStreamArchive(new FileInputStream(target));
+ archive.open(false); // this will throw, when the zip file is corrupt
+ // 8 entries including root and jcr_root
+ assertEquals("Wrong entry count for level " + level, 8, countEntries(archive.getRoot()));
+ } catch (ZipException ex) {
+ throw new AssertionError("Zip failed for level " + level, ex);
+ } finally {
+ if (archive != null) {
+ archive.close();
+ }
+ target.delete();
+ }
+ }
+ }
+
+ private int countEntries(Archive.Entry entry) {
+ int c = 1;
+ for (Archive.Entry child : entry.getChildren()) {
+ c += countEntries(child);
+ }
+ return c;
+ }
+
+ private class Mocks {
+
+ private final String basePath;
+
+ Mocks(String basePath) {
+ this.basePath = basePath;
+ }
+
+ private VaultFile mockFile(String relPath, String contentType) throws RepositoryException, IOException {
+ InputStream in = this.getClass().getClassLoader().getResourceAsStream(basePath + '/' + relPath);
+ Artifact a = mockArtifact(in, contentType);
+ VaultFile vaultFile = mock(VaultFile.class);
+ when(vaultFile.getPath()).thenReturn("/" + relPath);
+ when(vaultFile.getArtifact()).thenReturn(a);
+
+ return vaultFile;
+ }
+
+ private Artifact mockArtifact(InputStream in, String contentType) throws RepositoryException, IOException {
+ Artifact a = mock(Artifact.class);
+ when(a.getSerializationType()).thenReturn(SerializationType.GENERIC);
+ when(a.getContentType()).thenReturn(contentType);
+ when(a.getLastModified()).thenReturn(new Date().getTime());
+ when(a.getPreferredAccess()).thenReturn(AccessType.STREAM);
+ when(a.getInputStream()).thenReturn(in);
+
+ return a;
+ }
+ }
+}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/.content.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/.content.xml?rev=1820625&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/.content.xml (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/.content.xml Tue Jan 9 05:24:07 2018
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:mixinTypes="[rep:AccessControllable,rep:RepoAccessControllable]"
+ jcr:primaryType="rep:root"/>
Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/.content.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/.content.xml?rev=1820625&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/.content.xml (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/.content.xml Tue Jan 9 05:24:07 2018
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:rep="internal"
+ jcr:mixinTypes="[rep:AccessControllable]"
+ jcr:primaryType="sling:OrderedFolder">
+ <dam/>
+</jcr:root>
Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/.content.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/.content.xml?rev=1820625&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/.content.xml (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/.content.xml Tue Jan 9 05:24:07 2018
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:rep="internal"
+ jcr:mixinTypes="[mix:lockable,rep:AccessControllable]"
+ jcr:primaryType="sling:Folder"/>
Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/asf_logo.png
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/asf_logo.png?rev=1820625&view=auto
==============================================================================
Binary files jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/asf_logo.png (added) and jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/JarExporter/testEntriesWithSuppressedCompression/content/dam/asf_logo.png Tue Jan 9 05:24:07 2018 differ