/*
* 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));
}
}