/* * 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.service; import java.lang.reflect.Method; import java.util.List; import javax.management.MBeanServer; import org.jboss.as.jmx.MBeanRegistrationService; import org.jboss.as.server.Services; import org.jboss.as.server.deployment.SetupAction; import org.jboss.as.server.deployment.reflect.ClassReflectionIndex; import org.jboss.as.service.component.ServiceComponentInstantiator; import org.jboss.as.service.logging.SarLogger; import org.jboss.msc.inject.Injector; import org.jboss.msc.service.Service; import org.jboss.msc.service.ServiceBuilder; import org.jboss.msc.service.ServiceName; import org.jboss.msc.service.ServiceTarget; import org.jboss.msc.value.Value; /** * Services associated with MBean responsible for dependencies & injection management. * * @author <a href="mailto:ropalka@redhat.com">Richard Opalka</a> */ final class MBeanServices { private static final String CREATE_METHOD_NAME = "create"; private static final String DESTROY_METHOD_NAME = "destroy"; private static final String START_METHOD_NAME = "start"; private static final String STOP_METHOD_NAME = "stop"; private static final Class<?>[] NO_ARGS = new Class<?>[0]; private final String mBeanName; private final ServiceName createDestroyServiceName; private final ServiceName startStopServiceName; private final Service<Object> createDestroyService; private final Service<Object> startStopService; private final ServiceBuilder<?> createDestroyServiceBuilder; private final ServiceBuilder<?> startStopServiceBuilder; private final ServiceTarget target; private final ServiceName mbeanServerServiceName; private boolean installed; private final List<SetupAction> setupActions; /** * @param mBeanName * @param mBeanInstance * @param mBeanClassHierarchy * @param target * @param componentInstantiator * @param setupActions the deployment unit's service name * @param mbeanServerServiceName */ MBeanServices(final String mBeanName, final Object mBeanInstance, final List<ClassReflectionIndex> mBeanClassHierarchy, final ServiceTarget target, final ServiceComponentInstantiator componentInstantiator, final List<SetupAction> setupActions, final ClassLoader mbeanContextClassLoader, final ServiceName mbeanServerServiceName) { if (mBeanClassHierarchy == null) { throw SarLogger.ROOT_LOGGER.nullVar("mBeanName"); } if (mBeanInstance == null) { throw SarLogger.ROOT_LOGGER.nullVar("mBeanInstance"); } if (target == null) { throw SarLogger.ROOT_LOGGER.nullVar("target"); } if (mbeanServerServiceName == null) { throw SarLogger.ROOT_LOGGER.nullVar("mbeanServerServiceName"); } final Method createMethod = ReflectionUtils.getMethod(mBeanClassHierarchy, CREATE_METHOD_NAME, NO_ARGS, false); final Method destroyMethod = ReflectionUtils.getMethod(mBeanClassHierarchy, DESTROY_METHOD_NAME, NO_ARGS, false); createDestroyService = new CreateDestroyService(mBeanInstance, createMethod, destroyMethod,componentInstantiator, setupActions, mbeanContextClassLoader); createDestroyServiceName = ServiceNameFactory.newCreateDestroy(mBeanName); createDestroyServiceBuilder = target.addService(createDestroyServiceName, createDestroyService); Services.addServerExecutorDependency(createDestroyServiceBuilder, ((CreateDestroyService) createDestroyService).getExecutorInjector()); if(componentInstantiator != null) { // the service that starts the EE component needs to start first createDestroyServiceBuilder.addDependency(componentInstantiator.getComponentStartServiceName()); } final Method startMethod = ReflectionUtils.getMethod(mBeanClassHierarchy, START_METHOD_NAME, NO_ARGS, false); final Method stopMethod = ReflectionUtils.getMethod(mBeanClassHierarchy, STOP_METHOD_NAME, NO_ARGS, false); startStopService = new StartStopService(mBeanInstance, startMethod, stopMethod, setupActions, mbeanContextClassLoader); startStopServiceName = ServiceNameFactory.newStartStop(mBeanName); startStopServiceBuilder = target.addService(startStopServiceName, startStopService); startStopServiceBuilder.addDependency(createDestroyServiceName); for(SetupAction action : setupActions) { startStopServiceBuilder.addDependencies(action.dependencies()); } Services.addServerExecutorDependency(startStopServiceBuilder, ((StartStopService) startStopService).getExecutorInjector()); this.mBeanName = mBeanName; this.target = target; this.setupActions = setupActions; this.mbeanServerServiceName = mbeanServerServiceName; } Service<Object> getCreateDestroyService() { assertState(); return createDestroyService; } Service<Object> getStartStopService() { assertState(); return startStopService; } void addDependency(final String dependencyMBeanName) { assertState(); final ServiceName injectedMBeanCreateDestroyServiceName = ServiceNameFactory.newCreateDestroy(dependencyMBeanName); createDestroyServiceBuilder.addDependency(injectedMBeanCreateDestroyServiceName); final ServiceName injectedMBeanStartStopServiceName = ServiceNameFactory.newStartStop(dependencyMBeanName); startStopServiceBuilder.addDependency(injectedMBeanStartStopServiceName); } void addAttribute(final String attributeMBeanName, final Injector<Object> injector) { assertState(); final ServiceName injectedMBeanCreateDestroyServiceName = ServiceNameFactory.newCreateDestroy(attributeMBeanName); createDestroyServiceBuilder.addDependency(injectedMBeanCreateDestroyServiceName, injector); final ServiceName injectedMBeanStartStopServiceName = ServiceNameFactory.newStartStop(attributeMBeanName); startStopServiceBuilder.addDependency(injectedMBeanStartStopServiceName); } void addInjectionValue(final Injector<Object> injector, final Value<?> value) { assertState(); createDestroyServiceBuilder.addInjectionValue(injector, value); } void install() { assertState(); createDestroyServiceBuilder.install(); startStopServiceBuilder.install(); // Add service to register the mbean in the mbean server final MBeanRegistrationService<Object> mbeanRegistrationService = new MBeanRegistrationService<Object>(mBeanName, setupActions); target.addService(MBeanRegistrationService.SERVICE_NAME.append(mBeanName), mbeanRegistrationService) .addDependency(mbeanServerServiceName, MBeanServer.class, mbeanRegistrationService.getMBeanServerInjector()) .addDependency(startStopServiceName, Object.class, mbeanRegistrationService.getValueInjector()) .install(); installed = true; } private void assertState() { if (installed) { throw new IllegalStateException(); } } }