/*
* 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;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ArchiveFactory;
import org.jboss.shrinkwrap.api.ArchiveFormat;
import org.jboss.shrinkwrap.api.ArchivePath;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.Assignable;
import org.jboss.shrinkwrap.api.Configuration;
import org.jboss.shrinkwrap.api.ConfigurationBuilder;
import org.jboss.shrinkwrap.api.Domain;
import org.jboss.shrinkwrap.api.ExtensionLoader;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.UnknownExtensionTypeException;
import org.jboss.shrinkwrap.api.formatter.Formatter;
import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.api.spec.ResourceAdapterArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.impl.base.container.ContainerBase;
import org.jboss.shrinkwrap.impl.base.importer.ZipContentAssertionDelegate;
import org.junit.Test;
/**
* Tests ensuring that the static entry point {@link ShrinkWrap} is working as contracted.
*
* @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
* @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
* @version $Revision: $
*/
public class ShrinkWrapTestCase {
// -------------------------------------------------------------------------------------||
// Class Members ----------------------------------------------------------------------||
// -------------------------------------------------------------------------------------||
/**
* Delegate for performing ZIP content assertions
*/
private static final ZipContentAssertionDelegate delegate = new ZipContentAssertionDelegate();
/**
* The name of a simple TXT file
*/
private static final String NAME_FILE_NON_ZIP = "nonzipfile.txt";
// -------------------------------------------------------------------------------------||
// Tests ------------------------------------------------------------------------------||
// -------------------------------------------------------------------------------------||
/**
* Ensures we can create a new archive under the default {@link Domain}
*/
@Test
public void createNewArchiveUnderDefaultDomain() {
final String archiveName = "test.war";
final JavaArchive archive = ShrinkWrap.create(JavaArchive.class, archiveName);
// Test
Assert.assertNotNull("A archive should have been created", archive);
Assert.assertEquals("Should have the same name as given imput", archiveName, archive.getName());
}
/**
* Ensures that we can create isolated {@link Domain}s
*/
@Test
public void createIsolatedDomains() {
// Make a couple domains
final Domain domain1 = ShrinkWrap.createDomain();
final Domain domain2 = ShrinkWrap.createDomain();
// Ensure they exist
TestCase.assertNotNull("Domain should exist", domain1);
TestCase.assertNotNull("Domain should exist", domain2);
// Ensure they're not equal
TestCase.assertNotSame("Creation of domains should return new instances", domain1, domain2);
// Ensure the underlying configs are not equal
TestCase.assertNotSame("Creation of domains should have unique / isolated configurations",
domain1.getConfiguration(), domain2.getConfiguration());
}
/**
* Ensures that we can create a new {@link Domain} with explicit {@link Configuration}
*/
@Test
public void createDomainWithExplicitConfiguration() {
// Define configuration properties
final ExecutorService service = Executors.newSingleThreadExecutor();
final ExtensionLoader loader = new MockExtensionLoader();
// Create a new domain using these config props in a config
final Domain domain = ShrinkWrap.createDomain(new ConfigurationBuilder().executorService(service)
.extensionLoader(loader).build());
// Test
TestCase.assertEquals(ExecutorService.class.getSimpleName() + " specified was not contained in resultant "
+ Domain.class.getSimpleName(), service, domain.getConfiguration().getExecutorService());
TestCase.assertEquals(ExtensionLoader.class.getSimpleName() + " specified was not contained in resultant "
+ Domain.class.getSimpleName(), loader, domain.getConfiguration().getExtensionLoader());
}
/**
* Ensures that we can create a new {@link Domain} with explicit {@link ConfigurationBuilder}
*/
@Test
public void createDomainWithExplicitConfigurationBuilder() {
// Define configuration properties
final ExecutorService service = Executors.newSingleThreadExecutor();
final ExtensionLoader loader = new MockExtensionLoader();
// Create a new domain using these config props in a builder
final Domain domain = ShrinkWrap.createDomain(new ConfigurationBuilder().executorService(service)
.extensionLoader(loader));
// Test
TestCase.assertEquals(ExecutorService.class.getSimpleName() + " specified was not contained in resultant "
+ Domain.class.getSimpleName(), service, domain.getConfiguration().getExecutorService());
TestCase.assertEquals(ExtensionLoader.class.getSimpleName() + " specified was not contained in resultant "
+ Domain.class.getSimpleName(), loader, domain.getConfiguration().getExtensionLoader());
}
/**
* SHRINKWRAP-246 Ensures that the user may supply an explicit {@link ClassLoader} to the {@link Domain}, and this
* will be used when going via the {@link ArchiveFactory} to load archive extensions.
*/
@Test
public void serviceExtensionLoadingUsesExplicitDomainClassLoader() {
// Define the custom extension to attempt to load
final Class<? extends Assignable> assignable = CustomArchive.class;
// First ensure that we cannot get at the desired extension via traditional
// means (ie. TCCL)
try {
ShrinkWrap.create(assignable);
} catch (final UnknownExtensionTypeException uete) {
// Expected
}
// Define the ClassLoaders to search to use our new custom archive impl
final List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
classLoaders.add(TestSecurityActions.getThreadContextClassLoader());
classLoaders.add(new URLClassLoader(new URL[] {}) {
@Override
public InputStream getResourceAsStream(final String name) {
final String thisClassName = this.getClass().getName()
.substring(0, this.getClass().getName().length() - 1);
final String searchName = "META-INF/services/" + thisClassName + CustomArchive.class.getSimpleName();
if (name.equals(searchName)) {
return new ByteArrayInputStream(("implementingClassName=" + thisClassName
+ CustomArchiveImpl.class.getSimpleName() + "\nextension=.jar").getBytes());
} else {
return super.getResourceAsStream(name);
}
}
});
// Make a configuration and get the ArchiveFactory for it
final ConfigurationBuilder builder = new ConfigurationBuilder().classLoaders(classLoaders);
final ArchiveFactory factory = ShrinkWrap.createDomain(builder).getArchiveFactory();
// Now try to get the archive we asked for
final Assignable archive = factory.create(assignable);
Assert
.assertNotNull("Archive using custom extension available in explicit CL should have been loaded", archive);
}
public interface CustomArchive extends Assignable {
}
public static class CustomArchiveImpl extends GenericArchiveImpl implements CustomArchive {
public CustomArchiveImpl(final Archive<?> delegate) {
super(delegate);
}
}
/**
* Ensures we cannot create a new {@link Domain} with null {@link Configuration} specified
*/
@Test(expected = IllegalArgumentException.class)
public void newDomainRequiresConfiguration() {
ShrinkWrap.createDomain((Configuration) null);
}
/**
* Ensures we cannot create a new {@link Domain} with null {@link ConfigurationBuilder} specified
*/
@Test(expected = IllegalArgumentException.class)
public void newDomainRequiresConfigurationBuilder() {
ShrinkWrap.createDomain((ConfigurationBuilder) null);
}
/**
* Ensures all calls to get the default domain return the same reference
*/
@Test
public void getDefaultDomain() {
// Get the default domain twice
final Domain domain1 = ShrinkWrap.getDefaultDomain();
final Domain domain2 = ShrinkWrap.getDefaultDomain();
// Ensure they exist
TestCase.assertNotNull("Domain should exist", domain1);
TestCase.assertNotNull("Domain should exist", domain2);
// Ensure they're not equal
TestCase.assertSame(
"Obtaining the default domain should always return the same instance (idempotent operation)", domain1,
domain2);
}
/**
* Ensures that we may add extension overrides via the {@link ExtensionLoader} through some new {@link Domain}
*
* @throws Exception
*/
@Test
public void shouldBeAbleToAddOverride() throws Exception {
final Domain domain = ShrinkWrap.createDomain();
domain.getConfiguration().getExtensionLoader().addOverride(JavaArchive.class, MockJavaArchiveImpl.class);
final JavaArchive archive = domain.getArchiveFactory().create(JavaArchive.class, "test.jar");
Assert.assertEquals("Should have overridden normal JavaArchive impl", MockJavaArchiveImpl.class,
archive.getClass());
}
@Test
public void shouldCreateArchiveWithCorrectExtensionForJavaArchive() throws Exception {
JavaArchive javaArchive = ShrinkWrap.create(JavaArchive.class);
String archiveExtension = javaArchive.getName().substring(javaArchive.getName().lastIndexOf("."));
Assert.assertEquals("JavaArchive should have proper extension", ".jar", archiveExtension);
}
@Test
public void shouldCreateJavaArchiveWithGivenName() throws Exception {
String archiveName = "testArchive";
JavaArchive javaArchive = ShrinkWrap.create(JavaArchive.class, archiveName);
Assert.assertEquals("JavaArchive should have given name", archiveName, javaArchive.getName());
}
@Test
public void shouldCreateArchiveWithCorrectExtensionForWebArchive() throws Exception {
WebArchive webArchive = ShrinkWrap.create(WebArchive.class);
String archiveExtension = webArchive.getName().substring(webArchive.getName().lastIndexOf("."));
Assert.assertEquals("WebArchive should have proper extension", ".war", archiveExtension);
}
@Test
public void shouldCreateWebArchiveWithGivenName() throws Exception {
String archiveName = "testArchive";
WebArchive webArchive = ShrinkWrap.create(WebArchive.class, archiveName);
Assert.assertEquals("WebArchive should have given name", archiveName, webArchive.getName());
}
@Test
public void shouldCreateArchiveWithCorrectExtensionForEnterpriseArchive() throws Exception {
EnterpriseArchive enterpriseArchive = ShrinkWrap.create(EnterpriseArchive.class);
String archiveExtension = enterpriseArchive.getName().substring(enterpriseArchive.getName().lastIndexOf("."));
Assert.assertEquals("EnterpriseArchive should have proper extension", ".ear", archiveExtension);
}
@Test
public void shouldCreateEnterpriseArchiveWithGivenName() throws Exception {
String archiveName = "testArchive";
EnterpriseArchive enterpriseArchive = ShrinkWrap.create(EnterpriseArchive.class, archiveName);
Assert.assertEquals("EnterpriseArchive should have given name", archiveName, enterpriseArchive.getName());
}
@Test
public void shouldCreateArchiveWithCorrectExtensionForResourceAdapterArchive() throws Exception {
ResourceAdapterArchive resourceAdapterArchive = ShrinkWrap.create(ResourceAdapterArchive.class);
String archiveExtension = resourceAdapterArchive.getName().substring(
resourceAdapterArchive.getName().lastIndexOf("."));
Assert.assertEquals("ResourceAdapterArchive should have proper extension", ".rar", archiveExtension);
}
@Test
public void shouldCreateResourceAdapterArchiveWithGivenName() throws Exception {
String archiveName = "testArchive";
ResourceAdapterArchive resourceAdapterArchive = ShrinkWrap.create(ResourceAdapterArchive.class, archiveName);
Assert.assertEquals("ResourceAdapterArchive should have given name", archiveName,
resourceAdapterArchive.getName());
}
/**
* Ensures we can create a new Archive fro a ZIP file via {@link ShrinkWrap} convenience class
*/
@Test
public void shouldBeAbleToimportZipFileViaShrinkWrap() throws Exception {
// Get the test file
final File testFile = delegate.getExistingResource();
// Make a new archive via the default domain
final JavaArchive archive = ShrinkWrap.createFromZipFile(JavaArchive.class, testFile);
// Assert
Assert.assertNotNull("Should not return a null archive", archive);
Assert.assertEquals("name of the archive imported from a ZIP file was not as expected", testFile.getName(),
archive.getName());
delegate.assertContent(archive, testFile);
}
/**
* Ensures we can create a new Archive fro a ZIP file via an {@link ArchiveFactory}
*/
@Test
public void shouldBeAbleToimportZipFileViaArchiveFactory() throws Exception {
// Get the test file
final File testFile = delegate.getExistingResource();
// Make a new archive via the default domain
final JavaArchive archive = ShrinkWrap.getDefaultDomain().getArchiveFactory()
.createFromZipFile(JavaArchive.class, testFile);
// Assert
Assert.assertNotNull("Should not return a null archive", archive);
Assert.assertEquals("name of the archive imported from a ZIP file was not as expected", testFile.getName(),
archive.getName());
delegate.assertContent(archive, testFile);
}
/**
* Ensures that attempting to import as ZIP from a non-ZIP file leads to {@link IllegalArgumentException}
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void importFromNonZipFileThrowsException() throws Exception {
final File nonZipFile = new File(TestSecurityActions.getThreadContextClassLoader()
.getResource(NAME_FILE_NON_ZIP).toURI());
ShrinkWrap.createFromZipFile(JavaArchive.class, nonZipFile);
}
/**
* Ensures that attempting to import as ZIP from null file leads to {@link IllegalArgumentException}
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void importFromNullFileThrowsException() throws Exception {
ShrinkWrap.createFromZipFile(JavaArchive.class, null);
}
/**
* Ensures that attempting to import as ZIP from a {@link File} that doesn't exist leads to
* {@link IllegalArgumentException}
*
* @throws Exception
*/
@Test(expected = IllegalArgumentException.class)
public void importFromNonexistantlFileThrowsException() throws Exception {
final File file = new File("fileThatDoesntExist.tmp");
Assert.assertFalse("Error in test setup, file should not exist: " + file.getAbsolutePath(), file.exists());
ShrinkWrap.createFromZipFile(JavaArchive.class, null);
}
/**
* Ensures that creating a default name with no extension configured for a specified type results in
* {@link UnknownExtensionTypeException}
*
* SHRINKWRAP-163
*
* @throws Exception
*/
@Test(expected = UnknownExtensionTypeException.class)
public void shouldThrowExceptionOnNoConfiguredMappingForType() throws Exception {
ShrinkWrap.create(MockAssignable.class);
}
// -------------------------------------------------------------------------------------||
// Internal Helper Members ------------------------------------------------------------||
// -------------------------------------------------------------------------------------||
/**
* A Mock {@link ExtensionLoader} used only in testing reference equality
*
* @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
* @version $Revision: $
*/
private static class MockExtensionLoader implements ExtensionLoader {
@Override
public <T extends Assignable> T load(final Class<T> extensionClass, final Archive<?> baseArchive) {
return null;
}
@Override
public <T extends Assignable> ExtensionLoader addOverride(final Class<T> extensionClass,
final Class<? extends T> extensionImplClass) {
return null;
}
@Override
public <T extends Assignable> String getExtensionFromExtensionMapping(final Class<T> extensionClass) {
return null;
}
@Override
public <T extends Archive<T>> ArchiveFormat getArchiveFormatFromExtensionMapping(Class<T> extensionClass) {
return null;
}
}
/**
* Mock Archive wrapper implementation
*
* @author <a href="mailto:aslak@conduct.no">Aslak Knutsen</a>
* @version $Revision: $
*/
public static class MockJavaArchiveImpl extends ContainerBase<JavaArchive> implements JavaArchive {
public MockJavaArchiveImpl(Archive<?> archive) {
super(JavaArchive.class, archive);
}
@Override
protected ArchivePath getClassesPath() {
return ArchivePaths.root();
}
@Override
protected ArchivePath getLibraryPath() {
return ArchivePaths.root();
}
@Override
protected ArchivePath getManifestPath() {
return ArchivePaths.root();
}
@Override
protected ArchivePath getResourcePath() {
return ArchivePaths.root();
}
@Override
public String toString(final Formatter formatter) throws IllegalArgumentException {
return formatter.format(this);
}
}
/**
* Used in testing {@link Assignable} types without the need to function
*
* @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
* @version $Revision: $
*/
private static class MockAssignable implements Assignable {
@Override
public <TYPE extends Assignable> TYPE as(final Class<TYPE> clazz) {
// NO-OP
return null;
}
}
}