All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.as.server.moduleservice.ServiceModuleLoader Maven / Gradle / Ivy

The newest version!
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2010, Red Hat Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt 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.server.moduleservice;

import java.util.concurrent.CountDownLatch;

import org.jboss.as.server.Bootstrap;
import org.jboss.as.server.ServerLogger;
import org.jboss.as.server.ServerMessages;
import org.jboss.as.server.Services;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoadException;
import org.jboss.modules.ModuleLoader;
import org.jboss.modules.ModuleSpec;
import org.jboss.msc.service.AbstractServiceListener;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceContainer;
import org.jboss.msc.service.ServiceController;
import org.jboss.msc.service.ServiceController.State;
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.msc.service.ValueService;
import org.jboss.msc.value.ImmediateValue;

/**
 * {@link ModuleLoader} that loads module definitions from msc services. Module specs are looked up in msc services that
 * correspond to the module names.
 * 

* Modules are automatically removed when the corresponding service comes down. * * @author Stuart Douglas * */ public class ServiceModuleLoader extends ModuleLoader implements Service { // Provide logging private static final ServerLogger log = ServerLogger.MODULE_SERVICE_LOGGER; /** * Listener class that atomically retrieves the moduleSpec, and automatically removes the Module when the module spec * service is removed * * @author Stuart Douglas * */ private class ModuleSpecLoadListener extends AbstractServiceListener { private final CountDownLatch latch = new CountDownLatch(1); private volatile StartException startException; private volatile ModuleSpec moduleSpec; private ModuleSpecLoadListener(ModuleIdentifier identifier) { } @Override public void listenerAdded(ServiceController controller) { log.tracef("listenerAdded: %s", controller); State state = controller.getState(); if (state == State.UP || state == State.START_FAILED) { done(controller, controller.getStartException()); } } @Override public void transition(final ServiceController controller, final ServiceController.Transition transition) { switch (transition) { case STARTING_to_UP: log.tracef("serviceStarted: %s", controller); done(controller, null); break; case STARTING_to_START_FAILED: log.tracef(controller.getStartException(), "serviceFailed: %s", controller); done(controller, controller.getStartException()); break; case STOP_REQUESTED_to_STOPPING: { log.tracef("serviceStopping: %s", controller); ModuleSpec moduleSpec = this.moduleSpec; ModuleIdentifier identifier = moduleSpec.getModuleIdentifier(); Module module = findLoadedModuleLocal(identifier); if(module != null) unloadModuleLocal(module); // TODO: what if the service is restarted? controller.removeListener(this); break; } } } private void done(ServiceController controller, StartException reason) { startException = reason; if (startException == null) { moduleSpec = controller.getValue().getModuleSpec(); } latch.countDown(); } public ModuleSpec getModuleSpec() throws ModuleLoadException { if (startException != null) throw new ModuleLoadException(startException.getCause()); return moduleSpec; } } public static final ServiceName MODULE_SPEC_SERVICE_PREFIX = ServiceName.JBOSS.append("module", "spec", "service"); public static final ServiceName MODULE_SERVICE_PREFIX = ServiceName.JBOSS.append("module", "service"); public static final ServiceName MODULE_RESOLVED_SERVICE_PREFIX = ServiceName.of("module", "resolved", "service"); public static final String MODULE_PREFIX = "deployment."; private final ModuleLoader mainModuleLoader; private volatile ServiceContainer serviceContainer; public ServiceModuleLoader(ModuleLoader mainModuleLoader) { this.mainModuleLoader = mainModuleLoader; } @Override protected Module preloadModule(final ModuleIdentifier identifier) throws ModuleLoadException { if (identifier.getName().startsWith(MODULE_PREFIX)) { return super.preloadModule(identifier); } else { return preloadModule(identifier, mainModuleLoader); } } @SuppressWarnings("unchecked") @Override public ModuleSpec findModule(ModuleIdentifier identifier) throws ModuleLoadException { ServiceController controller = (ServiceController) serviceContainer.getService(moduleSpecServiceName(identifier)); if (controller == null) { ServerLogger.MODULE_SERVICE_LOGGER.debugf("Could not load module '%s' as corresponding module spec service '%s' was not found", identifier, identifier); return null; } ModuleSpecLoadListener listener = new ModuleSpecLoadListener(identifier); controller.addListener(listener); return listener.getModuleSpec(); } @Override public String toString() { return "Service Module Loader"; } @Override public synchronized void start(StartContext context) throws StartException { if (serviceContainer != null) { throw ServerMessages.MESSAGES.serviceModuleLoaderAlreadyStarted(); } serviceContainer = context.getController().getServiceContainer(); } @Override public synchronized void stop(StopContext context) { if (serviceContainer == null) { throw ServerMessages.MESSAGES.serviceModuleLoaderAlreadyStopped(); } serviceContainer = null; } @Override public ServiceModuleLoader getValue() throws IllegalStateException, IllegalArgumentException { return this; } public void relinkModule(Module module) throws ModuleLoadException { relink(module); } public static void addService(final ServiceTarget serviceTarget, final Bootstrap.Configuration configuration) { final Service service = new ServiceModuleLoader(configuration.getModuleLoader()); final ServiceBuilder serviceBuilder = serviceTarget.addService(Services.JBOSS_SERVICE_MODULE_LOADER, service); serviceBuilder.install(); } /** * Returns the corresponding ModuleSpec service name for the given module. * * @param identifier The module identifier * @return The service name of the ModuleSpec service */ public static ServiceName moduleSpecServiceName(ModuleIdentifier identifier) { if (!isDynamicModule(identifier)) { throw ServerMessages.MESSAGES.missingModulePrefix(identifier, MODULE_PREFIX); } return MODULE_SPEC_SERVICE_PREFIX.append(identifier.getName()).append(identifier.getSlot()); } public static void installModuleResolvedService(ServiceTarget serviceTarget, ModuleIdentifier identifier) { final ValueService resolvedService = new ValueService(new ImmediateValue(identifier)); serviceTarget.addService(ServiceModuleLoader.moduleResolvedServiceName(identifier), resolvedService) .addDependency(moduleSpecServiceName(identifier)) .install(); } /** * Returns the corresponding module resolved service name for the given module. * * The module resolved service is basically a latch that prevents the module from being loaded * until all the transitive dependencies that it depends upon have have their module spec services * come up. * * @param identifier The module identifier * @return The service name of the ModuleSpec service */ public static ServiceName moduleResolvedServiceName(ModuleIdentifier identifier) { if (!isDynamicModule(identifier)) { throw ServerMessages.MESSAGES.missingModulePrefix(identifier, MODULE_PREFIX); } return MODULE_RESOLVED_SERVICE_PREFIX.append(identifier.getName()).append(identifier.getSlot()); } /** * Returns true if the module identifier is a dynamic module that will be loaded by this module loader */ public static boolean isDynamicModule(ModuleIdentifier identifier) { return identifier.getName().startsWith(MODULE_PREFIX); } /** * Returns the corresponding ModuleLoadService service name for the given module. * * @param identifier The module identifier * @return The service name of the ModuleLoadService service */ public static ServiceName moduleServiceName(ModuleIdentifier identifier) { if (!identifier.getName().startsWith(MODULE_PREFIX)) { throw ServerMessages.MESSAGES.missingModulePrefix(identifier, MODULE_PREFIX); } return MODULE_SERVICE_PREFIX.append(identifier.getName()).append(identifier.getSlot()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy