Package org.jboss.as.service

Source Code of org.jboss.as.service.ParsedServiceDeploymentProcessor$AttributeValue

/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, 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 javax.management.MBeanServer;
import org.jboss.as.deployment.DeploymentPhases;
import org.jboss.as.deployment.descriptor.JBossServiceAttributeConfig;
import org.jboss.as.deployment.descriptor.JBossServiceConfig;
import org.jboss.as.deployment.descriptor.JBossServiceConstructorConfig;
import org.jboss.as.deployment.descriptor.JBossServiceDependencyConfig;
import org.jboss.as.deployment.descriptor.JBossServiceXmlDescriptor;
import org.jboss.as.deployment.module.ModuleDeploymentProcessor;
import org.jboss.as.deployment.unit.DeploymentUnitContext;
import org.jboss.as.deployment.unit.DeploymentUnitProcessingException;
import org.jboss.as.deployment.unit.DeploymentUnitProcessor;
import org.jboss.as.jmx.MBeanRegistrationService;
import org.jboss.as.jmx.MBeanServerService;
import org.jboss.logging.Logger;
import org.jboss.modules.Module;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.inject.MethodInjector;
import org.jboss.msc.service.BatchBuilder;
import org.jboss.msc.service.BatchServiceBuilder;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.value.CachedValue;
import org.jboss.msc.value.ConstructedValue;
import org.jboss.msc.value.LookupClassValue;
import org.jboss.msc.value.LookupConstructorValue;
import org.jboss.msc.value.LookupGetMethodValue;
import org.jboss.msc.value.LookupMethodValue;
import org.jboss.msc.value.LookupSetMethodValue;
import org.jboss.msc.value.MethodValue;
import org.jboss.msc.value.Value;
import org.jboss.msc.value.Values;

import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* DeploymentUnit processor responsible for taking JBossServiceXmlDescriptor configuration and creating the
* corresponding services.
*
* @author John E. Bailey
*/
public class ParsedServiceDeploymentProcessor implements DeploymentUnitProcessor {
    public static final long PRIORITY = DeploymentPhases.INSTALL_SERVICES.plus(101L);
    public static final Logger log = Logger.getLogger("org.jboss.as.deployment.service");
    private static final ServiceName MBEAN_SERVICE_NAME_BASE = ServiceName.JBOSS.append("mbean","service");
    private static final String CREATE_SUFFIX = "create";
    private static final String START_SUFFIX = "start";

    /**
     * Process a deployment for JbossService confguration.  Will install a {@Code JBossService} for each configured service.
     *
     * @param context the deployment unit context
     * @throws DeploymentUnitProcessingException
     */
    public void processDeployment(DeploymentUnitContext context) throws DeploymentUnitProcessingException {
        final JBossServiceXmlDescriptor serviceXmlDescriptor = context.getAttachment(JBossServiceXmlDescriptor.ATTACHMENT_KEY);
        if(serviceXmlDescriptor == null)
            return;

        final Module module = context.getAttachment(ModuleDeploymentProcessor.MODULE_ATTACHMENT_KEY);
        if(module == null)
            throw new DeploymentUnitProcessingException("Failed to get module attachment for deployment: " + context.getName());

        final ClassLoader classLoader = module.getClassLoader();
        final Value<ClassLoader> classLoaderValue = Values.immediateValue(classLoader);

        final JBossServiceXmlDescriptor.ControllerMode controllerMode = serviceXmlDescriptor.getControllerMode();
        final List<JBossServiceConfig> serviceConfigs = serviceXmlDescriptor.getServiceConfigs();
        final BatchBuilder batchBuilder = context.getBatchBuilder();
        for(final JBossServiceConfig serviceConfig : serviceConfigs) {
            addService(batchBuilder, serviceConfig, classLoaderValue);
        }
    }

    private void addService(final BatchBuilder batchBuilder, final JBossServiceConfig serviceConfig, final Value<ClassLoader> classLoaderValue) {
        final String codeName = serviceConfig.getCode();
        final Value<Class<?>> classValue = cached(new LookupClassValue(codeName, classLoaderValue));

        final List<Value<?>> constructorArguments = new ArrayList<Value<?>>();
        final List<Value<Class<?>>> constructorSignature = new ArrayList<Value<Class<?>>>();

        final JBossServiceConstructorConfig constructorConfig = serviceConfig.getConstructorConfig();
        if(constructorConfig != null) {
            final JBossServiceConstructorConfig.Argument[] arguments = constructorConfig.getArguments();
            for(JBossServiceConstructorConfig.Argument argument : arguments) {
                final Value<Class<?>> attributeTypeValue = cached(new LookupClassValue(argument.getType(), classLoaderValue));
                constructorArguments.add(cached(new ArgumentValue(attributeTypeValue, argument.getValue())));
                constructorSignature.add(attributeTypeValue);
            }
        }

        final Value<Constructor> constructorValue = cached(new LookupConstructorValue(classValue, constructorSignature));
        final Value<Object> constructedValue = cached(new ConstructedValue(constructorValue, constructorArguments));

        final CreateDestroyService<Object> createDestroyService = new CreateDestroyService<Object>(constructedValue);
        final StartStopService<Object> startStopService = new StartStopService<Object>(constructedValue);

        final String serviceName = serviceConfig.getName();
        final ServiceName createDestroyServiceName = convert(serviceName).append(CREATE_SUFFIX);
        final BatchServiceBuilder<?> createDestroyServiceBuilder = batchBuilder.addService(createDestroyServiceName, createDestroyService);
        final ServiceName startStopServiceName = convert(serviceName).append(START_SUFFIX);
        final BatchServiceBuilder<?> startStopServiceBuilder = batchBuilder.addService(startStopServiceName, startStopService);
        startStopServiceBuilder.addDependency(createDestroyServiceName);

        final JBossServiceDependencyConfig[] dependencyConfigs = serviceConfig.getDependencyConfigs();
        if(dependencyConfigs != null) {
            for(JBossServiceDependencyConfig dependencyConfig : dependencyConfigs) {
                final ServiceName dependencyCreateDestroyServiceName = convert(dependencyConfig.getDependencyName()).append(CREATE_SUFFIX);
                final ServiceName dependencyStartStopServiceName = convert(dependencyConfig.getDependencyName()).append(START_SUFFIX);
                final String optionalAttributeName = dependencyConfig.getOptionalAttributeName();
                if(optionalAttributeName != null) {
                    createDestroyServiceBuilder.addDependency(dependencyCreateDestroyServiceName, getPropertyInjector(classValue, optionalAttributeName, createDestroyService, Values.injectedValue()));
                } else {
                    createDestroyServiceBuilder.addDependency(dependencyCreateDestroyServiceName);
                }
                startStopServiceBuilder.addDependency(dependencyStartStopServiceName);
            }
        }

        final JBossServiceAttributeConfig[] attributeConfigs = serviceConfig.getAttributeConfigs();
        if(attributeConfigs != null) {
            for(JBossServiceAttributeConfig attributeConfig : attributeConfigs) {
                final String attributeName = attributeConfig.getName();
                final JBossServiceAttributeConfig.Inject inject = attributeConfig.getInject();
                final JBossServiceAttributeConfig.ValueFactory valueFactory = attributeConfig.getValueFactory();
                if(inject != null) {
                    final String propertyName = inject.getPropertyName();
                    Value<?> valueToInject = Values.injectedValue();
                    if(propertyName != null) {
                        valueToInject = cached(new MethodValue<Object>(new LookupGetMethodValue(classValue, propertyName), valueToInject, Values.<Object>emptyList()));
                    }
                    createDestroyServiceBuilder.addDependency(convert(inject.getBeanName()).append(CREATE_SUFFIX), getPropertyInjector(classValue, attributeName, createDestroyService, valueToInject));
                    startStopServiceBuilder.addDependencies(convert(inject.getBeanName()).append(START_SUFFIX));
                } else if(valueFactory != null) {
                    final String methodName = valueFactory.getMethodName();
                    final JBossServiceAttributeConfig.ValueFactoryParameter[] parameters = valueFactory.getParameters();
                    final List<Value<Class<?>>> paramTypes = new ArrayList<Value<Class<?>>>(parameters.length);
                    final List<Value<?>> paramValues = new ArrayList<Value<?>>(parameters.length);
                    for(JBossServiceAttributeConfig.ValueFactoryParameter parameter : parameters) {
                        final Value<Class<?>> attributeTypeValue = cached(new LookupClassValue(parameter.getType(), classLoaderValue));
                        paramTypes.add(attributeTypeValue);
                        paramValues.add(cached(new ArgumentValue(attributeTypeValue, parameter.getValue())));
                    }
                    final Value<?> valueToInject = cached(new MethodValue(new LookupMethodValue(classValue, methodName, paramTypes), Values.injectedValue(), paramValues));
                    createDestroyServiceBuilder.addDependency(convert(valueFactory.getBeanName()).append(CREATE_SUFFIX), getPropertyInjector(classValue, attributeName, createDestroyService, valueToInject));
                    startStopServiceBuilder.addDependencies(convert(valueFactory.getBeanName()).append(START_SUFFIX));
                } else {
                    createDestroyServiceBuilder.addInjectionValue(getPropertyInjector(classValue, attributeName, createDestroyService, Values.injectedValue()), cached(new AttributeValue(classValue, attributeName, attributeConfig.getValue())));
                }
            }
        }

        // Add service to register the bean in the mbean server
        final MBeanRegistrationService<Object> mbeanRegistrationService = new MBeanRegistrationService(serviceName);
        batchBuilder.addService(MBeanRegistrationService.SERVICE_NAME.append(serviceName), mbeanRegistrationService)
            .addDependency(MBeanServerService.SERVICE_NAME, MBeanServer.class, mbeanRegistrationService.getMBeanServerInjector())
            .addDependency(startStopServiceName, Object.class, mbeanRegistrationService.getValueInjector());
    }

    private Injector<Object> getPropertyInjector(final Value<Class<?>> classValue, final String propertyName, final CreateDestroyService<?> startStopService, final Value<?> value) {
        return new MethodInjector<Object>(cached(new LookupSetMethodValue(classValue, propertyName)), startStopService, null, Collections.singletonList(value));
    }

    private ServiceName convert(final String name) {
        if(name == null)
            throw new IllegalArgumentException("Name must not be null");
        return MBEAN_SERVICE_NAME_BASE.append(name);
    }

    private <T> Value<T> cached(final Value<T> value) {
        return new CachedValue<T>(value);
    }

    private static class AttributeValue<T> implements Value<T> {
        private final Value<Class<?>> targetClassValue;
        private final String name;
        private final String value;

        private AttributeValue(Value<Class<?>> targetClassValue, String name, String value) {
            this.targetClassValue = targetClassValue;
            this.name = name;
            this.value = value;
        }

        @Override
        public T getValue() throws IllegalStateException {
            Class<?> type = null;
            final String expectedMethodName = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
            final Class<?> targetType = targetClassValue.getValue();
            final Method[] methods = targetType.getMethods();
            for(Method method : methods) {
                if(expectedMethodName.equals(method.getName())) {
                    final Class<?>[] types = method.getParameterTypes();
                    if(types.length == 1) {
                        type = types[0];
                        break;
                    }
                }
            }
            if(type == null) {
                log.warn("Unable to find type for property " + name + " on class " + targetType);
                return null;
            }
            final PropertyEditor editor = PropertyEditorManager.findEditor(type);
            if(editor == null) {
                log.warn("Unable to find PropertyEditor for type " + type);
                return null;
            }
            editor.setAsText(value);
            return (T)editor.getValue();
        }
    }

    private static class ArgumentValue<T> implements Value<T> {
        private final Value<Class<?>> typeValue;
        private final String value;

        private ArgumentValue(final Value<Class<?>> typeValue, final String value) {
            this.typeValue = typeValue;
            this.value = value;
        }

        @Override
        public T getValue() throws IllegalStateException {
            final Class<?> type = typeValue.getValue();
            final PropertyEditor editor = PropertyEditorManager.findEditor(type);
            if(editor == null) {
                log.warn("Unable to find PropertyEditor for type " + type);
                return null;
            }
            editor.setAsText(value);
            return (T)editor.getValue();
        }
    }
}
TOP

Related Classes of org.jboss.as.service.ParsedServiceDeploymentProcessor$AttributeValue

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.