/* * 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.felix.deploymentadmin; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarInputStream; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import junit.framework.TestCase; /** * Test cases for {@link ContentCopyingJarInputStream}. */ public class ContentCopyingJarInputStreamTest extends TestCase { private static final String MANIFEST_NAME = JarFile.MANIFEST_NAME; private static final String INDEX_NAME = "META-INF/INDEX.LIST"; private File m_tempDir; private File m_jarFile; /** * Tests that we can copy a {@link JarInputStream} containing only a manifest. */ public void testCopyEmptyJarWithManifestOnlyOk() throws Exception { Manifest man = createManifest(); createEmptyJar(man); assertJarContents(man); } /** * Tests that we can copy a simple {@link JarInputStream}. */ public void testCopyJarWithIndexAndWithManifestOk() throws Exception { Manifest man = createManifest(); createJar(man, true /* includeIndex */); assertJarContents(man); } /** * Tests that we can copy a {@link JarInputStream} even if it does not contains a manifest file. */ public void testCopyJarWithIndexAndWithoutManifestOk() throws Exception { Manifest man = null; createJar(man, true /* includeIndex */); assertJarContents(man); } /** * Tests that we can copy a simple {@link JarInputStream}. */ public void testCopyJarWithoutIndexAndWithManifestOk() throws Exception { Manifest man = createManifest(); createJar(man, false /* includeIndex */); assertJarContents(man); } /** * Tests that we can copy a {@link JarInputStream} even if it does not contains a manifest file. */ public void testCopyJarWithoutIndexAndWithoutManifestOk() throws Exception { Manifest man = null; createJar(man, false /* includeIndex */); assertJarContents(man); } protected void setUp() throws IOException { m_tempDir = createTempDir(); m_jarFile = new File(m_tempDir, "input.jar"); } protected void tearDown() { Utils.delete(m_tempDir, true); } private void appendFiles(JarOutputStream jos, int count) throws IOException { int size = 1024; for (int i = 0, j = 1; i < count; i++, j++) { JarEntry entry = new JarEntry("sub/" + j); jos.putNextEntry(entry); for (int k = 0; k < size; k++) { jos.write('0' + j); } jos.closeEntry(); } } private void assertJarContents(Manifest man) throws IOException { File indexFile = new File(m_tempDir, "index.txt"); FileInputStream fis = new FileInputStream(m_jarFile); JarInputStream jis = new ContentCopyingJarInputStream(fis, indexFile, m_tempDir); try { JarEntry entry; while ((entry = jis.getNextJarEntry()) != null) { File f = new File(m_tempDir, entry.getName()); // Without reading the actual contents, the copy should already exist... assertTrue(entry.getName() + " does not exist?!", f.exists()); int size = (INDEX_NAME.equals(entry.getName()) ? 33 : 1024); byte[] input = new byte[size]; int read = jis.read(input); assertEquals("Not all bytes were read: " + entry.getName(), size, read); // Contents will only be completely written after closing the JAR entry itself... jis.closeEntry(); verifyContents(f, input); } assertEquals("Manifest not as expected", man, jis.getManifest()); } finally { jis.close(); } } private void createEmptyJar(Manifest man) throws IOException { FileOutputStream fos = new FileOutputStream(m_jarFile); JarOutputStream jos = new JarOutputStream(fos, man); jos.close(); } private void createJar(Manifest man, boolean includeIndex) throws IOException { FileOutputStream fos = new FileOutputStream(m_jarFile); JarOutputStream jos; if (man == null || includeIndex) { jos = new JarOutputStream(fos); } else { jos = new JarOutputStream(fos, man); } if (includeIndex) { // Write the INDEX.LIST file as first entry... jos.putNextEntry(new ZipEntry(INDEX_NAME)); jos.write(("JarIndex-Version: 1.0\n\n" + m_jarFile.getName() + "\n").getBytes()); jos.closeEntry(); if (man != null) { jos.putNextEntry(new ZipEntry(MANIFEST_NAME)); man.write(jos); jos.closeEntry(); } } try { appendFiles(jos, 5); } finally { jos.close(); } } private Manifest createManifest() { Manifest mf = new Manifest(); mf.getMainAttributes().putValue("Manifest-Version", "1.0"); mf.getMainAttributes().putValue("Bundle-ManifestVersion", "2"); mf.getMainAttributes().putValue("Bundle-Version", "1.0.0"); mf.getMainAttributes().putValue("Bundle-SymbolicName", "com.foo.bar"); return mf; } private File createTempDir() throws IOException { File tmpFile = File.createTempFile("ccjis_test", null); tmpFile.delete(); tmpFile.mkdir(); return tmpFile; } private void verifyContents(File file, byte[] expected) throws IOException { FileInputStream fis = new FileInputStream(file); GZIPInputStream gis = new GZIPInputStream(fis); try { byte[] b = new byte[expected.length]; int read = gis.read(b); assertEquals(b.length, read); for (int i = 0; i < expected.length; i++) { assertEquals(expected[i], b[i]); } } finally { gis.close(); fis.close(); } } }