org.jboss.as.capedwarf.extension.CapedwarfSubsystemAdd.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.as.capedwarf.extension.CapedwarfSubsystemAdd.java

Source

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2011, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.as.capedwarf.extension;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramSocket;
import java.net.Socket;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageReaderSpi;
import javax.jms.Connection;

import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi;
import org.apache.http.client.HttpClient;
import org.geotoolkit.image.io.plugin.RawTiffImageReader;
import org.jboss.as.capedwarf.deployment.*;
import org.jboss.as.capedwarf.services.ComponentRegistryService;
import org.jboss.as.capedwarf.services.HttpClientService;
import org.jboss.as.capedwarf.services.OptionalExecutorService;
import org.jboss.as.capedwarf.services.OptionalThreadFactoryService;
import org.jboss.as.capedwarf.services.ServletExecutorConsumerService;
import org.jboss.as.capedwarf.services.SimpleThreadsHandler;
import org.jboss.as.capedwarf.services.ThreadsHandler;
import org.jboss.as.capedwarf.utils.CapedwarfProperties;
import org.jboss.as.capedwarf.utils.Constants;
import org.jboss.as.clustering.infinispan.subsystem.EmbeddedCacheManagerService;
import org.jboss.as.clustering.jgroups.subsystem.ChannelService;
import org.jboss.as.controller.AbstractBoottimeAddStepHandler;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.OperationStepHandler;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.PathElement;
import org.jboss.as.controller.ProcessType;
import org.jboss.as.controller.ServiceVerificationHandler;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.controller.registry.ImmutableManagementResourceRegistration;
import org.jboss.as.controller.registry.Resource;
import org.jboss.as.naming.ManagedReferenceFactory;
import org.jboss.as.naming.deployment.ContextNames;
import org.jboss.as.server.AbstractDeploymentChainStep;
import org.jboss.as.server.DeploymentProcessorTarget;
import org.jboss.as.server.Services;
import org.jboss.as.server.deployment.Phase;
import org.jboss.as.server.deployment.module.TempFileProviderService;
import org.jboss.as.threads.ThreadsServices;
import org.jboss.as.txn.service.TxnServices;
import org.jboss.capedwarf.shared.components.ComponentRegistry;
import org.jboss.capedwarf.shared.components.Key;
import org.jboss.capedwarf.shared.components.Keys;
import org.jboss.capedwarf.shared.socket.CapedwarfSocketFactory;
import org.jboss.capedwarf.shared.url.URLHack;
import org.jboss.dmr.ModelNode;
import org.jboss.modules.ModuleLoader;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.ServiceTarget;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.vfs.TempDir;
import org.jboss.vfs.VFSUtils;

import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ARCHIVE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ENABLED;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PATH;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PERSISTENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNTIME_NAME;

/**
 * Handler responsible for adding the subsystem resource to the model
 *
 * @author <a href="mailto:marko.luksa@gmail.com">Marko Luksa</a>
 * @author <a href="mailto:ales.justin@jboss.org">Ales Justin</a>
 * @author <a href="mailto:mlazar@redhat.com">Matej Lazar</a>
 */
class CapedwarfSubsystemAdd extends AbstractBoottimeAddStepHandler {

    static final CapedwarfSubsystemAdd INSTANCE = new CapedwarfSubsystemAdd();

    private CapedwarfSubsystemAdd() {
    }

    @Override
    protected void populateModel(OperationContext context, ModelNode operation, Resource resource)
            throws OperationFailedException {
        super.populateModel(context, operation, resource);

        if (context.getProcessType() == ProcessType.STANDALONE_SERVER) {
            String rootDeployment = System.getProperty("rootDeployment");
            if (rootDeployment != null) {
                if (requiresRuntime(context)) { // only add the step if we are going to actually deploy the war
                    PathAddress deploymentAddress = PathAddress
                            .pathAddress(PathElement.pathElement(DEPLOYMENT, rootDeployment));
                    ModelNode op = Util.createOperation(ADD, deploymentAddress);
                    op.get(ENABLED).set(true);
                    op.get(PERSISTENT).set(false);
                    op.get(RUNTIME_NAME).set("ROOT.war");
                    op.get(CONTENT).add(getContentItem(rootDeployment));

                    ImmutableManagementResourceRegistration rootResourceRegistration = context
                            .getRootResourceRegistration();
                    OperationStepHandler handler = rootResourceRegistration.getOperationHandler(deploymentAddress,
                            ADD);

                    context.addStep(op, handler, OperationContext.Stage.MODEL);
                }
            }
        }
    }

    private ModelNode getContentItem(String explodedWar) {
        ModelNode contentItem = new ModelNode();
        File war = new File(explodedWar);
        contentItem.get(PATH).set(war.getAbsolutePath());
        contentItem.get(ARCHIVE).set(war.isFile());
        return contentItem;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
        CapedwarfDefinition.APPENGINE_API.validateAndSet(operation, model);
        CapedwarfDefinition.ADMIN_TGT.validateAndSet(operation, model);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void performBoottime(final OperationContext context, ModelNode operation, ModelNode model,
            ServiceVerificationHandler verificationHandler, final List<ServiceController<?>> newControllers)
            throws OperationFailedException {

        final ModelNode appEngineModel = CapedwarfDefinition.APPENGINE_API.resolveModelAttribute(context, model);
        final String appengineAPI = appEngineModel.isDefined() ? appEngineModel.asString() : null;

        final ModelNode adminTGTModel = CapedwarfDefinition.ADMIN_TGT.resolveModelAttribute(context, model);
        final String adminTGT = adminTGTModel.isDefined() ? adminTGTModel.asString() : null;

        final CapedwarfProperties properties = new CapedwarfProperties(System.getProperties());
        System.setProperties(properties); // override global properties, w/o synched code ...

        // register custom URLStreamHandlerFactory
        registerURLStreamHandlerFactory();

        // register custom Socket Factory
        registerSocketFactory();

        addTiffSupport();

        readCapedwarfConf();

        context.addStep(new AbstractDeploymentChainStep() {
            public void execute(DeploymentProcessorTarget processorTarget) {
                final ServiceTarget serviceTarget = context.getServiceTarget();

                addQueueConsumer(serviceTarget, newControllers);

                final ThreadsHandler handler = new SimpleThreadsHandler();
                putExecutorServiceToRegistry(serviceTarget, newControllers, handler);
                putThreadFactoryToRegistry(serviceTarget, newControllers, handler);
                addHttpClient(serviceTarget, newControllers);

                addServicesToRegistry(serviceTarget, newControllers);

                final TempDir tempDir = createTempDir(serviceTarget, newControllers);

                final int initialStructureOrder = Math.max(
                        Math.max(Phase.STRUCTURE_WAR, Phase.STRUCTURE_WAR_DEPLOYMENT_INIT), Phase.STRUCTURE_EAR);
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.STRUCTURE,
                        initialStructureOrder + 10, new CapedwarfInitializationProcessor());
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.STRUCTURE,
                        initialStructureOrder + 20, new CapedwarfSubsystemProcessor());
                final int initialParseOrder = Math.min(Phase.PARSE_WEB_DEPLOYMENT, Phase.PARSE_PERSISTENCE_UNIT);
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.PARSE, initialParseOrder - 20,
                        new CapedwarfEarAppInfoParseProcessor()); // adjust order as needed
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.PARSE, initialParseOrder - 18,
                        new CapedwarfWebAppInfoParseProcessor()); // adjust order as needed
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.PARSE, initialParseOrder - 16,
                        new CapedwarfAppIdProcessor()); // adjust order as needed
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.PARSE, initialParseOrder - 14,
                        new CapedwarfXmlsParserProcessor()); // adjust order as needed
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.PARSE, initialParseOrder - 12,
                        new CapedwarfCompatibilityParseProcessor()); // adjust order as needed
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.PARSE, initialParseOrder - 10,
                        new CapedwarfPersistenceModificationProcessor(tempDir)); // before persistence.xml parsing
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.PARSE,
                        Phase.PARSE_WEB_DEPLOYMENT + 1, new CapedwarfWebCleanupProcessor()); // right after web.xml parsing
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.PARSE,
                        Phase.PARSE_WEB_COMPONENTS - 1, new CapedwarfWebComponentsDeploymentProcessor(adminTGT));
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.PARSE,
                        Phase.PARSE_WELD_DEPLOYMENT + 10, new CapedwarfWeldParseProcessor()); // before Weld web integration
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.REGISTER,
                        Phase.REGISTER_BUNDLE_INSTALL - 10, new CapedwarfJPAProcessor()); // before default JPA processor
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.DEPENDENCIES,
                        Phase.DEPENDENCIES_WELD - 10, new CapedwarfWeldProcessor()); // before Weld
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.DEPENDENCIES,
                        Phase.DEPENDENCIES_JPA - 10, new CapedwarfExcludeGaeApiProcessor(appengineAPI)); // before CapedwarfDeploymentProcessor
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.DEPENDENCIES,
                        Phase.DEPENDENCIES_JPA - 7, new CapedwarfEarDeploymentProcessor()); // ear CL deps
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.DEPENDENCIES,
                        Phase.DEPENDENCIES_JPA - 5, new CapedwarfDeploymentProcessor(appengineAPI)); // web CL deps
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.DEPENDENCIES,
                        Phase.DEPENDENCIES_JPA - 1, new CapedwarfCacheEntriesTopProcessor()); // gather cache configs
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_INJECTION_ANNOTATION - 9, new CapedwarfModuleProcessor()); // right after module
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_INJECTION_ANNOTATION - 1, new CapedwarfEnvironmentProcessor(properties)); // after module
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_LOGGING_CONFIG - 1, new CapedwarfLoggingParseProcessor()); // just before AS logging configuration
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_WELD_PORTABLE_EXTENSIONS + 10, new CapedwarfCDIExtensionProcessor()); // after Weld portable extensions lookup
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_WELD_PORTABLE_EXTENSIONS + 20, new CapedwarfEntityProcessor()); // adjust as needed
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_WELD_PORTABLE_EXTENSIONS + 30, new CapedwarfPostModuleJPAProcessor()); // after entity processor
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_WELD_PORTABLE_EXTENSIONS + 40, new CapedwarfSynchHackProcessor()); // after module, adjust as needed
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_SAR_SERVICE_COMPONENT + 2, new CapedwarfCacheEntriesWebProcessor()); // gather cache configs
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_SAR_SERVICE_COMPONENT + 4, new CapedwarfCleanupProcessor()); // we still need module/CL
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_SAR_SERVICE_COMPONENT + 5, new CapedwarfSubCleanupProcessor()); // we still need module/CL
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.POST_MODULE,
                        Phase.POST_MODULE_SAR_SERVICE_COMPONENT + 6, new CapedwarfWebContextProcessor()); // before web context lifecycle
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.INSTALL,
                        Phase.INSTALL_WAR_DEPLOYMENT - 2, new CapedwarfCacheProcessor()); // after module
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.INSTALL,
                        Phase.INSTALL_WAR_DEPLOYMENT - 1, new CapedwarfMuxIdProcessor()); // adjust order as needed
                processorTarget.addDeploymentProcessor(Constants.CAPEDWARF, Phase.INSTALL,
                        Phase.INSTALL_MODULE_JNDI_BINDINGS - 2, new CapedwarfDependenciesProcessor()); // after logging
            }
        }, OperationContext.Stage.RUNTIME);

    }

    protected static void registerURLStreamHandlerFactory() throws OperationFailedException {
        try {
            URLHack.setupHandler();
        } catch (Exception e) {
            throw new OperationFailedException(e.getMessage(), e);
        }
    }

    protected static void registerSocketFactory() throws OperationFailedException {
        try {
            Socket.setSocketImplFactory(CapedwarfSocketFactory.INSTANCE);
            DatagramSocket.setDatagramSocketImplFactory(CapedwarfSocketFactory.INSTANCE);
        } catch (IOException e) {
            throw new OperationFailedException(e.getMessage(), e);
        }
    }

    protected static void readCapedwarfConf() {
        final Properties properties = new Properties();

        try {
            File bin = new File(System.getProperty("jboss.home.dir"), "bin");
            File cdConf = new File(bin, "capedwarf.conf");
            if (cdConf.exists()) {
                try (InputStream is = new FileInputStream(cdConf)) {
                    properties.load(is);
                }
            }
        } catch (IOException e) {
            Logger.getLogger(CapedwarfSubsystemAdd.class.getName()).log(Level.WARNING,
                    "Cannot read capedwarf.conf.", e);
        }

        ComponentRegistry.getInstance().setComponent(Keys.CONFIGURATION, properties);
    }

    protected static <T> void addComponentRegistryService(final ServiceTarget serviceTarget,
            final List<ServiceController<?>> newControllers, final Key<T> key, final ServiceName dependencyName) {
        final ComponentRegistryService<T> service = new ComponentRegistryService<>(key);
        final ServiceBuilder<T> builder = serviceTarget
                .addService(Constants.CAPEDWARF_NAME.append(String.valueOf(key.getSlot())), service);
        builder.addDependency(dependencyName, key.getType(), service.getInjectedValue());
        builder.setInitialMode(ServiceController.Mode.ON_DEMAND);
        newControllers.add(builder.install());
    }

    protected static void addQueueConsumer(final ServiceTarget serviceTarget,
            final List<ServiceController<?>> newControllers) {
        final ServletExecutorConsumerService consumerService = new ServletExecutorConsumerService();
        final ServiceBuilder<Connection> builder = serviceTarget.addService(ServletExecutorConsumerService.NAME,
                consumerService);
        builder.addDependency(ContextNames.bindInfoFor("java:/ConnectionFactory").getBinderServiceName(),
                ManagedReferenceFactory.class, consumerService.getFactory());
        builder.addDependency(ContextNames.bindInfoFor("java:/queue/" + Constants.CAPEDWARF).getBinderServiceName(),
                ManagedReferenceFactory.class, consumerService.getQueue());
        builder.addDependency(Services.JBOSS_SERVICE_MODULE_LOADER, ModuleLoader.class,
                consumerService.getLoader());
        builder.addDependency(ServiceName.JBOSS.append("messaging").append("default")); // depending on messaging sub-system impl details ...
        newControllers.add(builder.setInitialMode(ServiceController.Mode.ON_DEMAND).install());
    }

    protected static void putExecutorServiceToRegistry(ServiceTarget serviceTarget,
            List<ServiceController<?>> newControllers, ThreadsHandler handler) {
        final ServiceName realExecutor = ThreadsServices.executorName(Constants.CAPEDWARF);
        final ServiceName optionalExecutor = Constants.CAPEDWARF_NAME.append("OptionalExecutorService");
        final OptionalExecutorService oes = new OptionalExecutorService(handler);
        final ServiceBuilder<Executor> executorServiceBuilder = serviceTarget.addService(optionalExecutor, oes);
        executorServiceBuilder.addDependency(ServiceBuilder.DependencyType.OPTIONAL, realExecutor,
                ExecutorService.class, oes.getExecutorInjectedValue());
        executorServiceBuilder.setInitialMode(ServiceController.Mode.ON_DEMAND);
        newControllers.add(executorServiceBuilder.install());

        addComponentRegistryService(serviceTarget, newControllers, Keys.EXECUTOR_SERVICE, optionalExecutor);
    }

    protected static void putThreadFactoryToRegistry(ServiceTarget serviceTarget,
            List<ServiceController<?>> newControllers, ThreadsHandler handler) {
        final ServiceName realTF = ThreadsServices.threadFactoryName(Constants.CAPEDWARF);
        final ServiceName optionalTF = Constants.CAPEDWARF_NAME.append("OptionalThreadFactory");
        final OptionalThreadFactoryService otfs = new OptionalThreadFactoryService(handler);
        final ServiceBuilder<ThreadFactory> tfServiceBuilder = serviceTarget.addService(optionalTF, otfs);
        tfServiceBuilder.addDependency(ServiceBuilder.DependencyType.OPTIONAL, realTF, ThreadFactory.class,
                otfs.getThreadFactoryInjectedValue());
        tfServiceBuilder.setInitialMode(ServiceController.Mode.ON_DEMAND);
        newControllers.add(tfServiceBuilder.install());

        addComponentRegistryService(serviceTarget, newControllers, Keys.THREAD_FACTORY, optionalTF);
    }

    protected static void addHttpClient(final ServiceTarget serviceTarget,
            final List<ServiceController<?>> newControllers) {
        final HttpClientService service = new HttpClientService();
        final ServiceBuilder<HttpClient> builder = serviceTarget
                .addService(Constants.CAPEDWARF_NAME.append(String.valueOf(Keys.HTTP_CLIENT.getSlot())), service);
        builder.setInitialMode(ServiceController.Mode.ON_DEMAND);
        newControllers.add(builder.install());
    }

    protected static void addTiffSupport() {
        IIORegistry registry = IIORegistry.getDefaultInstance();
        registry.registerServiceProvider(new TIFFImageReaderSpi(), ImageReaderSpi.class);
        registry.registerServiceProvider(new RawTiffImageReader.Spi(), ImageReaderSpi.class);
    }

    protected static void addServicesToRegistry(ServiceTarget serviceTarget,
            List<ServiceController<?>> newControllers) {
        ServiceName mlServiceName = Services.JBOSS_SERVICE_MODULE_LOADER;
        addComponentRegistryService(serviceTarget, newControllers, Keys.MODULE_LOADER, mlServiceName);

        ServiceName chServiceName = ChannelService.getServiceName(Constants.CAPEDWARF);
        addComponentRegistryService(serviceTarget, newControllers, Keys.CHANNEL, chServiceName);

        ServiceName tmServiceName = TxnServices.JBOSS_TXN_TRANSACTION_MANAGER;
        addComponentRegistryService(serviceTarget, newControllers, Keys.TM, tmServiceName);

        ServiceName utServiceName = TxnServices.JBOSS_TXN_USER_TRANSACTION;
        addComponentRegistryService(serviceTarget, newControllers, Keys.USER_TX, utServiceName);

        ServiceName cmServiceName = EmbeddedCacheManagerService.getServiceName(Constants.CAPEDWARF);
        addComponentRegistryService(serviceTarget, newControllers, Keys.CACHE_MANAGER, cmServiceName);

        ServiceName mailServiceName = ServiceName.JBOSS.append("mail-session").append("java:jboss/mail/Default"); // TODO
        addComponentRegistryService(serviceTarget, newControllers, Keys.MAIL_SESSION, mailServiceName);
    }

    protected static TempDir createTempDir(final ServiceTarget serviceTarget,
            final List<ServiceController<?>> newControllers) {
        final TempDir tempDir;
        try {
            tempDir = TempFileProviderService.provider().createTempDir(Constants.CAPEDWARF);
        } catch (IOException e) {
            throw new IllegalArgumentException("Cannot create temp dir for CapeDwarf sub-system!", e);
        }

        final ServiceBuilder<TempDir> builder = serviceTarget.addService(Constants.CAPEDWARF_NAME.append("tempDir"),
                new Service<TempDir>() {
                    public void start(StartContext context) throws StartException {
                    }

                    public void stop(StopContext context) {
                        VFSUtils.safeClose(tempDir);
                    }

                    public TempDir getValue() throws IllegalStateException, IllegalArgumentException {
                        return tempDir;
                    }
                });
        newControllers.add(builder.setInitialMode(ServiceController.Mode.ACTIVE).install());
        return tempDir;
    }
}