Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package restx;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Stopwatch;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.google.common.net.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import restx.classloader.ColdClasses;
import restx.classloader.CompilationFinishedEvent;
import restx.classloader.CompilationManager;
import restx.classloader.CompilationSettings;
import restx.classloader.HotReloadingClassLoader;
import restx.common.MoreClasses;
import restx.common.RestxConfig;
import restx.common.metrics.api.MetricRegistry;
import restx.factory.Factory;
import restx.factory.Name;
import restx.factory.NamedComponent;
import restx.factory.SingletonFactoryMachine;
import restx.factory.StdWarehouse;
import restx.factory.Warehouse;
import restx.http.HttpStatus;
import restx.security.RestxSessionCookieFilter;
import restx.server.WebServer;
import restx.server.WebServers;
import restx.specs.RestxSpec;
import restx.specs.RestxSpecRecorder;
import restx.specs.RestxSpecRecorder.GivenRecorder;
import restx.specs.RestxSpecTape;
import javax.tools.Diagnostic;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getLast;
import static restx.common.MoreStrings.indent;
/**
* User: xavierhanin
* Date: 2/16/13
* Time: 3:40 PM
*/
public class RestxMainRouterFactory {
private static final Logger logger = LoggerFactory.getLogger(RestxMainRouterFactory.class);
private static final Map routers = new HashMap<>();
public static synchronized RestxMainRouter newInstance(final String serverId, Optional baseUri) {
checkNotNull(serverId);
RestxMainRouter router = routers.get(serverId);
if (router == null) {
AppSettings settings = loadFactory(newFactoryBuilder(serverId))
.getComponent(AppSettings.class);
router = new RestxMainRouterFactory(settings).build(serverId, baseUri);
}
return router;
}
public static synchronized Optional getInstance(String serverId) {
return Optional.fromNullable(routers.get(serverId));
}
public static synchronized void clear(String serverId) {
routers.remove(serverId);
Optional factory = Factory.getFactory(serverId);
if (factory.isPresent()) {
factory.get().close();
Factory.unregister(serverId, factory.get());
}
}
/**
* A blade is a context of test execution, it can be reused between tests, but can't be used concurrently.
*
* This allow to have a test client used to run tests concurrently, each thread executing tests being
* considered as a test blade. It allows to have some heavy components (like a database) initialized
* only once per blade.
*
* This works only when using a per request factory loading.
*/
public static final class Blade {
private static final AtomicLong BLADE_COUNTER = new AtomicLong();
private static final ThreadLocal BLADE = new ThreadLocal() {
@Override
protected String initialValue() {
return "BLADE-" + BLADE_COUNTER.incrementAndGet();
}
};
public static String current() {
return BLADE.get();
}
public static String contextId(String serverId, String bladeId) {
return serverId + "-" + bladeId;
}
public static Factory.LocalMachines bladeLocalMachines(String serverId) {
return Factory.LocalMachines.contextLocal(contextId(serverId, current()));
}
}
/**
* A main router decorator that may record all or some requests.
*
* Note that the provided router is only used for non recorded requests.
* The recorded requests are using a StdRestxMainRouter with a factory initialized per request,
* to allow recorders to be properly setup in the router factory.
*
* Therefore this class is not intended to be exposed outside the main router factory class.
*/
private class RecordingMainRouter implements RestxMainRouter {
private final RestxMainRouter router;
private final String serverId;
private final RestxSpec.Storage storage;
private final RestxSpec.StorageSettings storageSettings;
private final RestxSpecRecorder.Repository repository;
public RecordingMainRouter(String serverId,
RestxMainRouter router,
RestxSpec.StorageSettings storageSettings) {
this.serverId = serverId;
this.router = router;
this.storageSettings = storageSettings;
this.storage = RestxSpec.Storage.with(storageSettings);
this.repository = new RestxSpecRecorder.Repository();
}
@Override
public void route(final RestxRequest restxRequest, final RestxResponse restxResponse) throws IOException {
Factory.LocalMachines.threadLocal().set("RecordedSpecsRepository", repository);
if (!restxRequest.getRestxPath().startsWith("/@/")
&& RestxContext.Modes.RECORDING.equals(getMode(restxRequest))) {
logger.debug("RECORDING {}", restxRequest);
Factory factory = Factory.newInstance();
Set recorders = factory.getComponents(RestxSpecRecorder.GivenRecorder.class);
RestxSessionCookieFilter sessionFilter = factory.getComponent(RestxSessionCookieFilter.class);
final RestxSpecRecorder restxSpecRecorder = new RestxSpecRecorder(
recorders, sessionFilter, storageSettings, repository);
try {
Optional recordPath = restxRequest.getHeader("RestxRecordPath");
RestxSpecTape tape = restxSpecRecorder.record(restxRequest, restxResponse,
recordPath, restxRequest.getHeader("RestxRecordTitle"));
try {
router.route(tape.getRecordingRequest(), tape.getRecordingResponse());
} finally {
RestxSpecRecorder.RecordedSpec recordedSpec = restxSpecRecorder.stop(tape);
if (recordPath.isPresent()) {
if (recordedSpec.getSpec() == null) {
logger.warn("can't save spec, not properly recorded for {}", restxRequest);
} else {
// save directly the recorded spec
File recordFile = storage.store(recordedSpec.getSpec());
logger.info("saved recorded spec in {}", recordFile);
}
}
}
} catch (IOException e) {
throw e;
} catch (Exception e) {
Throwables.propagate(e);
}
} else {
router.route(restxRequest, restxResponse);
}
}
}
private class PerRequestFactoryLoader implements RestxMainRouter {
private final String serverId;
private final Warehouse warehouse;
public PerRequestFactoryLoader(String serverId, Warehouse warehouse) {
this.serverId = serverId;
this.warehouse = warehouse;
}
@Override
public void route(RestxRequest restxRequest, RestxResponse restxResponse) throws IOException {
Stopwatch stopwatch = Stopwatch.createStarted();
Factory factory = loadFactory(newFactoryBuilder(
serverId,
restxRequest.getHeader("RestxBlade"),
restxRequest.getHeader("RestxThreadLocal"),
getMode(restxRequest))
.addWarehouseProvider(warehouse));
if ("cleanrequest".equals(getLoadFactoryMode())) {
// in clean request mode auto startable components are started and cleaned per request
try {
factory.start();
} catch (Exception ex) {
logger.error("Exception when using factory to start components on clean request: " + ex.getMessage(), ex);
Throwables.propagate(ex);
}
}
factory.prepare();
try {
StdRestxMainRouter stdRestxMainRouter = newStdRouter(factory);
if (stopwatch.elapsed(TimeUnit.MILLISECONDS) > 200) {
logger.info("{} - per request factory created in {}", restxRequest, stopwatch);
} else {
logger.debug("{} - per request factory created in {}", restxRequest, stopwatch);
}
stdRestxMainRouter.route(restxRequest, restxResponse);
} catch (Factory.UnsatisfiedDependenciesException ex) {
if (restxRequest.getHeader("RestxDebug").isPresent()) {
logger.error("{} - Exception when using factory to load router: {}\n{}",
restxRequest, ex.getMessage(), factory.dumper());
} else {
logger.error("{} - Exception when using factory to load router: {}\n" +
"Pro Tip: Set HTTP Header RestxDebug to have a dump of the factory" +
" in your logs when you get this error.", restxRequest, ex.getMessage());
}
throw ex;
} finally {
factory.close();
}
}
}
/**
* Enables hot reload: this rely on classes compiled by an external compiler
*/
private class HotReloadRouter implements RestxMainRouter {
private final RestxMainRouter delegate;
private final String rootPackage;
private final Supplier> coldClasses;
public HotReloadRouter(RestxMainRouter delegate, Supplier> coldClasses) {
this.delegate = delegate;
this.coldClasses = Suppliers.memoize(coldClasses);
this.rootPackage = appSettings.appPackage().get();
}
@Override
public void route(RestxRequest restxRequest, RestxResponse restxResponse) throws IOException {
ClassLoader previousLoader =
Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(new HotReloadingClassLoader(
previousLoader, rootPackage, coldClasses.get()));
delegate.route(restxRequest, restxResponse);
} catch (Factory.UnsatisfiedDependenciesException ex) {
handleUnsatisfiedDependencyOnHotReload(restxResponse, ex, rootPackage);
} finally {
Thread.currentThread().setContextClassLoader(previousLoader);
}
}
}
private class CompilationManagerRouter implements RestxMainRouter {
private final RestxMainRouter delegate;
private final String rootPackage;
private final CompilationManager compilationManager;
private final Supplier> coldClasses;
private ClassLoader classLoader;
public CompilationManagerRouter(RestxMainRouter delegate, EventBus eventBus,
Supplier> coldClasses, CompilationSettings compilationSettings) {
this.delegate = delegate;
this.coldClasses = Suppliers.memoize(coldClasses);
this.rootPackage = appSettings.appPackage().get();
compilationManager = Apps.with(appSettings).newAppCompilationManager(eventBus, compilationSettings);
eventBus.register(new Object() {
@Subscribe
public void onCompilationFinished(
CompilationFinishedEvent event) {
synchronized (CompilationManagerRouter.this) {
classLoader = null;
}
}
});
compilationManager.incrementalCompile();
if (useAutoCompile()) {
compilationManager.startAutoCompile();
}
}
private void setClassLoader() {
classLoader = compilationManager.newHotReloadingClassLoader(rootPackage, coldClasses.get());
}
@Override
public void route(RestxRequest restxRequest, RestxResponse restxResponse) throws IOException {
ClassLoader previousLoader =
Thread.currentThread().getContextClassLoader();
try {
if (!useAutoCompile()) {
compilationManager.incrementalCompile();
}
Collection> lastDiagnostics = compilationManager.getLastDiagnostics();
if (!lastDiagnostics.isEmpty()) {
restxResponse.setStatus(HttpStatus.SERVICE_UNAVAILABLE);
restxResponse.setContentType(MediaType.PLAIN_TEXT_UTF_8.toString());
PrintWriter restxResponseWriter = restxResponse.getWriter();
restxResponseWriter.write("COMPILATION ERROR(S):\n\n\n");
for (Diagnostic> d : lastDiagnostics) {
if (d.getKind() != Diagnostic.Kind.NOTE) {
restxResponseWriter.write(d + "\n\n");
}
}
return;
}
synchronized (this) {
if (classLoader == null) {
setClassLoader();
}
}
Thread.currentThread().setContextClassLoader(classLoader);
delegate.route(restxRequest, restxResponse);
} catch (Factory.UnsatisfiedDependenciesException ex) {
handleUnsatisfiedDependencyOnHotReload(restxResponse, ex, rootPackage);
} finally {
Thread.currentThread().setContextClassLoader(previousLoader);
}
}
}
private final AppSettings appSettings;
private RestxMainRouterFactory(AppSettings appSettings) {
this.appSettings = appSettings;
}
private RestxMainRouter build(final String serverId, Optional baseUri) {
checkNotNull(serverId);
checkNotNull(baseUri);
logger.info("LOADING MAIN ROUTER");
if (RestxContext.Modes.DEV.equals(getMode()) && !useHotCompile()) {
logger.info("\nHot compile is not enabled, no on the fly compilation will be performed\n" +
"To enable it, use '-Drestx.app.package= -Drestx.router.hotcompile=true' as VM argument\n" +
"and make sure you have JDK tools.jar in your classpath");
if (!useHotReload()) {
logger.info("\nHot reload is not enabled either, no hot reload on recompilation will be performed\n" +
"To enable it, use '-Drestx.app.package= -Drestx.router.hotreload=true' as VM argument");
}
}
if (getLoadFactoryMode().equals("onstartup")) {
if (RestxContext.Modes.RECORDING.equals(getMode())) {
throw new IllegalStateException("can't use RECORDING mode without per request factory loading");
}
Factory factory = loadFactory(newFactoryBuilder(serverId));
factory = Factory.register(serverId, factory);
StdRestxMainRouter mainRouter = newStdRouter(factory);
routers.put(serverId, mainRouter);
factory.start().and().prepare();
logPrompt(baseUri, "READY", mainRouter);
return mainRouter;
} else if (getLoadFactoryMode().equals("onrequest")
|| getLoadFactoryMode().equals("cleanrequest")) {
logPrompt(baseUri, ">> LOAD ON REQUEST <<"
+ (getLoadFactoryMode().equals("cleanrequest") ? " >> CLEAN <<" : ""), null);
// keep a reference on the classloader loading factory initial classes, we will need to it
// to load cold classes
ClassLoader mainFactoryClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader previous = Thread.currentThread().getContextClassLoader();
if (useAutoCompile()) {
CompilationManager compilationManager = Apps.with(appSettings).newAppCompilationManager(
new EventBus(), CompilationManager.DEFAULT_SETTINGS);
compilationManager.incrementalCompile();
HotReloadingClassLoader hotReloadingClassLoader = compilationManager.newHotReloadingClassLoader(
appSettings.appPackage().get(), ImmutableSet.of());
mainFactoryClassLoader = hotReloadingClassLoader;
Thread.currentThread().setContextClassLoader(
hotReloadingClassLoader);
}
// Create a Factory to load autotartable components
// then one factory will be created for each request.
// The warehouse of this first factory will be shared among all factories created for this router,
// making autostartable components live tied to the router itself and not per request
// in 'cleanrequest' mode, this factory is not actually used, autostartable components
// are started per request
Factory factory;
try {
factory = loadFactory(newFactoryBuilder(serverId));
factory = Factory.register(serverId, factory);
} finally {
Thread.currentThread().setContextClassLoader(previous);
}
Warehouse warehouse = getLoadFactoryMode().equals("cleanrequest") ? new StdWarehouse() : factory.getWarehouse();
RestxMainRouter router = new PerRequestFactoryLoader(serverId, warehouse);
// this factory is used to look up settings only
// we don't use 'factory' instance to avoid having settings built into the autostartable factory
Factory settingsFactory = loadFactory(newFactoryBuilder(serverId));
// wrap in a recording router, as any request may ask for recording with RestxMode header
router = new RecordingMainRouter(serverId, router,
settingsFactory.getComponent(RestxSpec.StorageSettings.class));
// wrap in hot reloading or hoy compile router if needed.
// this must be the last wrapping so that the classloader is used for the full request, including
// for recording
if (useHotCompile()) {
final RestxConfig config = settingsFactory.getComponent(RestxConfig.class);
router = new CompilationManagerRouter(router, factory.getComponent(EventBus.class),
getColdClasses(mainFactoryClassLoader, factory, appSettings),
new CompilationSettings() {
@Override
public int autoCompileCoalescePeriod() {
return config.getInt("restx.fs.watch.coalesce.period").get();
}
@Override
public Predicate classpathResourceFilter() {
return CompilationManager.DEFAULT_CLASSPATH_RESOURCE_FILTER;
}
});
} else if (useHotReload()) {
router = new HotReloadRouter(router, getColdClasses(mainFactoryClassLoader, factory, appSettings));
}
routers.put(serverId, router);
if (getLoadFactoryMode().equals("onrequest")) {
factory.start();
}
return router;
} else {
throw new IllegalStateException("illegal load factory mode: '" + getLoadFactoryMode() + "'. " +
"It must be either 'onstartup', 'onrequest' or 'cleanrequest'.");
}
}
private void logPrompt(Optional baseUri, String state, StdRestxMainRouter mainRouter) {
logger.info("\n" +
"--------------------------------------\n" +
" -- RESTX " + state + " >> " + getMode().toUpperCase(Locale.ENGLISH)+ " MODE <<" +
getHotIndicator() + "\n" +
(mainRouter != null ? (" -- " + mainRouter.getNbFilters() + " filters\n") : "") +
(mainRouter != null ? (" -- " + mainRouter.getNbRoutes() + " routes\n") : "") +
(baseUri.or("").isEmpty() ? "" :
" -- for admin console,\n" +
" -- VISIT " + baseUri.get() + "/@/ui/\n") +
" --\n");
}
private String getHotIndicator() {
if (useAutoCompile()) {
return " >> AUTO COMPILE <<";
}
if (useHotCompile()) {
return " >> HOT COMPILE <<";
}
if (useHotReload()) {
return " >> HOT RELOAD <<";
}
return "";
}
private static Factory loadFactory(Factory.Builder builder) {
Factory factory = builder.build();
logger.debug("restx factory ready: {}", factory.dumper());
return factory;
}
private static Factory.Builder newFactoryBuilder(String serverId,
Optional bladeId,
Optional threadLocalId,
String mode) {
Factory.Builder builder = newFactoryBuilder(serverId);
if (threadLocalId.isPresent()) {
builder.addLocalMachines(Factory.LocalMachines.threadLocalFrom(threadLocalId.get()));
}
if (bladeId.isPresent()) {
builder.addLocalMachines(Factory.LocalMachines.contextLocal(Blade.contextId(serverId, bladeId.get())));
}
builder.addMachine(new SingletonFactoryMachine<>(
-100000, NamedComponent.of(String.class, "restx.mode", mode)));
return builder;
}
private static Factory.Builder newFactoryBuilder(String serverId) {
Factory.Builder builder = newFactoryBuilder();
if (serverId != null) {
builder.addLocalMachines(Factory.LocalMachines.contextLocal(serverId));
// make server id and base url accessible in the factory components
Optional serverById = WebServers.getServerById(serverId);
builder
.addMachine(new SingletonFactoryMachine<>(
0, NamedComponent.of(String.class, "restx.server.id", serverId)))
.addMachine(new SingletonFactoryMachine<>(
0, NamedComponent.of(String.class, "restx.server.baseUrl",
serverById.isPresent() ? serverById.get().baseUrl() : "")))
.addMachine(new SingletonFactoryMachine<>(
0, NamedComponent.of(String.class, "restx.server.port",
serverById.isPresent() ? String.valueOf(serverById.get().getPort()) : "")))
.addMachine(new SingletonFactoryMachine<>(
0, NamedComponent.of(String.class, "restx.server.type",
serverById.isPresent() ? serverById.get().getServerType() : "")))
;
}
return builder;
}
private static Factory.Builder newFactoryBuilder() {
return Factory.builder()
.addFromServiceLoader()
.addLocalMachines(Factory.LocalMachines.threadLocal())
;
}
private StdRestxMainRouter newStdRouter(Factory factory) {
return new StdRestxMainRouter(
factory.getComponent(MetricRegistry.class),
factory.getComponent(RestxRouting.class),
factory.getComponent(Name.of(String.class, "restx.mode")));
}
private String getLoadFactoryMode() {
if (appSettings.factoryLoadMode().isPresent()) {
return appSettings.factoryLoadMode().get();
}
if (RestxContext.Modes.TEST.equals(getMode())
|| RestxContext.Modes.INFINIREST.equals(getMode())) {
return "cleanrequest";
} else if (RestxContext.Modes.RECORDING.equals(getMode())
|| useHotCompile()
|| useHotReload()) {
return "onrequest";
} else {
return "onstartup";
}
}
private boolean useHotReload() {
if (appSettings.hotReload().or(Boolean.FALSE)) {
// hotreload is explicitly set
if (!appSettings.appPackage().isPresent()) {
logger.info("can't enable hot reload: restx.app.package is not set.\n" +
"Run your app with -Drestx.app.package= to enable hot reload.");
return false;
} else {
return true;
}
} else {
return appSettings.hotReload().or(Boolean.TRUE)
&& !getMode().equals(RestxContext.Modes.PROD)
&& !getMode().equals(RestxContext.Modes.TEST)
&& appSettings.appPackage().isPresent();
}
}
private boolean useHotCompile() {
if (appSettings.hotCompile().or(Boolean.FALSE)
|| appSettings.autoCompile().or(Boolean.FALSE)) {
// hotcompile or autocompile is explicitly set
if (!appSettings.appPackage().isPresent()) {
logger.info("can't enable hot compile: restx.app.package is not set.\n" +
"Run your app with -Drestx.app.package= to enable hot compile.");
return false;
} else if (!hasSystemJavaCompiler()) {
logger.info("can't enable hot compile: tools.jar is not in classpath.\n" +
"Run your app with a JDK rather than a JRE to enable hot compile.");
return false;
} else {
return true;
}
} else {
return appSettings.hotCompile().or(Boolean.TRUE)
&& !getMode().equals(RestxContext.Modes.PROD)
&& !getMode().equals(RestxContext.Modes.TEST)
&& appSettings.appPackage().isPresent()
&& hasSystemJavaCompiler();
}
}
private String getMode() {
return appSettings.mode();
}
private String getMode(RestxRequest restxRequest) {
return restxRequest.getHeader("RestxMode").or(getMode());
}
private boolean hasSystemJavaCompiler() {
return Apps.hasSystemJavaCompiler();
}
private boolean useAutoCompile() {
return appSettings.autoCompile().or(Boolean.TRUE)
&& useHotCompile();
}
private static void handleUnsatisfiedDependencyOnHotReload(
RestxResponse restxResponse, Factory.UnsatisfiedDependenciesException ex, String hotPackage) throws IOException {
restxResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);
PrintWriter writer = restxResponse.getWriter();
// let's check one possible cause which is hard to understand: circular dependencies between
// hot and cold classes - ie classes part of hot reload and classes outside hot reload
boolean hotColdFound = false;
for (Factory.UnsatisfiedDependency unsatisfiedDependency :
ex.getUnsatisfiedDependencies().getUnsatisfiedDependencies()) {
if (unsatisfiedDependency.getPath().isEmpty()) {
continue;
}
Class> dependerClass = getLast(unsatisfiedDependency.getPath()).getName().getClazz();
Class> dependeeClass = unsatisfiedDependency.getUnsatisfied().getComponentClass();
if (!dependerClass.getName().startsWith(hotPackage)
&& dependeeClass.getName().startsWith(hotPackage)) {
// we have found a dependency from cold to hot class
String msg = String.format(">>>>>> SOURCE CODE ERROR >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" +
"You are currently using hot reload feature of RESTX which has some limitations.\n\n" +
"You can't inject a component which is hot reloaded (called a 'Hot' component)\n" +
" into a component which is not hot reloaded (called a 'Cold' component)\n" +
"\n" +
"Such a dependency from a 'Cold' class to a 'Hot' class has been found in your sources:\n\n" +
" `%s`\n" +
" ^------------------------------------- HOT because it is in package `%s`\n\n" +
" is injected into\n\n" +
" `%s`\n" +
" ^------------------------------------- COLD because it is NOT in package `%s`\n" +
"\n\n" +
" >>> THIS IS NOT SUPPORTED, IT CAUSES CLASSLOADING ERRORS <<<\n" +
"\n\n" +
"Possible solutions:\n" +
"===================\n\n" +
"1) remove that dependency\n" +
" Check the source of `%s`\n" +
" and remove its dependency on `%s`\n\n" +
"2) change which classes are hot reloaded\n" +
" Classes which are hot reloaded are in package `%s`.\n" +
" You can change that by setting the `restx.app.package` system property.\n\n" +
"3) don't use hot compile mode\n" +
" Use production mode\n" +
" or explicitly disable it by setting `restx.router.hotcompile`\n" +
" and / or `restx.router.hotreload` to false\n\n" +
">>>>>> SOURCE CODE ERROR >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n",
dependeeClass.getName(), hotPackage,
dependerClass.getName(), hotPackage,
dependerClass.getName(), dependeeClass.getName(),
hotPackage);
logger.error("\n\n" + msg);
writer.println(msg);
hotColdFound = true;
break;
}
}
if (!hotColdFound) {
String msg =
"Error when loading Factory to process your request.\n" +
"One or more dependency injections can be satisfied.\n\n" +
indent(ex.getMessage(), 2);
logger.error(msg);
writer.println(msg);
}
}
/**
* Supplies cold classes.
*
* Cold classes are:
* - all components classes of the specified factory
* - all components inherited classes
* - all cold classes specified in the app settings (setting "coldClasses")
*
* All cold classes need to be loaded using the same classloader, so for the ones loaded from the property, the same classloader than
* the one used to load the components need to be used.
*/
private static Supplier> getColdClasses(final ClassLoader mainFactoryClassLoader, final Factory factory, final AppSettings appSettings) {
return new Supplier>() {
@Override
public ImmutableSet get() {
Collection coldClasses = new HashSet<>();
for (Name> name : factory.getWarehouse().listNames()) {
Optional> c = factory.queryByName(name).findOneAsComponent();
if (c.isPresent()) {
coldClasses.add(c.get().getClass()); // add the component's class
coldClasses.addAll(MoreClasses.getInheritedClasses(c.get().getClass())); // add all inherited classes
} else {
logger.debug(
"invalid cold class {}: found in factory warehouse but not available as component." +
" Ignored.", name);
}
}
// also add in cold classes, cold classes defined in app settings
coldClasses.addAll(appSettings.coldClasses().transform(
new Function>>() {
@Override
public ImmutableSet> apply(String input) {
return ColdClasses.extractFromString(mainFactoryClassLoader, input);
}
}
).or(ImmutableSet.>of()));
// and finally try to get some cold classes from resources files
try {
coldClasses.addAll(ColdClasses.extractFromResources(mainFactoryClassLoader));
} catch (IOException e) {
logger.warn("Unable to extract cold classes from resources, due to {}", e.getMessage());
}
logger.debug("cold classes: {}", coldClasses);
return ImmutableSet.copyOf(coldClasses);
}
};
}
}