/**
* Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.seed.core.internal;
import com.google.common.base.Strings;
import com.google.inject.Module;
import io.nuun.kernel.api.plugin.InitState;
import io.nuun.kernel.api.plugin.context.InitContext;
import io.nuun.kernel.api.plugin.request.ClasspathScanRequest;
import org.seedstack.seed.Install;
import org.seedstack.seed.SeedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* Core plugin that configures base package roots and detects diagnostic collectors, dependency providers, Guice modules
* and configuration files.
*/
public class CorePlugin extends AbstractSeedPlugin {
static final String AUTODETECT_MODULES_KERNEL_PARAM = "seedstack.autodetectModules";
private static final Logger LOGGER = LoggerFactory.getLogger(CorePlugin.class);
private static final String SEEDSTACK_PACKAGE = "org.seedstack";
private final Set<Class<? extends Module>> seedModules = new HashSet<>();
@Override
public String name() {
return "core";
}
@Override
public String pluginPackageRoot() {
return SEEDSTACK_PACKAGE;
}
@Override
public Collection<ClasspathScanRequest> classpathScanRequests() {
return classpathScanRequestBuilder()
.annotationType(Install.class)
.build();
}
@SuppressWarnings("unchecked")
@Override
public InitState initialize(InitContext initContext) {
String autodetectModules = initContext.kernelParam(AUTODETECT_MODULES_KERNEL_PARAM);
if (Strings.isNullOrEmpty(autodetectModules) || Boolean.parseBoolean(autodetectModules)) {
detectModules(initContext);
}
return InitState.INITIALIZED;
}
@SuppressWarnings("unchecked")
private void detectModules(InitContext initContext) {
initContext.scannedClassesByAnnotationClass().get(Install.class)
.stream()
.filter(Module.class::isAssignableFrom)
.forEach(candidate -> {
seedModules.add((Class<Module>) candidate);
LOGGER.trace("Detected module to install {}", candidate.getCanonicalName());
});
LOGGER.debug("Detected {} module(s) to install", seedModules.size());
}
@Override
public Object nativeUnitModule() {
Collection<Module> subModules = new HashSet<>();
for (Class<? extends Module> klazz : seedModules) {
try {
Constructor<? extends Module> declaredConstructor = klazz.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
subModules.add(declaredConstructor.newInstance());
} catch (Exception e) {
throw SeedException.wrap(e, CoreErrorCode.UNABLE_TO_INSTANTIATE_MODULE).put("module", klazz.getCanonicalName());
}
}
return new CoreModule(subModules);
}
}