org.jboss.shrinkwrap.api.ConfigurationBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of shrinkwrap-api Show documentation
Show all versions of shrinkwrap-api Show documentation
Client View of the ShrinkWrap Project
/*
* JBoss, Home of Professional Open Source
* Copyright 2010, 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.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Mutable construction object for new instances of {@link Configuration}. Provides defaults for each property if not
* specified (null) according to the following:
*
*
* executorService
- Stay null, none is required and ShrinkWrap will create its own and destroy it when
* done as needed
* extensionLoader
- A new instance of the service extension loader from shrinkwrap-impl
*
*
* Not thread-safe. When done altering properties here, a new configuration may be constructed by calling upon
* {@link ConfigurationBuilder#build()}.
*
* @author ALR
* @author Ken Gullaksen
* @version $Revision: $
*/
public class ConfigurationBuilder {
// -------------------------------------------------------------------------------------||
// Class Members ----------------------------------------------------------------------||
// -------------------------------------------------------------------------------------||
/**
* Logger
*/
private static final Logger log = Logger.getLogger(ConfigurationBuilder.class.getName());
/**
* Implementation class name of the default {@link ExtensionLoader} to be used
*/
private static final String EXTENSION_LOADER_IMPL = "org.jboss.shrinkwrap.impl.base.ServiceExtensionLoader";
// -------------------------------------------------------------------------------------||
// Instance Members -------------------------------------------------------------------||
// -------------------------------------------------------------------------------------||
/**
* Loader mapping archive types to the appropriate underlying implementation
*/
private ExtensionLoader extensionLoader;
/**
* {@link ExecutorService} used for all asynchronous operations
*/
private ExecutorService executorService;
/**
* {@link ClassLoader}s used for extension loading, adding resources, etc
*/
private Iterable classLoaders;
// -------------------------------------------------------------------------------------||
// Constructor ------------------------------------------------------------------------||
// -------------------------------------------------------------------------------------||
/**
* Creates a new builder initialized to defaults (null) values. Any properties not explicitly provided by the user
* will be defaulted during {@link ConfigurationBuilder#build()}.
*/
public ConfigurationBuilder() {
}
// -------------------------------------------------------------------------------------||
// Functional Methods ----------------------------------------------------------------||
// -------------------------------------------------------------------------------------||
/**
* @return the extensionLoader
*/
public ExtensionLoader getExtensionLoader() {
return extensionLoader;
}
/**
* @return the executorService
*/
public ExecutorService getExecutorService() {
return executorService;
}
/**
* @return
*/
public Iterable getClassLoaders() {
return classLoaders;
}
/**
* Sets the {@link ExtensionLoader} to be used, returning this instance
*
* @param extensionLoader
* @return
*/
public ConfigurationBuilder extensionLoader(final ExtensionLoader extensionLoader) {
this.extensionLoader = extensionLoader;
return this;
}
/**
* Sets the {@link ExecutorService} to be used, returning this instance
*
* @param executorService
* @return
*/
public ConfigurationBuilder executorService(final ExecutorService executorService) {
this.executorService = executorService;
return this;
}
/**
* Sets the {@link ClassLoader} used in resolving extension implementations by the {@link ExtensionLoader}; other
* tasks requiring a CL by the {@link Archive}
*
* @param classLoaders
* @return
*/
public ConfigurationBuilder classLoaders(final Iterable classLoaders) {
this.classLoaders = classLoaders;
return this;
}
/**
* Builds a new {@link Configuration} using the properties contained in this builder. In the case a property has not
* been specified, it will be defaulted according to the rules set forth in this {@link ConfigurationBuilder}'s
* contract.
*
* @return
*/
public Configuration build() {
// Make a new configuration and return it.
return new Configuration(this);
}
// -------------------------------------------------------------------------------------||
// Internal Helper Methods -----------------------------------------------------------||
// -------------------------------------------------------------------------------------||
/**
* Sets properties to their default values if they haven't been explicitly provided by the user. If no ClassLoaders
* are specified, use the TCCL.
*/
void setDefaults() {
// If no ClassLoaders are specified, use the TCCL
// Ensure we default this BEFORE defaulting the extension loader, as
// the loader needs a CL to be created
if (this.getClassLoaders() == null) {
final ClassLoader tccl = SecurityActions.getThreadContextClassLoader();
if (log.isLoggable(Level.FINER)) {
log.finer("User has not defined an explicit " + ClassLoader.class.getSimpleName()
+ "; defaulting to the TCCL: " + tccl);
}
final Collection tcclCollection = new ArrayList(1);
// Adjust for the bootstrap CL, which may be denoted as null in some JVM impls
if (tccl != null) {
tcclCollection.add(tccl);
} else {
tcclCollection.add(ClassLoader.getSystemClassLoader());
}
this.classLoaders = tcclCollection;
}
// Adjust the CLs to be sure of no duplicate or null references (which may indicate
// the bootstrap CL, so get to the system CL)
final Collection adjustedCls = new HashSet();
for (ClassLoader cl : this.classLoaders) {
// Adjust for null references
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
// Add to the set, which will restrict duplicates
adjustedCls.add(cl);
}
this.classLoaders = adjustedCls;
// If no extension loader is present, create one
if (getExtensionLoader() == null) {
final ExtensionLoader loader = createDefaultExtensionLoader();
if (log.isLoggable(Level.FINER)) {
log.finer("User has not defined an explicit " + ExtensionLoader.class.getSimpleName()
+ "; defaulting to " + loader);
}
this.extensionLoader(loader);
}
}
/**
* Obtains the default {@link ExtensionLoader} to be used if none is specified
*
* @return
*/
ExtensionLoader createDefaultExtensionLoader() {
// First find the right Class/ClassLoader
final Class> extensionLoaderImplClass;
try {
extensionLoaderImplClass = ClassLoaderSearchUtil.findClassFromClassLoaders(EXTENSION_LOADER_IMPL,
getClassLoaders());
} catch (final ClassNotFoundException cnfe) {
throw new IllegalStateException(
"Could not find extension loader impl class in any of the configured ClassLoaders", cnfe);
}
// Return
return SecurityActions.newInstance(extensionLoaderImplClass, new Class>[] { Iterable.class },
new Object[] { this.getClassLoaders() }, ExtensionLoader.class);
}
}