/*
* 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();
}
}
}