/* * 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.api; import java.io.File; import java.io.IOException; import java.util.UUID; import java.util.zip.ZipException; import java.util.zip.ZipFile; import org.jboss.shrinkwrap.api.importer.ArchiveImportException; import org.jboss.shrinkwrap.api.importer.ZipImporter; import org.jboss.shrinkwrap.api.spec.WebArchive; /** * Responsible for creating {@link Archive}s, which may be presented to the caller in a designated {@link Assignable} * view. * * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a> * @author <a href="mailto:ken@glxn.net">Ken Gullaksen</a> * @version $Revision: $ */ public final class ArchiveFactory { // -------------------------------------------------------------------------------------|| // Class Members ----------------------------------------------------------------------|| // -------------------------------------------------------------------------------------|| /** * Implementation class name backing {@link Archive}s to be created */ private static final String ARCHIVE_IMPL = "org.jboss.shrinkwrap.impl.base.MemoryMapArchiveImpl"; // -------------------------------------------------------------------------------------|| // Instance Members -------------------------------------------------------------------|| // -------------------------------------------------------------------------------------|| /** * Configuration for all archives created from this factory */ private final Configuration configuration; // -------------------------------------------------------------------------------------|| // Constructor ------------------------------------------------------------------------|| // -------------------------------------------------------------------------------------|| /** * Creates a new {@link ArchiveFactory} which will use the supplied {@link Configuration} for each new * {@link Archive} it creates. * * @param configuration * the {@link Configuration} to use * @throws IllegalArgumentException * if configuration is not supplied */ ArchiveFactory(final Configuration configuration) throws IllegalArgumentException { // Precondition checks assert configuration != null : "configuration must be supplied"; // Set this.configuration = configuration; } // -------------------------------------------------------------------------------------|| // Functional Methods -----------------------------------------------------------------|| // -------------------------------------------------------------------------------------|| /** * Creates a new archive of the specified type. The archive will be be backed by the {@link Configuration} specific * to this {@link ArchiveFactory}. Generates a random name for the archive and adds proper extension based on the * service descriptor properties file if extension property is present (e.g. * shrinkwrap/impl-base/src/main/resources/META-INF/services/org.jboss.shrinkwrap.api.spec.JavaArchive) * * * @param type * The type of the archive e.g. {@link WebArchive} * @return An {@link Assignable} archive base * @throws IllegalArgumentException * if type is not specified * @throws UnknownExtensionTypeException * If no extension mapping is found for the specified type */ public <T extends Assignable> T create(final Class<T> type) throws IllegalArgumentException, UnknownExtensionTypeException { // Precondition checks if (type == null) { throw new IllegalArgumentException("Type must be specified"); } // Get the extensionType type final String extension = configuration.getExtensionLoader().getExtensionFromExtensionMapping(type); // Generate a random name String archiveName = UUID.randomUUID().toString(); // Delegate return create(type, archiveName += extension); } /** * Creates a new archive of the specified type. The archive will be be backed by the {@link Configuration} specific * to this {@link ArchiveFactory}. * * @param type * The type of the archive e.g. {@link org.jboss.shrinkwrap.api.spec.WebArchive} * @param archiveName * the archiveName to use * @return An {@link Assignable} view * @throws IllegalArgumentException * either argument is not supplied */ public <T extends Assignable> T create(final Class<T> type, final String archiveName) throws IllegalArgumentException { // Precondition checks if (type == null) { throw new IllegalArgumentException("Type must be specified"); } if (archiveName == null) { throw new IllegalArgumentException("ArchiveName must be specified"); } // Get the impl class final Class<?> archiveImplClass; try { archiveImplClass = ClassLoaderSearchUtil.findClassFromClassLoaders(ARCHIVE_IMPL, this.configuration.getClassLoaders()); } catch (final ClassNotFoundException cnfe) { throw new IllegalStateException("Could not find the archive implementation class " + ARCHIVE_IMPL + " in any configured ClassLoader", cnfe); } // Make a new instance final Archive<?> archive = SecurityActions.newInstance(archiveImplClass, new Class<?>[] { String.class, Configuration.class }, new Object[] { archiveName, configuration }, Archive.class); // Wrap as the requested type and return return archive.as(type); } /** * Creates a new archive of the specified type as imported from the specified {@link File}. The file is expected to * be encoded as ZIP (ie. JAR/WAR/EAR). The name of the archive will be set to {@link File#getName()}. The archive * will be be backed by the {@link Configuration} specific to this {@link ArchiveFactory}. * * @param type * The type of the archive e.g. {@link org.jboss.shrinkwrap.api.spec.WebArchive} * @param archiveFile * the archiveFile to use * @return An {@link Assignable} view * @throws IllegalArgumentException * If either argument is not supplied, if the specified {@link File} does not exist, or is not a valid * ZIP file * @throws org.jboss.shrinkwrap.api.importer.ArchiveImportException * If an error occurred during the import process */ public <T extends Assignable> T createFromZipFile(final Class<T> type, final File archiveFile) throws IllegalArgumentException, ArchiveImportException { // Precondition checks if (type == null) { throw new IllegalArgumentException("Type must be specified"); } if (archiveFile == null) { throw new IllegalArgumentException("File must be specified"); } if (!archiveFile.exists()) { throw new IllegalArgumentException("File for import does not exist: " + archiveFile.getAbsolutePath()); } if (archiveFile.isDirectory()) { throw new IllegalArgumentException("File for import must not be a directory: " + archiveFile.getAbsolutePath()); } try { // Import return ShrinkWrap.create(type, archiveFile.getName()).as(ZipImporter.class).importFrom(new ZipFile(archiveFile)).as(type); } catch (final ZipException ze) { throw new IllegalArgumentException("Does not appear to be a valid ZIP file: " + archiveFile.getAbsolutePath()); } catch (final IOException ioe) { throw new RuntimeException("I/O Error in importing new archive from ZIP: " + archiveFile.getAbsolutePath(), ioe); } } }