package org.atomnuke.fallout.service.loader;
import org.atomnuke.container.packaging.loader.PackageLoader;
import java.io.File;
import java.net.URI;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import org.atomnuke.container.packaging.bindings.BindingEnvironmentFactory;
import org.atomnuke.container.packaging.bindings.PackageLoadingException;
import org.atomnuke.container.packaging.DeployedPackage;
import org.atomnuke.container.packaging.PackageContext;
import org.atomnuke.container.packaging.Unpacker;
import org.atomnuke.container.packaging.UnpackerException;
import org.atomnuke.container.packaging.archive.zip.ArchiveExtractor;
import org.atomnuke.container.packaging.bindings.environment.BindingEnvironmentManagerImpl;
import org.atomnuke.container.packaging.loader.impl.BindingAwarePackageLoader;
import org.atomnuke.container.packaging.resource.ResourceManager;
import org.atomnuke.container.packaging.resource.ResourceManagerImpl;
import org.atomnuke.container.service.annotation.NukeBootstrap;
import org.atomnuke.container.service.annotation.Requires;
import org.atomnuke.plugin.ReferenceInstantiationException;
import org.atomnuke.service.ServiceManager;
import org.atomnuke.service.ServiceContext;
import org.atomnuke.service.gc.ReclamationHandler;
import org.atomnuke.lifecycle.InitializationException;
import org.atomnuke.service.runtime.AbstractRuntimeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author zinic
*/
@NukeBootstrap
@Requires(ReclamationHandler.class)
public class DirectoryLoaderService extends AbstractRuntimeService {
private static final String LOADER_SVC_NAME = "org.atomnuke.container.packaging.loader.impl.DirectoryLoaderService";
private static final Logger LOG = LoggerFactory.getLogger(DirectoryLoaderService.class);
private final BindingEnvironmentFactory bindingEnvFactory;
private final ResourceManager rootResourceManager;
private File deploymentDirectory, libraryDirectory;
private PackageLoader packageLoader;
public DirectoryLoaderService() {
super(PackageLoader.class);
rootResourceManager = new ResourceManagerImpl();
bindingEnvFactory = new BindingEnvironmentManagerImpl(rootResourceManager);
}
@Override
public String name() {
return LOADER_SVC_NAME;
}
@Override
public Object instance() {
return packageLoader;
}
@Override
public void init(ServiceContext sc) throws InitializationException {
LOG.info("Directory package loader service starting.");
deploymentDirectory = new File(sc.environment().deploymentDirectory());
libraryDirectory = new File(sc.environment().libraryDirectory());
packageLoader = new BindingAwarePackageLoader(bindingEnvFactory);
try {
loadPackages();
loadServices(sc.serviceManager());
} catch (PackageLoadingException ple) {
LOG.error(ple.getMessage(), ple);
}
}
@Override
public void destroy() {
LOG.info("Directory package loader service stopping.");
}
private void loadServices(ServiceManager serviceManager) {
for (PackageContext loadedPackage : packageLoader.packageContexts()) {
try {
// Gather services from the package
gatherServices(serviceManager, loadedPackage);
} catch (ReferenceInstantiationException bie) {
LOG.error("Failed to init services.");
}
}
}
private void gatherServices(ServiceManager serviceManager, PackageContext pkgContext) throws ReferenceInstantiationException {
pkgContext.packageBindings().resolveServices(serviceManager);
serviceManager.resolve();
}
private void loadPackages() throws PackageLoadingException {
final Unpacker archiveUnpacker = new ArchiveExtractor(deploymentDirectory);
if (!libraryDirectory.exists()) {
if (!libraryDirectory.mkdirs()) {
throw new PackageLoadingException("Unable to make library directory: " + libraryDirectory.getAbsolutePath());
}
}
if (!libraryDirectory.isDirectory()) {
throw new PackageLoadingException(libraryDirectory.getAbsolutePath() + " is not a valid library directory.");
}
final List<DeployedPackage> deployedPackages = new LinkedList<DeployedPackage>();
for (File archive : libraryDirectory.listFiles()) {
if (!archive.isDirectory()) {
final DeployedPackage nextPackage = loadFile(archive, archiveUnpacker);
if (nextPackage != null) {
deployedPackages.add(nextPackage);
}
}
// Ignore directories for now
}
// Load the root context first
packageLoader.load(UUID.randomUUID() + ".ROOT", rootResourceManager);
// Load all of the isolate contexts
for (DeployedPackage deployedPackage : deployedPackages) {
try {
LOG.info("Loading package \"" + deployedPackage.archiveUri().toString() + "\"");
packageLoader.load(deployedPackage.archiveUri().toString(), deployedPackage.resourceManager());
LOG.info("Package \"" + deployedPackage.archiveUri().toString() + "\" loaded");
} catch (PackageLoadingException ple) {
LOG.error("Failed to load package (" + deployedPackage.archiveUri().toString() + ") - Reason: " + ple.getMessage(), ple);
}
}
}
private DeployedPackage loadFile(File archive, final Unpacker archiveUnpacker) {
final URI archiveUri = archive.toURI();
if (archiveUnpacker.canUnpack(archiveUri)) {
LOG.info("Extracting package \"" + archiveUri.toString() + "\"");
try {
return archiveUnpacker.unpack(rootResourceManager, archiveUri);
} catch (UnpackerException ue) {
LOG.error("Failed to unpack package (" + archive.getAbsolutePath() + ") - Reason: " + ue.getMessage(), ue);
}
}
return null;
}
}