/* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed 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.jboss.shrinkwrap.impl.base.importer; import junit.framework.Assert; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ArchiveFormat; import org.jboss.shrinkwrap.api.ArchivePath; import org.jboss.shrinkwrap.api.ArchivePaths; import org.jboss.shrinkwrap.api.Filters; import org.jboss.shrinkwrap.api.GenericArchive; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.exporter.StreamExporter; import org.jboss.shrinkwrap.api.importer.ArchiveImportException; import org.jboss.shrinkwrap.api.importer.StreamImporter; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.jboss.shrinkwrap.impl.base.io.IOUtil; import org.junit.Test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.logging.Logger; /** * Base upon which tests of {@link StreamImporter} implementations may build * * @param <T> * Type of importer under test * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a> */ public abstract class StreamImporterImplTestBase<T extends StreamImporter<T>> { // -------------------------------------------------------------------------------------|| // Class Members -----------------------------------------------------------------------|| // -------------------------------------------------------------------------------------|| /** * Logger */ private static final Logger log = Logger.getLogger(StreamImporterImplTestBase.class.getName()); /** * Name of an existing resource on the ClassPath */ private static final String EXISTING_RESOURCE = "org/jboss/shrinkwrap/impl/base/asset/Test.properties"; // -------------------------------------------------------------------------------------|| // Contracts ---------------------------------------------------------------------------|| // -------------------------------------------------------------------------------------|| /** * Obtains the delegate used in asserting imported content is as expected */ protected abstract ContentAssertionDelegateBase getDelegate(); /** * Obtains the importer type used by these tests * * @return */ protected abstract Class<T> getImporterClass(); /** * Exporter used for roundtrip testing import/export/import * * @return */ protected abstract Class<? extends StreamExporter> getExporterClass(); /** * Obtains an {@link InputStream} used to throw an exception for testing * {@link StreamImporterImplTestBase#shouldThrowExceptionOnErrorInImportFromStream()} * * @return */ protected abstract InputStream getExceptionThrowingInputStream(); /** * Obtains the {@link org.jboss.shrinkwrap.api.ArchiveFormat} to be used * @return */ protected abstract ArchiveFormat getArchiveFormat(); // -------------------------------------------------------------------------------------|| // Tests -------------------------------------------------------------------------------|| // -------------------------------------------------------------------------------------|| /** * Ensures that we may import a file and create an archive with matching structure */ @Test public void shouldBeAbleToImportFile() throws Exception { // Get the delegate final ContentAssertionDelegateBase delegate = this.getDelegate(); assert delegate != null : "Delegate must be specified by implementations"; final File testFile = delegate.getExistingResource(); // Import final Class<? extends StreamImporter<?>> importerClass = this.getImporterClass(); assert importerClass != null : "Importer class must be specified by implementations"; Archive<?> archive = ShrinkWrap.create(importerClass, "test.jar").importFrom(testFile).as(JavaArchive.class); // Ensure we don't have a null archive Assert.assertNotNull("Should not return a null archive", archive); // Validate the contents of the imported archive match that of the file from // which it was created delegate.assertContent(archive, testFile); } /** * Ensures that we may import a file and create an archive with matching structure with filter */ @Test public void shouldBeAbleToImportFileWithFilter() throws Exception { // Get the delegate final ContentAssertionDelegateBase delegate = this.getDelegate(); assert delegate != null : "Delegate must be specified by implementations"; final File testFile = delegate.getExistingResource(); // Import final Class<? extends StreamImporter<?>> importerClass = this.getImporterClass(); assert importerClass != null : "Importer class must be specified by implementations"; Archive<?> archive = ShrinkWrap.create(importerClass, "test.jar") .importFrom(testFile, Filters.include(".*MANIFEST\\.MF")).as(JavaArchive.class); // Ensure we don't have a null archive Assert.assertNotNull("Should not return a null archive", archive); // Validate the contents of the imported only contain filtered content Assert.assertEquals(2, archive.getContent().size()); Assert.assertTrue(archive.contains(ArchivePaths.create("META-INF/MANIFEST.MF"))); } /** * Ensures an attempt to import a directory fails w/ {@link IllegalArgumentException} */ @Test public void shouldNotBeAbleToImportDirectory() throws Exception { // Get the delegate final ContentAssertionDelegateBase delegate = this.getDelegate(); assert delegate != null : "Delegate must be specified by implementations"; final File testDir = delegate.getExistingResource().getParentFile(); // Import final Class<? extends StreamImporter<?>> importerClass = this.getImporterClass(); assert importerClass != null : "Importer class must be specified by implementations"; try { ShrinkWrap.create(importerClass, "test.jar").importFrom(testDir); } // Expected catch (final IllegalArgumentException iae) { // Good return; } Assert.fail("Should have received " + IllegalArgumentException.class.getSimpleName() + " on attempt to import a dir"); } /** * Ensures that we may import an archive, add content to it, export, and that the added content has been reflected * to the exported view. * * @throws Exception */ @Test public void shouldBeAbleToImportAddAndExport() throws Exception { // Get the delegate final ContentAssertionDelegateBase delegate = this.getDelegate(); assert delegate != null : "Delegate must be specified by implementations"; final File testFile = delegate.getExistingResource(); // Import from file final Class<? extends StreamImporter<?>> importerClass = this.getImporterClass(); assert importerClass != null : "Importer class must be specified by implementations"; final Archive<?> archive = ShrinkWrap.create(importerClass, "test.jar").importFrom(testFile) .as(JavaArchive.class); Assert.assertNotNull("Should not return a null archive", archive); // Add a new resource archive.add(new ClassLoaderAsset(EXISTING_RESOURCE), ArchivePaths.create("test.properties")); // Export File tempFile = new File("target/testOutput"); tempFile.deleteOnExit(); final Class<? extends StreamExporter> exporterClass = this.getExporterClass(); Assert.assertNotNull("Exporter class must be specified by implementations", exporterClass); final InputStream stream = archive.as(exporterClass).exportAsInputStream(); IOUtil.copyWithClose(stream, new FileOutputStream(tempFile)); // Ensure the exported view matches that of the archive delegate.assertContent(archive, tempFile); } /** * Ensures that we may import an archive as a stream, and the contents will be as expected * * @throws Exception */ @Test public void shouldBeAbleToImportInputStream() throws Exception { // Get the delegate final ContentAssertionDelegateBase delegate = this.getDelegate(); assert delegate != null : "Delegate must be specified by implementations"; final File testFile = delegate.getExistingResource(); // Get the input as a stream InputStream stream = new FileInputStream(testFile); // Get the importer final Class<T> importerClass = this.getImporterClass(); assert importerClass != null : "Importer class must be specified by implementations"; // Import as a stream final T importer = ShrinkWrap.create(importerClass, "test.jar"); final Archive<?> archive; try { archive = importer.importFrom(stream).as(GenericArchive.class); } finally { stream.close(); } Assert.assertNotNull("Should not return a null archive", archive); // Ensure the archive matches the file input delegate.assertContent(archive, testFile); } /** * Ensures that we may import an archive as a stream, and the contents will be as expected with filter * * @throws Exception */ @Test public void shouldBeAbleToImportInputStreamWithFilter() throws Exception { // Get the delegate final ContentAssertionDelegateBase delegate = this.getDelegate(); assert delegate != null : "Delegate must be specified by implementations"; final File testFile = delegate.getExistingResource(); // Get the input as a stream InputStream stream = new FileInputStream(testFile); // Get the importer final Class<T> importerClass = this.getImporterClass(); assert importerClass != null : "Importer class must be specified by implementations"; // Import as a stream final T importer = ShrinkWrap.create(importerClass, "test.jar"); final Archive<?> archive; try { archive = importer.importFrom(stream, Filters.include(".*MANIFEST\\.MF")).as(GenericArchive.class); } finally { stream.close(); } Assert.assertNotNull("Should not return a null archive", archive); // Validate the contents of the imported only contain filtered content Assert.assertEquals(2, archive.getContent().size()); Assert.assertTrue(archive.contains(ArchivePaths.create("META-INF/MANIFEST.MF"))); } /** * Ensures that an import of {@link InputStream} results in {@link ArchiveImportException} if an unexpected error * occurred. * * @throws Exception */ @Test(expected = ArchiveImportException.class) public void shouldThrowExceptionOnErrorInImportFromStream() throws Exception { final InputStream exceptionIn = this.getExceptionThrowingInputStream(); // Get the importer final Class<T> importerClass = this.getImporterClass(); assert importerClass != null : "Importer class must be specified by implementations"; final T importer = ShrinkWrap.create(importerClass, "test.jar"); try { final GenericArchive archive = importer.importFrom(exceptionIn).as(GenericArchive.class); log.info("Imported: " + archive.toString(true)); } finally { exceptionIn.close(); } } /** * SHRINKWRAP-474 */ @Test public void canRoundTrip() { // Define a path/name for the archive and the file it contains final String embeddedArchiveName = "lib.jar"; final String emptyFileName = "empty.file"; // Create an archive which contains another archive in the lib dir final JavaArchive embeddedArchive = ShrinkWrap.create(JavaArchive.class, embeddedArchiveName) .add(EmptyAsset.INSTANCE, emptyFileName); final WebArchive outerArchive = ShrinkWrap.create(WebArchive.class).addAsLibraries(embeddedArchive); // Now pull the embedded archive back out final JavaArchive roundtrip = outerArchive.getAsType(JavaArchive.class, ArchivePaths.create("WEB-INF/lib", embeddedArchiveName), this.getArchiveFormat()); Assert.assertTrue("roundtrip could not be obtained", roundtrip != null); Assert.assertTrue( "contents of embedded archive are not intact after roundtrip", roundtrip.contains(emptyFileName)); } }