/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2012, 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.naming.subsystem;

import javax.xml.stream.XMLStreamException;

import org.jboss.as.controller.persistence.SubsystemMarshallingContext;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.Property;
import org.jboss.staxmapper.XMLElementWriter;
import org.jboss.staxmapper.XMLExtendedStreamWriter;

import static org.jboss.as.naming.subsystem.NamingSubsystemModel.BINDING;
import static org.jboss.as.naming.subsystem.NamingSubsystemModel.BINDING_TYPE;
import static org.jboss.as.naming.subsystem.NamingSubsystemModel.EXTERNAL_CONTEXT;
import static org.jboss.as.naming.subsystem.NamingSubsystemModel.LOOKUP;
import static org.jboss.as.naming.subsystem.NamingSubsystemModel.OBJECT_FACTORY;
import static org.jboss.as.naming.subsystem.NamingSubsystemModel.REMOTE_NAMING;
import static org.jboss.as.naming.subsystem.NamingSubsystemModel.SERVICE;
import static org.jboss.as.naming.subsystem.NamingSubsystemModel.SIMPLE;

/**
 * @author Eduardo Martins
 */
public class NamingSubsystemXMLPersister implements XMLElementWriter<SubsystemMarshallingContext> {

    public static final NamingSubsystemXMLPersister INSTANCE = new NamingSubsystemXMLPersister();

    private NamingSubsystemXMLPersister() {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {

        context.startSubsystemElement(NamingExtension.NAMESPACE_2_0, false);

        ModelNode model = context.getModelNode();

        // bindings
        if (model.hasDefined(BINDING)) {
            writer.writeStartElement(NamingSubsystemXMLElement.BINDINGS.getLocalName());
            final ModelNode bindingModel = model.get(BINDING);
            this.writeBindings(writer, bindingModel);
            // </timer-service>
            writer.writeEndElement();
        }

        if (model.hasDefined(SERVICE)) {
            final ModelNode service = model.get(SERVICE);
            if (service.has(REMOTE_NAMING)) {
                writer.writeEmptyElement(REMOTE_NAMING);
            }
        }
        // write the subsystem end element
        writer.writeEndElement();
    }

    private void writeBindings(final XMLExtendedStreamWriter writer, final ModelNode bindingModel) throws XMLStreamException {
        for (Property binding : bindingModel.asPropertyList()) {
            final String type = binding.getValue().get(BINDING_TYPE).asString();
            if (type.equals(SIMPLE)) {
                writeSimpleBinding(binding, writer);
            } else if (type.equals(OBJECT_FACTORY)) {
                writeObjectFactoryBinding(binding, writer);
            } else if (type.equals(LOOKUP)) {
                writeLookupBinding(binding, writer);
            } else if (type.equals(EXTERNAL_CONTEXT)) {
                writeExternalContext(binding, writer);
            } else {
                throw new XMLStreamException("Unknown binding type " + type);
            }

        }
    }

    private void writeSimpleBinding(final Property binding, final XMLExtendedStreamWriter writer) throws XMLStreamException {
        writer.writeStartElement(NamingSubsystemXMLElement.SIMPLE.getLocalName());
        writer.writeAttribute(NamingSubsystemXMLAttribute.NAME.getLocalName(), binding.getName());
        NamingBindingResourceDefinition.VALUE.marshallAsAttribute(binding.getValue(), writer);
        NamingBindingResourceDefinition.TYPE.marshallAsAttribute(binding.getValue(), writer);
        writer.writeEndElement();
    }

    private void writeObjectFactoryBinding(final Property binding, final XMLExtendedStreamWriter writer)
            throws XMLStreamException {

        writer.writeStartElement(NamingSubsystemXMLElement.OBJECT_FACTORY.getLocalName());
        writer.writeAttribute(NamingSubsystemXMLAttribute.NAME.getLocalName(), binding.getName());
        NamingBindingResourceDefinition.MODULE.marshallAsAttribute(binding.getValue(), writer);
        NamingBindingResourceDefinition.CLASS.marshallAsAttribute(binding.getValue(), writer);
        NamingBindingResourceDefinition.ENVIRONMENT.marshallAsElement(binding.getValue(), writer);
        writer.writeEndElement();
    }

    private void writeExternalContext(final Property binding, final XMLExtendedStreamWriter writer)
            throws XMLStreamException {

        writer.writeStartElement(NamingSubsystemXMLElement.EXTERNAL_CONTEXT.getLocalName());
        writer.writeAttribute(NamingSubsystemXMLAttribute.NAME.getLocalName(), binding.getName());
        NamingBindingResourceDefinition.MODULE.marshallAsAttribute(binding.getValue(), writer);
        NamingBindingResourceDefinition.CLASS.marshallAsAttribute(binding.getValue(), writer);
        NamingBindingResourceDefinition.CACHE.marshallAsAttribute(binding.getValue(), writer);
        NamingBindingResourceDefinition.ENVIRONMENT.marshallAsElement(binding.getValue(), writer);
        writer.writeEndElement();
    }

    private void writeLookupBinding(final Property binding, final XMLExtendedStreamWriter writer) throws XMLStreamException {
        writer.writeStartElement(NamingSubsystemXMLElement.LOOKUP.getLocalName());
        writer.writeAttribute(NamingSubsystemXMLAttribute.NAME.getLocalName(), binding.getName());
        NamingBindingResourceDefinition.LOOKUP.marshallAsAttribute(binding.getValue(), writer);
        writer.writeEndElement();
    }

}


/*
 * 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.txn.subsystem;

import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
import static org.jboss.as.txn.logging.TransactionLogger.ROOT_LOGGER;

import com.arjuna.ats.jta.common.JTAEnvironmentBean;
import org.jboss.as.controller.AbstractAddStepHandler;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.txn.service.CMResourceService;
import org.jboss.as.txn.service.TxnServices;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.service.ServiceController;

/**
 * the {@link AbstractAddStepHandler} implementations that add CM managed resource.
 *
 * @author Stefano Maestri (c) 2011 Red Hat Inc.
 */
class CMResourceAdd extends AbstractAddStepHandler {
    static CMResourceAdd INSTANCE = new CMResourceAdd();

    /**
     * {@inheritDoc}
     */
    @Override
    protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
        String str = PathAddress.pathAddress(operation.get(OP_ADDR)).getLastElement().getValue();
        if (!str.startsWith("java:/") && !str.startsWith("java:jboss/")) {
            throw ROOT_LOGGER.jndiNameInvalidFormat();
        }

        CMResourceResourceDefinition.CM_TABLE_NAME.validateAndSet(operation, model);
        CMResourceResourceDefinition.CM_TABLE_BATCH_SIZE.validateAndSet(operation, model);
        CMResourceResourceDefinition.CM_TABLE_IMMEDIATE_CLEANUP.validateAndSet(operation, model);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void performRuntime(final OperationContext context, final ModelNode operation, final ModelNode model) throws OperationFailedException {
        PathAddress address = PathAddress.pathAddress(operation.get(OP_ADDR));
        final String jndiName = address.getLastElement().getValue();
        final String tableName = CMResourceResourceDefinition.CM_TABLE_NAME.resolveModelAttribute(context, model).asString();
        final int batchSize =  CMResourceResourceDefinition.CM_TABLE_BATCH_SIZE.resolveModelAttribute(context, model).asInt();
        final boolean immediateCleanup = CMResourceResourceDefinition.CM_TABLE_IMMEDIATE_CLEANUP.resolveModelAttribute(context, model).asBoolean();
        ROOT_LOGGER.debugf("adding commit-markable-resource: jndi-name=%s, table-name=%s, batch-size=%d, immediate-cleanup=%b", jndiName, tableName, batchSize, immediateCleanup);

        CMResourceService service = new CMResourceService(jndiName, tableName, immediateCleanup, batchSize);
        context.getServiceTarget().addService(TxnServices.JBOSS_TXN_CMR.append(jndiName), service)
                .addDependency(TxnServices.JBOSS_TXN_JTA_ENVIRONMENT, JTAEnvironmentBean.class, service.getJTAEnvironmentBeanInjector())
                .setInitialMode(ServiceController.Mode.ACTIVE)
                .install();

        if (!context.isBooting()) {
            context.reloadRequired();
        }
    }
}


/*
 * 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.naming.service;

import org.jboss.as.naming.NamingContext;
import org.jboss.as.naming.NamingStore;
import org.jboss.as.naming.logging.NamingLogger;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedValue;

import static org.jboss.as.naming.logging.NamingLogger.ROOT_LOGGER;

/**
 * Service responsible for creating and managing the life-cycle of the Naming Server.
 *
 * @author John E. Bailey
 * @author Eduardo Martins
 */
public class NamingService implements Service<NamingStore> {
    public static final String CAPABILITY_NAME = "org.wildfly.naming";
    /**
     * @deprecated Dependent subsystem should instead register a requirement on the {@link #CAPABILITY_NAME} capability.
     */
    @Deprecated
    public static final ServiceName SERVICE_NAME = ServiceName.JBOSS.append("naming");
    private final InjectedValue<NamingStore> namingStore;

    /**
     * Construct a new instance.
     *
     */
    public NamingService() {
        this.namingStore = new InjectedValue<>();
    }

    /**
     * Retrieves the naming store's InjectedValue.
     * @return
     */
    public InjectedValue<NamingStore> getNamingStore() {
        return namingStore;
    }

    /**
     * Creates a new NamingServer and sets the naming context to use the naming server.
     *
     * @param context The start context
     * @throws StartException If any errors occur setting up the naming server
     */
    public void start(StartContext context) throws StartException {
        ROOT_LOGGER.startingService();
        try {
            NamingContext.setActiveNamingStore(namingStore.getValue());
        } catch (Throwable t) {
            throw new StartException(NamingLogger.ROOT_LOGGER.failedToStart("naming service"), t);
        }
    }

    /**
     * Removes the naming server from the naming context.
     *
     * @param context The stop context.
     */
    public void stop(StopContext context) {
        NamingContext.setActiveNamingStore(null);
    }

    /**
     * Get the naming store value.
     *
     * @return The naming store.
     * @throws IllegalStateException
     */
    public NamingStore getValue() throws IllegalStateException {
        return namingStore.getValue();
    }
}


/*
 * 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.naming.subsystem;

import java.util.List;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;

import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.controller.parsing.ParseUtils;
import org.jboss.dmr.ModelNode;
import org.jboss.staxmapper.XMLElementReader;
import org.jboss.staxmapper.XMLExtendedStreamReader;

/**
 * @author Stuart Douglas
 */
class NamingSubsystem10Parser implements XMLStreamConstants, XMLElementReader<List<ModelNode>> {

    private final boolean appclient;

    NamingSubsystem10Parser(boolean appclient) {
        this.appclient = appclient;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void readElement(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
        ParseUtils.requireNoAttributes(reader);
        ParseUtils.requireNoContent(reader);

        list.add(Util.createAddOperation(PathAddress.pathAddress(NamingExtension.SUBSYSTEM_PATH)));
        if(!appclient) {
            //we do not add remote naming to the application client
            //note that this is a bi
            list.add(Util.createAddOperation(PathAddress.pathAddress(NamingExtension.SUBSYSTEM_PATH).append(NamingSubsystemModel.SERVICE, NamingSubsystemModel.REMOTE_NAMING)));
        }
    }
}


/*
 * 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.jpa.processor;

import static org.jboss.as.jpa.messages.JpaLogger.ROOT_LOGGER;

import org.jboss.as.hibernate.Hibernate51CompatibilityTransformer;
import org.jboss.as.jpa.classloader.JPADelegatingClassFileTransformer;
import org.jboss.as.jpa.config.Configuration;
import org.jboss.as.jpa.config.PersistenceUnitMetadataHolder;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
import org.jboss.as.server.deployment.DeploymentUtils;
import org.jboss.as.server.deployment.module.DelegatingClassFileTransformer;
import org.jboss.as.server.deployment.module.ResourceRoot;
import org.jipijapa.plugin.spi.PersistenceUnitMetadata;
import org.wildfly.security.manager.WildFlySecurityManager;

/**
 * Deployment processor which ensures the persistence provider ClassFileTransformer are used.
 *
 * @author Scott Marlow
 */
public class JPAClassFileTransformerProcessor implements DeploymentUnitProcessor {

    private final boolean hibernate51CompatibilityTransformer = Boolean.parseBoolean(
            WildFlySecurityManager.getPropertyPrivileged("Hibernate51CompatibilityTransformer","false"));

    public JPAClassFileTransformerProcessor() {
        if(hibernate51CompatibilityTransformer) {
            ROOT_LOGGER.hibernate51CompatibilityTransformerEnabled();
        }
    }

    /**
     * Add dependencies for modules required for JPA deployments
     */
    public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
        final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
        setClassLoaderTransformer(deploymentUnit);
    }

    private void setClassLoaderTransformer(DeploymentUnit deploymentUnit) {
        // (AS7-2233) each persistence unit can use a persistence provider, that might need
        // to use ClassTransformers.  Providers that need class transformers will add them
        // during the call to CreateContainerEntityManagerFactory.

        DelegatingClassFileTransformer transformer = deploymentUnit.getAttachment(DelegatingClassFileTransformer.ATTACHMENT_KEY);
        boolean appContainsPersistenceProviderJars = false;  // remove when we revert WFLY-10520
        if ( transformer != null) {

            for (ResourceRoot resourceRoot : DeploymentUtils.allResourceRoots(deploymentUnit)) {
                PersistenceUnitMetadataHolder holder = resourceRoot.getAttachment(PersistenceUnitMetadataHolder.PERSISTENCE_UNITS);
                if (holder != null) {
                    for (PersistenceUnitMetadata pu : holder.getPersistenceUnits()) {
                        if (Configuration.needClassFileTransformer(pu)) {
                            transformer.addTransformer(new JPADelegatingClassFileTransformer(pu));
                        }
                        // remove this check when we revert WFLY-10520
                        String provider = pu.getProperties().getProperty(Configuration.PROVIDER_MODULE);
                        if (provider != null) {
                            if (provider.equals(Configuration.PROVIDER_MODULE_APPLICATION_SUPPLIED)) {
                                appContainsPersistenceProviderJars = true;
                            }
                        }

                    }
                }
            }
            // WFLY-10520 Add Hibernate ORM 5.3 compatibility transformer
            if(!appContainsPersistenceProviderJars && hibernate51CompatibilityTransformer) {
                transformer.addTransformer(Hibernate51CompatibilityTransformer.getInstance());
            }
        }
    }

    @Override
    public void undeploy(DeploymentUnit context) {

    }
}


/*
 * 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.weld.deployment.processors;

import static org.jboss.as.weld.interceptors.Jsr299BindingsInterceptor.factory;
import static org.jboss.as.weld.util.Utils.getRootDeploymentUnit;

import java.util.HashSet;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;

import javax.enterprise.inject.spi.InterceptionType;

import org.jboss.as.ee.component.BasicComponentInstance;
import org.jboss.as.ee.component.ComponentConfiguration;
import org.jboss.as.ee.component.ComponentConfigurator;
import org.jboss.as.ee.component.ComponentDescription;
import org.jboss.as.ee.component.ComponentInstance;
import org.jboss.as.ee.component.ComponentStartService;
import org.jboss.as.ee.component.DependencyConfigurator;
import org.jboss.as.ee.component.EEModuleDescription;
import org.jboss.as.ee.component.InterceptorDescription;
import org.jboss.as.ee.component.ViewConfiguration;
import org.jboss.as.ee.component.interceptors.InterceptorOrder;
import org.jboss.as.ee.component.interceptors.UserInterceptorFactory;
import org.jboss.as.ee.utils.ClassLoadingUtils;
import org.jboss.as.naming.ManagedReference;
import org.jboss.as.server.deployment.Attachments;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
import org.jboss.as.weld.ServiceNames;
import org.jboss.as.weld.WeldBootstrapService;
import org.jboss.as.weld._private.WeldDeploymentMarker;
import org.jboss.as.weld.WeldStartService;
import org.jboss.as.weld.deployment.WeldClassIntrospector;
import org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor;
import org.jboss.as.weld.ejb.WeldInterceptorBindingsService;
import org.jboss.as.weld.injection.WeldComponentService;
import org.jboss.as.weld.injection.WeldConstructionStartInterceptor;
import org.jboss.as.weld.injection.WeldInjectionContextInterceptor;
import org.jboss.as.weld.injection.WeldInjectionInterceptor;
import org.jboss.as.weld.injection.WeldInterceptorInjectionInterceptor;
import org.jboss.as.weld.injection.WeldManagedReferenceFactory;
import org.jboss.as.weld.interceptors.Jsr299BindingsCreateInterceptor;
import org.jboss.as.weld.logging.WeldLogger;
import org.jboss.as.weld.spi.ComponentIntegrator;
import org.jboss.as.weld.spi.ComponentIntegrator.DefaultInterceptorIntegrationAction;
import org.jboss.as.weld.spi.ComponentInterceptorSupport;
import org.jboss.as.weld.util.ServiceLoaders;
import org.jboss.invocation.ImmediateInterceptorFactory;
import org.jboss.invocation.Interceptor;
import org.jboss.invocation.InterceptorContext;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleClassLoader;
import org.jboss.msc.service.ServiceBuilder;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.ServiceTarget;
import org.jboss.weld.ejb.spi.InterceptorBindings;
import org.wildfly.security.manager.WildFlySecurityManager;

/**
 * Deployment unit processor that add the {@link org.jboss.as.weld.injection.WeldManagedReferenceFactory} instantiator
 * to components that are part of a bean archive.
 *
 * @author Stuart Douglas
 * @author Richard Opalka
 */
public class WeldComponentIntegrationProcessor implements DeploymentUnitProcessor {

    @Override
    public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
        final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();

        if (!WeldDeploymentMarker.isWeldDeployment(deploymentUnit)) {
            return;
        }

        final DeploymentUnit topLevelDeployment = getRootDeploymentUnit(deploymentUnit);
        final EEModuleDescription eeModuleDescription = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
        final ServiceName weldBootstrapService = topLevelDeployment.getServiceName().append(WeldBootstrapService.SERVICE_NAME);
        final ServiceName weldStartService = topLevelDeployment.getServiceName().append(WeldStartService.SERVICE_NAME);
        final ServiceName beanManagerService = ServiceNames.beanManagerServiceName(deploymentUnit);

        final Iterable<ComponentIntegrator> componentIntegrators = ServiceLoader.load(ComponentIntegrator.class,
                WildFlySecurityManager.getClassLoaderPrivileged(WeldComponentIntegrationProcessor.class));
        final ComponentInterceptorSupport componentInterceptorSupport = ServiceLoaders.loadSingle(ComponentInterceptorSupport.class,
                WeldComponentIntegrationProcessor.class).orElse(null);

        WeldClassIntrospector.install(deploymentUnit, phaseContext.getServiceTarget());

        eeModuleDescription.setDefaultClassIntrospectorServiceName(WeldClassIntrospector.serviceName(deploymentUnit));

        for (ComponentDescription component : eeModuleDescription.getComponentDescriptions()) {
            final String beanName;
            if (isBeanNameRequired(component, componentIntegrators)) {
                beanName = component.getComponentName();
            } else {
                beanName = null;
            }
            component.getConfigurators().add((context, description, configuration) -> {

                //add interceptor to activate the request scope if required
                final EjbRequestScopeActivationInterceptor.Factory requestFactory = new EjbRequestScopeActivationInterceptor.Factory(beanManagerService);

                for(ViewConfiguration view : configuration.getViews()) {
                    view.addViewInterceptor(requestFactory, InterceptorOrder.View.CDI_REQUEST_SCOPE);
                }
                configuration.addTimeoutViewInterceptor(requestFactory, InterceptorOrder.View.CDI_REQUEST_SCOPE);
            });
            component.getConfigurators().addFirst(new ComponentConfigurator() {
                @Override
                public void configure(final DeploymentPhaseContext context, final ComponentDescription description, final ComponentConfiguration configuration) throws DeploymentUnitProcessingException {
                    final Class<?> componentClass = configuration.getComponentClass();
                    final DeploymentUnit deploymentUnit = context.getDeploymentUnit();
                    final Module module = deploymentUnit.getAttachment(Attachments.MODULE);
                    final ModuleClassLoader classLoader = module.getClassLoader();

                    //get the interceptors so they can be injected as well
                    final Set<Class<?>> interceptorClasses = new HashSet<Class<?>>();
                    for (InterceptorDescription interceptorDescription : description.getAllInterceptors()) {
                        try {
                            interceptorClasses.add(ClassLoadingUtils.loadClass(interceptorDescription.getInterceptorClassName(), module));
                        } catch (ClassNotFoundException e) {
                            throw WeldLogger.ROOT_LOGGER.couldNotLoadInterceptorClass(interceptorDescription.getInterceptorClassName(), e);
                        }
                    }
                    addWeldIntegration(componentIntegrators, componentInterceptorSupport, context.getServiceTarget(), configuration, description,
                            componentClass, beanName, weldBootstrapService, weldStartService, beanManagerService,
                            interceptorClasses, classLoader, description.getBeanDeploymentArchiveId());
                }
            });
        }

    }

    private boolean isBeanNameRequired(ComponentDescription component, Iterable<ComponentIntegrator> integrators) {
        for (ComponentIntegrator integrator : integrators) {
            if (integrator.isBeanNameRequired(component)) {
                return true;
            }
        }
        return false;
    }

    private boolean isComponentWithView(ComponentDescription component, Iterable<ComponentIntegrator> integrators) {
        for (ComponentIntegrator integrator : integrators) {
            if (integrator.isComponentWithView(component)) {
                return true;
            }
        }
        return false;
    }

    /**
     * As the weld based instantiator needs access to the bean manager it is installed as a service.
     */
    private void addWeldIntegration(final Iterable<ComponentIntegrator> componentIntegrators, final ComponentInterceptorSupport componentInterceptorSupport, final ServiceTarget target, final ComponentConfiguration configuration, final ComponentDescription description, final Class<?> componentClass, final String beanName, final ServiceName weldServiceName, final ServiceName weldStartService, final ServiceName beanManagerService, final Set<Class<?>> interceptorClasses, final ClassLoader classLoader, final String beanDeploymentArchiveId) {
        final ServiceName serviceName = configuration.getComponentDescription().getServiceName().append("WeldInstantiator");
        final ServiceBuilder<?> builder = target.addService(serviceName);
        builder.requires(weldStartService);

        configuration.setInstanceFactory(WeldManagedReferenceFactory.INSTANCE);
        configuration.getStartDependencies().add(new DependencyConfigurator<ComponentStartService>() {
            @Override
            public void configureDependency(final ServiceBuilder<?> serviceBuilder, ComponentStartService service) throws DeploymentUnitProcessingException {
                serviceBuilder.requires(serviceName);
            }
        });

        boolean isComponentIntegrationPerformed = false;
        for (ComponentIntegrator componentIntegrator : componentIntegrators) {
            Supplier<ServiceName> bindingServiceNameSupplier = () -> {
                if (componentInterceptorSupport == null) {
                    throw WeldLogger.DEPLOYMENT_LOGGER.componentInterceptorSupportNotAvailable(componentClass);
                }
                return addWeldInterceptorBindingService(target, configuration, componentClass, beanName, weldServiceName, weldStartService,
                        beanDeploymentArchiveId, componentInterceptorSupport);
            };
            DefaultInterceptorIntegrationAction integrationAction = (bindingServiceName) -> {
                if (componentInterceptorSupport == null) {
                    throw WeldLogger.DEPLOYMENT_LOGGER.componentInterceptorSupportNotAvailable(componentClass);
                }
                addJsr299BindingsCreateInterceptor(configuration, description, beanName, weldServiceName, builder, bindingServiceName,
                        componentInterceptorSupport);
                addCommonLifecycleInterceptionSupport(configuration, builder, bindingServiceName, beanManagerService, componentInterceptorSupport);
                configuration.addComponentInterceptor(
                        new UserInterceptorFactory(factory(InterceptionType.AROUND_INVOKE, builder, bindingServiceName, componentInterceptorSupport),
                                factory(InterceptionType.AROUND_TIMEOUT, builder, bindingServiceName, componentInterceptorSupport)),
                        InterceptorOrder.Component.CDI_INTERCEPTORS, false);
            };
            if (componentIntegrator.integrate(beanManagerService, configuration, description, builder, bindingServiceNameSupplier, integrationAction,
                    componentInterceptorSupport)) {
                isComponentIntegrationPerformed = true;
                break;
            }
        }

        final Supplier<WeldBootstrapService> weldContainerSupplier = builder.requires(weldServiceName);
        final WeldComponentService weldComponentService =
                new WeldComponentService(weldContainerSupplier, componentClass, beanName, interceptorClasses, classLoader,
                        beanDeploymentArchiveId, description.isCDIInterceptorEnabled(),
                        description, isComponentWithView(description, componentIntegrators));
        builder.setInstance(weldComponentService);

        if (!isComponentIntegrationPerformed) {
            description.setIgnoreLifecycleInterceptors(true); //otherwise they will be called twice
            // for components with no view register interceptors that delegate to InjectionTarget lifecycle methods to trigger lifecycle interception
            configuration.addPostConstructInterceptor(new ImmediateInterceptorFactory(new AbstractInjectionTargetDelegatingInterceptor() {
                @Override
                protected void run(Object instance) {
                    weldComponentService.getInjectionTarget().postConstruct(instance);
                }
            }), InterceptorOrder.ComponentPostConstruct.CDI_INTERCEPTORS);
            configuration.addPreDestroyInterceptor(new ImmediateInterceptorFactory(new AbstractInjectionTargetDelegatingInterceptor() {
                @Override
                protected void run(Object instance) {
                    weldComponentService.getInjectionTarget().preDestroy(instance);
                }
            }), InterceptorOrder.ComponentPreDestroy.CDI_INTERCEPTORS);
        }

        builder.install();

        configuration.addPostConstructInterceptor(new ImmediateInterceptorFactory(new WeldInjectionContextInterceptor(weldComponentService)), InterceptorOrder.ComponentPostConstruct.WELD_INJECTION_CONTEXT_INTERCEPTOR);
        configuration.addPostConstructInterceptor(new ImmediateInterceptorFactory(new WeldInterceptorInjectionInterceptor(interceptorClasses)), InterceptorOrder.ComponentPostConstruct.INTERCEPTOR_WELD_INJECTION);
        configuration.addPostConstructInterceptor(WeldInjectionInterceptor.FACTORY, InterceptorOrder.ComponentPostConstruct.COMPONENT_WELD_INJECTION);

    }

    private static ServiceName addWeldInterceptorBindingService(final ServiceTarget target, final ComponentConfiguration configuration, final Class<?> componentClass, final String beanName, final ServiceName weldServiceName, final ServiceName weldStartService, final String beanDeploymentArchiveId, final ComponentInterceptorSupport componentInterceptorSupport) {
        ServiceName bindingServiceName = configuration.getComponentDescription().getServiceName().append(WeldInterceptorBindingsService.SERVICE_NAME);
        final ServiceBuilder<?> sb = target.addService(bindingServiceName);
        final Consumer<InterceptorBindings> interceptorBindingsConsumer = sb.provides(bindingServiceName);
        final Supplier<WeldBootstrapService> weldContainerSupplier = sb.requires(weldServiceName);
        sb.requires(weldStartService);
        sb.setInstance(new WeldInterceptorBindingsService(interceptorBindingsConsumer, weldContainerSupplier, beanDeploymentArchiveId, beanName, componentClass, componentInterceptorSupport));
        sb.install();
        return bindingServiceName;
    }

    private static void addJsr299BindingsCreateInterceptor(final ComponentConfiguration configuration, final ComponentDescription description, final String beanName, final ServiceName weldServiceName, ServiceBuilder<?> builder, final ServiceName bindingServiceName, final ComponentInterceptorSupport componentInterceptorSupport) {
        //add the create interceptor that creates the CDI interceptors
        final Supplier<WeldBootstrapService> weldContainerSupplier = builder.requires(weldServiceName);
        final Supplier<InterceptorBindings> interceptorBindingsSupplier = builder.requires(bindingServiceName);
        final Jsr299BindingsCreateInterceptor createInterceptor = new Jsr299BindingsCreateInterceptor(weldContainerSupplier, interceptorBindingsSupplier, description.getBeanDeploymentArchiveId(), beanName, componentInterceptorSupport);
        configuration.addPostConstructInterceptor(new ImmediateInterceptorFactory(createInterceptor), InterceptorOrder.ComponentPostConstruct.CREATE_CDI_INTERCEPTORS);
    }

    private static void addCommonLifecycleInterceptionSupport(final ComponentConfiguration configuration, ServiceBuilder<?> builder, final ServiceName bindingServiceName, final ServiceName beanManagerServiceName, final ComponentInterceptorSupport componentInterceptorSupport) {
        configuration.addPreDestroyInterceptor(factory(InterceptionType.PRE_DESTROY, builder, bindingServiceName, componentInterceptorSupport), InterceptorOrder.ComponentPreDestroy.CDI_INTERCEPTORS);
        configuration.addAroundConstructInterceptor(factory(InterceptionType.AROUND_CONSTRUCT, builder, bindingServiceName, componentInterceptorSupport), InterceptorOrder.AroundConstruct.WELD_AROUND_CONSTRUCT_INTERCEPTORS);
        configuration.addPostConstructInterceptor(factory(InterceptionType.POST_CONSTRUCT, builder, bindingServiceName, componentInterceptorSupport), InterceptorOrder.ComponentPostConstruct.CDI_INTERCEPTORS);
        /*
         * Add interceptor to activate the request scope for the @PostConstruct callback.
         * See https://issues.jboss.org/browse/CDI-219 for details
         */
        final EjbRequestScopeActivationInterceptor.Factory postConstructRequestContextActivationFactory = new EjbRequestScopeActivationInterceptor.Factory(beanManagerServiceName);
        configuration.addPostConstructInterceptor(postConstructRequestContextActivationFactory, InterceptorOrder.ComponentPostConstruct.REQUEST_SCOPE_ACTIVATING_INTERCEPTOR);
        // @AroundConstruct support
        configuration.addAroundConstructInterceptor(new ImmediateInterceptorFactory(WeldConstructionStartInterceptor.INSTANCE), InterceptorOrder.AroundConstruct.CONSTRUCTION_START_INTERCEPTOR);
    }

    @Override
    public void undeploy(DeploymentUnit context) {
    }

    /**
     * Retrieves ManagedReference from the interceptor context and performs an InjectionTarget operation on the instance
     */
    private abstract static class AbstractInjectionTargetDelegatingInterceptor implements Interceptor {

        @Override
        public Object processInvocation(InterceptorContext context) throws Exception {
            ManagedReference reference = (ManagedReference) context.getPrivateData(ComponentInstance.class).getInstanceData(BasicComponentInstance.INSTANCE_KEY);
            if (reference != null) {
                run(reference.getInstance());
            }
            return context.proceed();
        }

        protected abstract void run(Object instance);
    }

}


package org.wildfly.extension.batch.jberet;

import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.Services;
import org.jboss.as.threads.ThreadsServices;
import org.jboss.msc.service.ServiceName;

/**
 * Service names for the batch subsystem.
 *
 * @author James R. Perkins
 */
public class BatchServiceNames {

    /**
     * The default service name fo the thread-pool
     */
    public static final ServiceName BASE_BATCH_THREAD_POOL_NAME = ThreadsServices.EXECUTOR.append("batch");

    /**
     * Creates a service name for the batch environment service.
     *
     * @param deploymentUnit the deployment unit to create the service name for
     *
     * @return the service name
     */
    public static ServiceName batchEnvironmentServiceName(final DeploymentUnit deploymentUnit) {
        return deploymentUnit.getServiceName().append("batch").append("environment");
    }

    /**
     * Creates a service name for the {@linkplain org.jberet.spi.ArtifactFactory artifact factory} service.
     *
     * @param deploymentUnit the deployment unit to create the service name for
     *
     * @return the service name
     */
    public static ServiceName batchArtifactFactoryServiceName(final DeploymentUnit deploymentUnit) {
        return deploymentUnit.getServiceName().append("batch").append("artifact").append("factory");
    }

    /**
     * Creates the service name used for the bean manager on the deployment.
     *
     * @param deploymentUnit the deployment unit to create the service name for
     *
     * @return the service name
     */
    public static ServiceName beanManagerServiceName(final DeploymentUnit deploymentUnit) {
        return deploymentUnit.getServiceName().append("beanmanager");
    }

    /**
     * Creates the service name used for the job operator registered for the deployment.
     *
     * @param deploymentUnit the deployment unit where the operator is to be registered
     *
     * @return the service name
     */
    public static ServiceName jobOperatorServiceName(final DeploymentUnit deploymentUnit) {
        return deploymentUnit.getServiceName().append("batch").append("job-operator");
    }

    /**
     * Creates the service name used for the job operator registered for the deployment.
     *
     * @param deploymentRuntimeName the runtime name for the deployment
     *
     * @return the service name
     */
    public static ServiceName jobOperatorServiceName(final String deploymentRuntimeName) {
        return Services.deploymentUnitName(deploymentRuntimeName).append("batch").append("job-operator");
    }

    /**
     * Creates the service name used for the job operator registered for the deployment.
     *
     * @param deploymentRuntimeName the runtime name for the deployment
     * @param subdeploymentName     the name of the subdeployment
     *
     * @return the service name
     */
    public static ServiceName jobOperatorServiceName(final String deploymentRuntimeName, final String subdeploymentName) {
        return Services.deploymentUnitName(deploymentRuntimeName, subdeploymentName).append("batch").append("job-operator");
    }
}


/*
 * 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.ee.component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jboss.vfs.VirtualFile;

/**
 * @author John Bailey
 */
public class EEApplicationDescription {
    //these are only written to by a single top level processor, so do not need to be synchronized
    private final Map<String, List<ViewInformation>> componentsByViewName = new HashMap<String, List<ViewInformation>>();
    private final Map<String, List<Description>> componentsByName = new HashMap<String, List<Description>>();

    //this must be synchronized for writing
    private final Map<String, List<MessageDestinationMapping>> messageDestinationJndiMapping = new HashMap<String, List<MessageDestinationMapping>>();

    /**
     * Add a component to this application.
     *
     * @param description    the component description
     * @param deploymentRoot
     */
    public void addComponent(final ComponentDescription description, final VirtualFile deploymentRoot) {
        for (final ViewDescription viewDescription : description.getViews()) {
            List<ViewInformation> viewComponents = componentsByViewName.get(viewDescription.getViewClassName());
            if (viewComponents == null) {
                viewComponents = new ArrayList<ViewInformation>(1);
                componentsByViewName.put(viewDescription.getViewClassName(), viewComponents);
            }
            viewComponents.add(new ViewInformation(viewDescription, deploymentRoot, description.getComponentName()));
        }
        List<Description> components = componentsByName.get(description.getComponentName());
        if (components == null) {
            componentsByName.put(description.getComponentName(), components = new ArrayList<Description>(1));
        }
        components.add(new Description(description, deploymentRoot));
    }

    /**
     * Add a message destination to the application
     *
     * @param name           The message destination name
     * @param resolvedName   The resolved JNDI name
     * @param deploymentRoot The deployment root
     */
    public void addMessageDestination(final String name, final String resolvedName, final VirtualFile deploymentRoot) {
        List<MessageDestinationMapping> components = messageDestinationJndiMapping.get(name);
        if (components == null) {
            messageDestinationJndiMapping.put(name, components = new ArrayList<MessageDestinationMapping>(1));
        }
        components.add(new MessageDestinationMapping(resolvedName, deploymentRoot));
    }

    /**
     * Get all views that have the given type in the application
     *
     * @param viewType The view type
     * @return All views of the given type
     */
    public Set<ViewDescription> getComponentsForViewName(final String viewType, final VirtualFile deploymentRoot) {
        final List<ViewInformation> info = componentsByViewName.get(viewType);

        if (info == null) {
            return Collections.<ViewDescription>emptySet();
        }
        final Set<ViewDescription> ret = new HashSet<ViewDescription>();
        final Set<ViewDescription> currentDep = new HashSet<ViewDescription>();
        for (ViewInformation i : info) {
            if (deploymentRoot.equals(i.deploymentRoot)) {
                currentDep.add(i.viewDescription);
            }
            ret.add(i.viewDescription);
        }
        if(!currentDep.isEmpty()) {
            return currentDep;
        }
        return ret;
    }

    /**
     * Get all components in the application that have the given name
     *
     * @param componentName  The name of the component
     * @param deploymentRoot The deployment root of the component doing the lookup
     * @return A set of all views for the given component name and type
     */
    public Set<ComponentDescription> getComponents(final String componentName, final VirtualFile deploymentRoot) {
        if (componentName.contains("#")) {
            final String[] parts = componentName.split("#");
            String path = parts[0];
            if (!path.startsWith("../")) {
                path = "../" + path;
            }
            final VirtualFile virtualPath = deploymentRoot.getChild(path);
            final String name = parts[1];
            final List<Description> info = componentsByName.get(name);
            if (info == null) {
                return Collections.emptySet();
            }
            final Set<ComponentDescription> ret = new HashSet<ComponentDescription>();
            for (Description i : info) {
                //now we need to check the path
                if (virtualPath.equals(i.deploymentRoot)) {
                    ret.add(i.componentDescription);
                }
            }
            return ret;
        } else {
            final List<Description> info = componentsByName.get(componentName);
            if (info == null) {
                return Collections.emptySet();
            }
            final Set<ComponentDescription> all = new HashSet<ComponentDescription>();
            final Set<ComponentDescription> thisDeployment = new HashSet<ComponentDescription>();
            for (Description i : info) {
                all.add(i.componentDescription);
                if (i.deploymentRoot.equals(deploymentRoot)) {
                    thisDeployment.add(i.componentDescription);
                }
            }
            //if there are multiple e
            if (all.size() > 1) {
                return thisDeployment;
            }
            return all;
        }
    }

    /**
     * Get all views in the application that have the given name and view type
     *
     * @param componentName  The name of the component
     * @param viewName       The view type
     * @param deploymentRoot The deployment root of the component doing the lookup
     * @return A set of all views for the given component name and type
     */
    public Set<ViewDescription> getComponents(final String componentName, final String viewName, final VirtualFile deploymentRoot) {
        final List<ViewInformation> info = componentsByViewName.get(viewName);
        if (info == null) {
            return Collections.<ViewDescription>emptySet();
        }
        if (componentName.contains("#")) {
            final String[] parts = componentName.split("#");
            String path = parts[0];
            if (!path.startsWith("../")) {
                path = "../" + path;
            }
            final VirtualFile virtualPath = deploymentRoot.getChild(path);
            final String name = parts[1];
            final Set<ViewDescription> ret = new HashSet<ViewDescription>();
            for (ViewInformation i : info) {
                if (i.beanName.equals(name)) {
                    //now we need to check the path
                    if (virtualPath.equals(i.deploymentRoot)) {
                        ret.add(i.viewDescription);
                    }
                }
            }
            return ret;
        } else {
            final Set<ViewDescription> all = new HashSet<ViewDescription>();
            final Set<ViewDescription> thisDeployment = new HashSet<ViewDescription>();
            for (ViewInformation i : info) {
                if (i.beanName.equals(componentName)) {
                    all.add(i.viewDescription);
                    if (i.deploymentRoot.equals(deploymentRoot)) {
                        thisDeployment.add(i.viewDescription);
                    }
                }
            }
            if (all.size() > 1) {
                return thisDeployment;
            }
            return all;
        }
    }

    /**
     * Resolves a message destination name into a JNDI name
     */
    public Set<String> resolveMessageDestination(final String messageDestName, final VirtualFile deploymentRoot) {

        if (messageDestName.contains("#")) {
            final String[] parts = messageDestName.split("#");
            String path = parts[0];
            if (!path.startsWith("../")) {
                path = "../" + path;
            }
            final VirtualFile virtualPath = deploymentRoot.getChild(path);
            final String name = parts[1];
            final Set<String> ret = new HashSet<String>();
            final List<MessageDestinationMapping> data = messageDestinationJndiMapping.get(name);
            if (data != null) {
                for (final MessageDestinationMapping i : data) {
                    //now we need to check the path
                    if (virtualPath.equals(i.deploymentRoot)) {
                        ret.add(i.jndiName);
                    }
                }
            }
            return ret;
        } else {
            final Set<String> all = new HashSet<String>();
            final Set<String> thisDeployment = new HashSet<String>();
            final List<MessageDestinationMapping> data = messageDestinationJndiMapping.get(messageDestName);
            if (data != null) {
                for (final MessageDestinationMapping i : data) {
                    all.add(i.jndiName);
                    if (i.deploymentRoot.equals(deploymentRoot)) {
                        thisDeployment.add(i.jndiName);
                    }
                }
            }
            if (all.size() > 1) {
                return thisDeployment;
            }
            return all;
        }
    }

    private static class ViewInformation {
        private final ViewDescription viewDescription;
        private final VirtualFile deploymentRoot;
        private final String beanName;

        ViewInformation(final ViewDescription viewDescription, final VirtualFile deploymentRoot, final String beanName) {
            this.viewDescription = viewDescription;
            this.deploymentRoot = deploymentRoot;
            this.beanName = beanName;
        }
    }

    private static class Description {
        private final ComponentDescription componentDescription;
        private final VirtualFile deploymentRoot;

        Description(final ComponentDescription componentDescription, final VirtualFile deploymentRoot) {
            this.componentDescription = componentDescription;
            this.deploymentRoot = deploymentRoot;
        }
    }

    private static final class MessageDestinationMapping {
        private final String jndiName;
        private final VirtualFile deploymentRoot;

        MessageDestinationMapping(final String jndiName, final VirtualFile deploymentRoot) {
            this.jndiName = jndiName;
            this.deploymentRoot = deploymentRoot;
        }
    }

}


/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2012, 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.messaging;

import static org.jboss.as.controller.PathElement.pathElement;
import static org.jboss.as.controller.transform.description.RejectAttributeChecker.DEFINED;
import static org.jboss.as.messaging.AddressSettingDefinition.MAX_REDELIVERY_DELAY;
import static org.jboss.as.messaging.AddressSettingDefinition.REDELIVERY_MULTIPLIER;
import static org.jboss.as.messaging.AddressSettingDefinition.SLOW_CONSUMER_CHECK_PERIOD;
import static org.jboss.as.messaging.AddressSettingDefinition.SLOW_CONSUMER_POLICY;
import static org.jboss.as.messaging.AddressSettingDefinition.SLOW_CONSUMER_THRESHOLD;
import static org.jboss.as.messaging.CommonAttributes.HORNETQ_SERVER;
import static org.jboss.as.messaging.CommonAttributes.OVERRIDE_IN_VM_SECURITY;
import static org.jboss.as.messaging.CommonAttributes.RETRY_INTERVAL_MULTIPLIER;
import static org.jboss.as.messaging.MessagingExtension.VERSION_1_3_0;
import static org.jboss.as.messaging.MessagingExtension.VERSION_1_4_0;
import static org.jboss.as.messaging.MessagingExtension.VERSION_2_0_0;
import static org.jboss.as.messaging.MessagingExtension.VERSION_2_1_0;

import java.math.BigDecimal;

import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.ModelVersion;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.SubsystemRegistration;
import org.jboss.as.controller.transform.TransformationContext;
import org.jboss.as.controller.transform.description.AttributeConverter;
import org.jboss.as.controller.transform.description.ChainedTransformationDescriptionBuilder;
import org.jboss.as.controller.transform.description.DiscardAttributeChecker.DiscardAttributeValueChecker;
import org.jboss.as.controller.transform.description.ResourceTransformationDescriptionBuilder;
import org.jboss.as.controller.transform.description.TransformationDescriptionBuilder;
import org.jboss.as.messaging.jms.ConnectionFactoryDefinition;
import org.jboss.as.messaging.jms.PooledConnectionFactoryDefinition;
import org.jboss.dmr.ModelNode;

/**
 * Resource transformations for the messaging subsystem.
 *

 * Jeff Mesnil (c) 2012 Red Hat, inc.
 */

public class MessagingTransformers {

    static void registerTransformers(final SubsystemRegistration subsystem) {
        ChainedTransformationDescriptionBuilder chainedBuilder = TransformationDescriptionBuilder.Factory.createChainedSubystemInstance(subsystem.getSubsystemVersion());

        // Current
        // 3.0.0 -> 2.1.0 (WildFly 8.1.0.Final)
        buildTransformers2_1_0(chainedBuilder.createBuilder(subsystem.getSubsystemVersion(), VERSION_2_1_0));
        // 2.1.0 -> 2.0.0 (WildFly 8.0.0.Final)
        buildTransformers2_0_0(chainedBuilder.createBuilder(VERSION_2_1_0, VERSION_2_0_0));
        // 2.0.0 -> 1.4.0 (AS7 7.5.0) EAP 6.4
        buildTransformers1_4_0(chainedBuilder.createBuilder(VERSION_2_0_0, VERSION_1_4_0));
        // 1.4.0 -> 1.3.0 (AS7 7.3.0) EAP 6.2 & EAP 6.3
        buildTransformers1_3_0(chainedBuilder.createBuilder(VERSION_1_4_0, VERSION_1_3_0));

        chainedBuilder.buildAndRegister(subsystem, new ModelVersion[]{
                VERSION_1_3_0,
                VERSION_1_4_0,
                VERSION_2_0_0,
                VERSION_2_1_0
        });
    }

    /**
     * Transformation for WildFly 8.1.0.Final
     */
    private static void buildTransformers2_1_0(ResourceTransformationDescriptionBuilder builder) {
        ResourceTransformationDescriptionBuilder hornetqServer = builder.addChildResource(pathElement(HORNETQ_SERVER));
        ResourceTransformationDescriptionBuilder addressSetting = hornetqServer.addChildResource(AddressSettingDefinition.PATH);
        rejectDefinedAttributeWithDefaultValue(addressSetting, MAX_REDELIVERY_DELAY, REDELIVERY_MULTIPLIER);

        ResourceTransformationDescriptionBuilder bridge = hornetqServer.addChildResource(BridgeDefinition.PATH);
        bridge.getAttributeBuilder().setValueConverter(new DoubleToBigDecimalConverter(), RETRY_INTERVAL_MULTIPLIER);

        ResourceTransformationDescriptionBuilder clusterConnection = hornetqServer.addChildResource(ClusterConnectionDefinition.PATH);
        clusterConnection.getAttributeBuilder().setValueConverter(new DoubleToBigDecimalConverter(), RETRY_INTERVAL_MULTIPLIER);

        ResourceTransformationDescriptionBuilder connectionFactory = hornetqServer.addChildResource(ConnectionFactoryDefinition.PATH);
        connectionFactory.getAttributeBuilder().setValueConverter(new DoubleToBigDecimalConverter(), RETRY_INTERVAL_MULTIPLIER);

        ResourceTransformationDescriptionBuilder pooledConnectionFactory = hornetqServer.addChildResource(PooledConnectionFactoryDefinition.PATH);
        pooledConnectionFactory.getAttributeBuilder().setValueConverter(new DoubleToBigDecimalConverter(), RETRY_INTERVAL_MULTIPLIER);
    }

    /**
     * Transformation for WildFly 8.0.0.Final
     */
    private static void buildTransformers2_0_0(ResourceTransformationDescriptionBuilder builder) {
        // nothing has changed from 8.1.0.Final
    }

    /**
     * Transformers for EAP 6.4 / AS7 7.5.0
     */
    private static void buildTransformers1_4_0(ResourceTransformationDescriptionBuilder builder) {
        ResourceTransformationDescriptionBuilder hornetqServer = builder.addChildResource(pathElement(HORNETQ_SERVER));
        renameAttribute(hornetqServer, CommonAttributes.STATISTICS_ENABLED, CommonAttributes.MESSAGE_COUNTER_ENABLED);

        ResourceTransformationDescriptionBuilder bridge = hornetqServer.addChildResource(BridgeDefinition.PATH);
        rejectDefinedAttributeWithDefaultValue(bridge, BridgeDefinition.RECONNECT_ATTEMPTS_ON_SAME_NODE, BridgeDefinition.INITIAL_CONNECT_ATTEMPTS);

        ResourceTransformationDescriptionBuilder clusterConnection = hornetqServer.addChildResource(ClusterConnectionDefinition.PATH);
        rejectDefinedAttributeWithDefaultValue(clusterConnection, ClusterConnectionDefinition.INITIAL_CONNECT_ATTEMPTS);

        ResourceTransformationDescriptionBuilder addressSetting = hornetqServer.addChildResource(AddressSettingDefinition.PATH);
        rejectDefinedAttributeWithDefaultValue(addressSetting, AddressSettingDefinition.EXPIRY_DELAY);

    }

    /**
     * Transformation for EAP 6.2.0 / AS7 7.3.0
     */
    private static void buildTransformers1_3_0(ResourceTransformationDescriptionBuilder builder) {
        ResourceTransformationDescriptionBuilder hornetqServer = builder.addChildResource(pathElement(HORNETQ_SERVER));
        rejectDefinedAttributeWithDefaultValue(hornetqServer, OVERRIDE_IN_VM_SECURITY);

        hornetqServer.rejectChildResource(HTTPAcceptorDefinition.PATH);
        hornetqServer.rejectChildResource(pathElement(CommonAttributes.HTTP_CONNECTOR));

        ResourceTransformationDescriptionBuilder addressSetting = hornetqServer.addChildResource(AddressSettingDefinition.PATH);
        rejectDefinedAttributeWithDefaultValue(addressSetting, SLOW_CONSUMER_CHECK_PERIOD, SLOW_CONSUMER_POLICY, SLOW_CONSUMER_THRESHOLD);

    }

    /**
     * Reject the attributes if they are defined or discard them if they are undefined or set to their default value.
     */
    private static void rejectDefinedAttributeWithDefaultValue(ResourceTransformationDescriptionBuilder builder, AttributeDefinition... attrs) {
        for (AttributeDefinition attr : attrs) {
            builder.getAttributeBuilder()
                    .setDiscard(new DiscardAttributeValueChecker(attr.getDefaultValue()), attr)
                    .addRejectCheck(DEFINED, attr);
        }
    }

    /**
     * Rename an attribute
     */
    private static void renameAttribute(ResourceTransformationDescriptionBuilder builder,
                                        AttributeDefinition attribute, AttributeDefinition alias) {
        builder.getAttributeBuilder().addRename(attribute, alias.getName());
    }

    private static class DoubleToBigDecimalConverter extends AttributeConverter.DefaultAttributeConverter {
        @Override
        protected void convertAttribute(PathAddress address, String attributeName, ModelNode attributeValue, TransformationContext context) {
            double value = attributeValue.asDouble(RETRY_INTERVAL_MULTIPLIER.getDefaultValue().asDouble());
            attributeValue.set(new BigDecimal(value));
        }
    }

}


/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2014, 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.security.api;

import java.security.Principal;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;

import javax.security.auth.Subject;

import org.jboss.as.core.security.RealmGroup;
import org.jboss.as.core.security.RealmRole;
import org.jboss.as.core.security.RealmUser;
import org.jboss.as.core.security.api.RealmPrincipal;
import org.jboss.as.security.remoting.RemoteConnection;
import org.jboss.as.security.remoting.RemotingContext;
import org.jboss.security.SecurityContext;
import org.jboss.security.SecurityContextAssociation;
import org.jboss.security.SecurityContextFactory;
import org.wildfly.security.auth.server.SecurityIdentity;

/**
 * Utility class to allow inspection and replacement of identity associated with the Connection.
 *
 * As a connection is established to the application server the remote user is authenticated, this API allows the
 * {@link Collection} of {@link Principal}s for the remote user to be obtained, the API then allows for an alternative identity
 * to be pushed by interceptors for validation in the security interceptors for subsequent EJB invocations.
 *
 * @author Darran Lofthouse
 */
public class ConnectionSecurityContext {

    private ConnectionSecurityContext() {
    }

    /**
     * Obtain a {@link Collection} containing the {@link Principal} instances for the user associated with the connection.
     *
     * Note: This method should be called from within a {@link PrivilegedAction}.
     *
     * @return The Collection of Principals for the user authenticated with the connection. An empty Collection will be returned
     *         of no user is associated with the connection, {@code null} will be returned if no connection is associated with
     *         the {@link Thread}
     */
    public static Collection<Principal> getConnectionPrincipals() {
        RemoteConnection con = RemotingContext.getRemoteConnection();

        if (con != null) {
            Collection<Principal> principals = new HashSet<>();
            SecurityIdentity localIdentity = con.getSecurityIdentity();
            if (localIdentity != null) {
                final Principal principal = localIdentity.getPrincipal();
                final String realm = principal instanceof RealmPrincipal ? ((RealmPrincipal) principal).getRealm() : null;
                principals.add(new RealmUser(realm, principal.getName()));
                for (String role : localIdentity.getRoles()) {
                    principals.add(new RealmGroup(role));
                    principals.add(new RealmRole(role));
                }
                return principals;
            } else {
                return Collections.emptySet();
            }
        }

        return null;
    }

    /**
     * Push a new {@link Principal} and Credential pair.
     *
     * This method is to be called before an EJB invocation is passed through it's security interceptor, at that point the
     * Principal and Credential pair can be verified.
     *
     * Note: This method should be called from within a {@link PrivilegedAction}.
     *
     * @param principal - The alternative {@link Principal} to use in verification before the next EJB is called.
     * @param credential - The credential to verify with the {@linl Principal}
     * @return A {@link ContextStateCache} that can later be used to pop the identity pushed here and restore internal state to it's previous values.
     * @throws Exception If there is a problem associating the new {@link Principal} and Credential pair.
     */
    public static ContextStateCache pushIdentity(final Principal principal, final Object credential) throws Exception {
        SecurityContext current = SecurityContextAssociation.getSecurityContext();

        SecurityContext nextContext = SecurityContextFactory.createSecurityContext(principal, credential, new Subject(), "USER_DELEGATION");
        SecurityContextAssociation.setSecurityContext(nextContext);

        RemoteConnection con = RemotingContext.getRemoteConnection();
        RemotingContext.clear();

        return new ContextStateCache(con, current);
    }

    /**
     * Pop the identity previously associated and restore internal state to it's previous value.
     *
     * @param stateCache - The cache containing the state as it was when pushIdentity was called.
     */
    public static void popIdentity(final ContextStateCache stateCache) {
        RemotingContext.setConnection(stateCache.getConnection());
        SecurityContextAssociation.setSecurityContext(stateCache.getSecurityContext());
    }

}


/*
 * 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.security.context;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Enumeration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;

import org.jboss.as.naming.ContextListAndJndiViewManagedReferenceFactory;
import org.jboss.as.naming.ManagedReference;
import org.jboss.as.naming.ValueManagedReference;
import org.jboss.as.security.logging.SecurityLogger;
import org.jboss.as.security.plugins.DefaultAuthenticationCacheFactory;
import org.jboss.as.security.plugins.JNDIBasedSecurityManagement;
import org.jboss.as.security.plugins.SecurityDomainContext;
import org.jboss.modules.ModuleLoadException;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.value.ImmediateValue;
import org.jboss.msc.value.InjectedValue;
import org.jboss.security.ISecurityManagement;
import org.jboss.security.SecurityConstants;

/**
 * Implementation of {@code ManagedReferenceFactory} that returns {@code AuthenticationManager}s
 *
 * @author Marcus Moyses
 */
public class SecurityDomainJndiInjectable implements InvocationHandler, ContextListAndJndiViewManagedReferenceFactory {

    private static final String ACTIVE_SUBJECT = "subject";
    private static final String AUTHENTICATION_MGR = "authenticationMgr";
    private static final String AUTHORIZATION_MGR = "authorizationMgr";
    private static final String AUDIT_MGR = "auditMgr";
    private static final String MAPPING_MGR = "mappingMgr";
    private static final String IDENTITY_TRUST_MGR = "identityTrustMgr";
    private static final String DOMAIN_CONTEXT = "domainContext";
    private static final String JSSE = "jsse";

    private final InjectedValue<ISecurityManagement> securityManagementValue = new InjectedValue<ISecurityManagement>();

    @Override
    public String getInstanceClassName() {
        return getReference().getInstance().getClass().getName();
    }

    @Override
    public String getJndiViewInstanceValue() {
        return String.valueOf(getReference().getInstance());
    }

    /**
     * {@inheritDoc}
     *
     * This method returns a Context proxy that is only able to handle a lookup operation for an atomic name of a security
     * domain.
     */
    public ManagedReference getReference() {
        final ClassLoader loader;
        try {
            loader = SecurityActions.getModuleClassLoader();
        } catch (ModuleLoadException e) {
            throw SecurityLogger.ROOT_LOGGER.unableToGetModuleClassLoader(e);
        }
        Class<?>[] interfaces = { Context.class };
        return new ValueManagedReference(new ImmediateValue<Object>(Proxy.newProxyInstance(loader, interfaces, this)));
    }

    /**
     * This is the InvocationHandler callback for the Context interface that was created by our getObjectInstance() method. We
     * handle the java:jboss/jaas/domain level operations here.
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Context ctx = new InitialContext();
        NameParser parser = ctx.getNameParser("");
        String securityDomain = null;
        Name name = null;

        final JNDIBasedSecurityManagement securityManagement = JNDIBasedSecurityManagement.class.cast(securityManagementValue
                .getValue());
        final ConcurrentHashMap<String, SecurityDomainContext> securityManagerMap = securityManagement.getSecurityManagerMap();

        String methodName = method.getName();
        if (methodName.equals("toString"))
            return SecurityConstants.JAAS_CONTEXT_ROOT + " Context proxy";

        if (methodName.equals("list"))
            return new DomainEnumeration(securityManagerMap.keys(), securityManagerMap);

        if (methodName.equals("bind") || methodName.equals("rebind")) {
            if (args[0] instanceof String)
                name = parser.parse((String) args[0]);
            else
                name = (Name) args[0];
            securityDomain = name.get(0);
            SecurityDomainContext val = (SecurityDomainContext) args[1];
            securityManagerMap.put(securityDomain, val);
            return proxy;
        }
        if (!methodName.equals("lookup"))
            throw SecurityLogger.ROOT_LOGGER.operationNotSupported(method);
        if (args[0] instanceof String)
            name = parser.parse((String) args[0]);
        else
            name = (Name) args[0];
        securityDomain = name.get(0);
        SecurityDomainContext securityDomainCtx = lookupSecurityDomain(securityManagement, securityManagerMap, securityDomain);
        Object binding = securityDomainCtx.getAuthenticationManager();
        // Look for requests against the security domain context
        if (name.size() == 2) {
            String request = name.get(1);
            binding = lookup(securityDomainCtx, request);
        }
        return binding;
    }

    /**
     * Creates a {@code SecurityDomainContext} if one cannot be found in JNDI for a given security domain
     *
     * @param securityManagement security management
     * @param securityManagerMap security manager map
     * @param securityDomain the name of the security domain
     * @return an instance of {@code SecurityDomainContext}
     * @throws Exception if an error occurs
     */
    private SecurityDomainContext lookupSecurityDomain(final JNDIBasedSecurityManagement securityManagement,
            final ConcurrentHashMap<String, SecurityDomainContext> securityManagerMap, final String securityDomain)
            throws Exception {
        SecurityDomainContext sdc = securityManagerMap.get(securityDomain);
        if (sdc == null) {
            sdc = securityManagement.createSecurityDomainContext(securityDomain, new DefaultAuthenticationCacheFactory());
            securityManagerMap.put(securityDomain, sdc);
        }
        return sdc;
    }

    private static Object lookup(SecurityDomainContext securityDomainContext, String name) throws NamingException {
        Object binding = null;
        if (name == null || name.length() == 0)
            throw SecurityLogger.ROOT_LOGGER.nullName();

        if (name.equals(ACTIVE_SUBJECT))
            binding = securityDomainContext.getSubject();
        else if (name.equals(AUTHENTICATION_MGR))
            binding = securityDomainContext.getAuthenticationManager();
        else if (name.equals(AUTHORIZATION_MGR))
            binding = securityDomainContext.getAuthorizationManager();
        else if (name.equals(AUDIT_MGR))
            binding = securityDomainContext.getAuditManager();
        else if (name.equals(MAPPING_MGR))
            binding = securityDomainContext.getMappingManager();
        else if (name.equals(IDENTITY_TRUST_MGR))
            binding = securityDomainContext.getIdentityTrustManager();
        else if (name.equals(DOMAIN_CONTEXT))
            binding = securityDomainContext;
        else if (name.equals(JSSE))
            binding = securityDomainContext.getJSSE();

        return binding;

    }

    public Injector<ISecurityManagement> getSecurityManagementInjector() {
        return securityManagementValue;
    }

    /**
     * Enumeration for the bound security domains in JNDI
     *
     * @author Marcus Moyses
     */
    class DomainEnumeration implements NamingEnumeration<NameClassPair> {
        Enumeration<String> domains;
        Map<String, SecurityDomainContext> ctxMap;

        DomainEnumeration(Enumeration<String> domains, Map<String, SecurityDomainContext> ctxMap) {
            this.domains = domains;
            this.ctxMap = ctxMap;
        }

        public void close() {
        }

        public boolean hasMoreElements() {
            return domains.hasMoreElements();
        }

        public boolean hasMore() {
            return domains.hasMoreElements();
        }

        public NameClassPair next() {
            String name = (String) domains.nextElement();
            Object value = ctxMap.get(name);
            String className = value.getClass().getName();
            NameClassPair pair = new NameClassPair(name, className);
            return pair;
        }

        public NameClassPair nextElement() {
            return next();
        }
    }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @author tags. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License, v. 2.1.
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * 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,
 * v.2.1 along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */

package org.jboss.as.jsf.deployment;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jboss.as.jsf.logging.JSFLogger;
import org.jboss.as.jsf.subsystem.JSFResourceDefinition;
import org.jboss.modules.ModuleIdentifier;

/**
 * This class finds all the installed JSF implementations and provides their ModuleId's.
 *
 * @author Stan Silvert ssilvert@redhat.com (C) 2012 Red Hat Inc.
 */
public class JSFModuleIdFactory {
    private static final String API_MODULE = "javax.faces.api";
    private static final String IMPL_MODULE = "com.sun.jsf-impl";
    private static final String INJECTION_MODULE = "org.jboss.as.jsf-injection";

    private static final JSFModuleIdFactory instance = new JSFModuleIdFactory();

    // The default JSF impl slot.  This can be overridden by the management layer.
    private String defaultSlot = JSFResourceDefinition.DEFAULT_SLOT;

    private Map<String, ModuleIdentifier> apiIds = new HashMap<String, ModuleIdentifier>();
    private Map<String, ModuleIdentifier> implIds = new HashMap<String, ModuleIdentifier>();
    private Map<String, ModuleIdentifier> injectionIds = new HashMap<String, ModuleIdentifier>();

    private Set<String> allVersions = new HashSet<String>();
    private List<String> activeVersions = new ArrayList<String>();

    public static JSFModuleIdFactory getInstance() {
        return instance;
    }

    private JSFModuleIdFactory() {
        String modulePath = System.getProperty("module.path", System.getenv("JAVA_MODULEPATH"));
        if (!isBogusPath(modulePath)) {
            loadIdsFromModulePath(modulePath);
        }

        if (!activeVersions.contains("main")) {
            loadIdsManually();
        }

        JSFLogger.ROOT_LOGGER.activatedJSFImplementations(activeVersions);
    }

    void setDefaultSlot(String defaultSlot) {
        this.defaultSlot = defaultSlot;
    }

    String getDefaultSlot() {
        return this.defaultSlot;
    }

    private boolean isBogusPath(String path) {
        if (path == null) return true;

        // must have at least one existing directory in the path
        for (String dir : path.split(File.pathSeparator)) {
            if (new File(dir).exists()) return false;
        }

        return true; // no directory in the path exists
    }

    // just provide the default implementations
    private void loadIdsManually() {
        implIds.put("main", ModuleIdentifier.create(IMPL_MODULE));
        apiIds.put("main", ModuleIdentifier.create(API_MODULE));
        injectionIds.put("main", ModuleIdentifier.create(INJECTION_MODULE));

        allVersions.add("main");

        activeVersions.add("main");
    }

    private void loadIdsFromModulePath(String modulePath) {
        for (String moduleRootDir : modulePath.split(File.pathSeparator)) {
            loadIds(moduleRootDir, apiIds, API_MODULE);
            loadIds(moduleRootDir, implIds, IMPL_MODULE);
            loadIds(moduleRootDir, injectionIds, INJECTION_MODULE);
        }
        checkVersionIntegrity();
    }

    private void loadIds(String moduleRootDir, Map<String, ModuleIdentifier> idMap, String moduleName) {
        StringBuilder baseDirBuilder = new StringBuilder(moduleRootDir);
        baseDirBuilder.append(File.separator);
        baseDirBuilder.append(moduleName.replace(".", File.separator));

        File moduleBaseDir = new File(baseDirBuilder.toString());
        File[] slots = moduleBaseDir.listFiles(new FileFilter() {
            public boolean accept(File pathname) {
                return pathname.isDirectory();
            }
        });

        if (slots == null) return;

        for (File slot : slots) {
            if (!new File(slot, "module.xml").exists()) continue; // make sure directory represents a real module
            String slotName = slot.getName();
            allVersions.add(slotName);
            idMap.put(slotName, ModuleIdentifier.create(moduleName, slotName));
        }
    }

    // make sure that each version has api, impl, and injection
    private void checkVersionIntegrity() {
        activeVersions.addAll(allVersions);

        for (String version : allVersions) {
            if (!apiIds.containsKey(version)) {
                JSFLogger.ROOT_LOGGER.missingJSFModule(version, API_MODULE);
                activeVersions.remove(version);
            }

            if (!implIds.containsKey(version)) {
                JSFLogger.ROOT_LOGGER.missingJSFModule(version, IMPL_MODULE);
                activeVersions.remove(version);
            }

            if (!injectionIds.containsKey(version)) {
                JSFLogger.ROOT_LOGGER.missingJSFModule(version, INJECTION_MODULE);
                activeVersions.remove(version);
            }
        }
    }

    /**
     * If needed, convert old JSFVersionMarker values to slot values.
     *
     * @param jsfVersion The version value from JSFVersionMarker, or null for default slot.
     * @return The equivalent slot value.
     */
    String computeSlot(String jsfVersion) {
        if (jsfVersion == null) return defaultSlot;
        if (JsfVersionMarker.JSF_2_0.equals(jsfVersion)) return defaultSlot;
        return jsfVersion;
    }

    ModuleIdentifier getApiModId(String jsfVersion) {
        return this.apiIds.get(computeSlot(jsfVersion));
    }

    ModuleIdentifier getImplModId(String jsfVersion) {
        return this.implIds.get(computeSlot(jsfVersion));
    }

    ModuleIdentifier getInjectionModId(String jsfVersion) {
        return this.injectionIds.get(computeSlot(jsfVersion));
    }

    boolean isValidJSFSlot(String slot) {
        String computedSlot = computeSlot(slot);
        return apiIds.containsKey(computedSlot) && implIds.containsKey(computedSlot) && injectionIds.containsKey(computedSlot);
    }

    /**
     * Return the slot id's of all active JSF versions.
     *
     * @return The slot id's of all active JSF versions.
     */
    public List<String> getActiveJSFVersions() {
        return Collections.unmodifiableList(activeVersions);
    }

}


/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2012, 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.jsf.subsystem;

import org.jboss.as.controller.Extension;
import org.jboss.as.controller.ExtensionContext;
import org.jboss.as.controller.ModelVersion;
import org.jboss.as.controller.PathElement;
import org.jboss.as.controller.PersistentResourceXMLDescription;
import org.jboss.as.controller.PersistentResourceXMLParser;
import org.jboss.as.controller.SubsystemRegistration;
import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver;
import org.jboss.as.controller.parsing.ExtensionParsingContext;
import org.jboss.as.jsf.logging.JSFLogger;

import static org.jboss.as.controller.PersistentResourceXMLDescription.builder;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;

/**
 * Domain extension used to initialize the jsf subsystem.
 *
 * @author Stuart Douglas
 * @author Emanuel Muckenhuber
 * @author Stan Silvert
 */
public class JSFExtension implements Extension {

    public static final String SUBSYSTEM_NAME = "jsf";
    public static final String NAMESPACE_1_0 = "urn:jboss:domain:jsf:1.0";
    public static final String NAMESPACE_1_1 = "urn:jboss:domain:jsf:1.1";

    static final PathElement PATH_SUBSYSTEM = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);

    private static final String RESOURCE_NAME = JSFExtension.class.getPackage().getName() + ".LocalDescriptions";

    private static final ModelVersion CURRENT_MODEL_VERSION = ModelVersion.create(1, 1, 0);

    static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
        StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
        for (String kp : keyPrefix) {
            prefix.append('.').append(kp);
        }
        return new StandardResourceDescriptionResolver(prefix.toString(), RESOURCE_NAME, JSFExtension.class.getClassLoader(), true, false);
    }

    /** {@inheritDoc} */
    @Override
    public void initialize(final ExtensionContext context) {
        JSFLogger.ROOT_LOGGER.debug("Activating JSF(Mojarra) Extension");
        final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, CURRENT_MODEL_VERSION);
        subsystem.registerSubsystemModel(JSFResourceDefinition.INSTANCE);
        subsystem.registerXMLElementWriter(JSFSubsystemParser_1_1.INSTANCE);
    }

    /** {@inheritDoc} */
    @Override
    public void initializeParsers(final ExtensionParsingContext context) {
        context.setSubsystemXmlMapping(SUBSYSTEM_NAME, JSFExtension.NAMESPACE_1_0, () -> JSFSubsystemParser_1_0.INSTANCE);
        context.setSubsystemXmlMapping(SUBSYSTEM_NAME, JSFExtension.NAMESPACE_1_1, () -> JSFSubsystemParser_1_1.INSTANCE);
    }

    static class JSFSubsystemParser_1_0 extends PersistentResourceXMLParser {

        private static final JSFSubsystemParser_1_0 INSTANCE = new JSFSubsystemParser_1_0();

        private static final PersistentResourceXMLDescription xmlDescription;

        static {
            xmlDescription = builder(JSFResourceDefinition.INSTANCE.getPathElement(), NAMESPACE_1_0)
                    .addAttributes(JSFResourceDefinition.DEFAULT_JSF_IMPL_SLOT)
                    .build();
        }

        @Override
        public PersistentResourceXMLDescription getParserDescription() {
            return xmlDescription;
        }
    }

    static class JSFSubsystemParser_1_1 extends PersistentResourceXMLParser {

        private static final JSFSubsystemParser_1_1 INSTANCE = new JSFSubsystemParser_1_1();
        private static final PersistentResourceXMLDescription xmlDescription;

        static {
            xmlDescription = builder(JSFResourceDefinition.INSTANCE, NAMESPACE_1_1)
                    .addAttributes(JSFResourceDefinition.DEFAULT_JSF_IMPL_SLOT)
                    .addAttributes(JSFResourceDefinition.DISALLOW_DOCTYPE_DECL)
                    .build();
        }

        @Override
        public PersistentResourceXMLDescription getParserDescription() {
            return xmlDescription;
        }
    }
}


/*
 * 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.security.service;

import org.jboss.as.security.SecurityExtension;
import org.jboss.as.security.logging.SecurityLogger;
import org.jboss.as.security.plugins.JNDIBasedSecurityManagement;
import org.jboss.as.server.moduleservice.ServiceModuleLoader;
import org.jboss.msc.inject.Injector;
import org.jboss.msc.service.Service;
import org.jboss.msc.service.ServiceName;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedValue;
import org.jboss.security.ISecurityManagement;
import org.picketbox.factories.SecurityFactory;

/**
 * Security Management service for the security container
 *
 * @author Marcus Moyses
 */
public class SecurityManagementService implements Service<ISecurityManagement> {

    public static final ServiceName SERVICE_NAME = SecurityExtension.JBOSS_SECURITY.append("security-management");

    private final String authenticationManagerClassName;

    private final boolean deepCopySubjectMode;

    private final String callbackHandlerClassName;

    private final String authorizationManagerClassName;

    private final String auditManagerClassName;

    private final String identityTrustManagerClassName;

    private final String mappingManagerClassName;

    private volatile ISecurityManagement previousSecurityManagement;
    private volatile ISecurityManagement securityManagement;

    private final InjectedValue<ServiceModuleLoader> serviceModuleLoaderValue = new InjectedValue<ServiceModuleLoader>();

    public SecurityManagementService(String authenticationManagerClassName, boolean deepCopySubjectMode,
            String callbackHandlerClassName, String authorizationManagerClassName, String auditManagerClassName,
            String identityTrustManagerClassName, String mappingManagerClassName) {
        this.authenticationManagerClassName = authenticationManagerClassName;
        this.deepCopySubjectMode = deepCopySubjectMode;
        this.callbackHandlerClassName = callbackHandlerClassName;
        this.authorizationManagerClassName = authorizationManagerClassName;
        this.auditManagerClassName = auditManagerClassName;
        this.identityTrustManagerClassName = identityTrustManagerClassName;
        this.mappingManagerClassName = mappingManagerClassName;
    }

    /** {@inheritDoc} */
    @Override
    public void start(StartContext context) throws StartException {
        SecurityLogger.ROOT_LOGGER.debugf("Starting SecurityManagementService");
        // set properties of JNDIBasedSecurityManagement
        JNDIBasedSecurityManagement securityManagement = new JNDIBasedSecurityManagement(serviceModuleLoaderValue.getValue());
        securityManagement.setAuthenticationManagerClassName(authenticationManagerClassName);
        securityManagement.setDeepCopySubjectMode(deepCopySubjectMode);
        securityManagement.setCallbackHandlerClassName(callbackHandlerClassName);
        securityManagement.setAuthorizationManagerClassName(authorizationManagerClassName);
        securityManagement.setAuditManagerClassName(auditManagerClassName);
        securityManagement.setIdentityTrustManagerClassName(identityTrustManagerClassName);
        securityManagement.setMappingManagerClassName(mappingManagerClassName);
        this.securityManagement = securityManagement;

        previousSecurityManagement = SecurityFactory.getSecurityManagement();
        SecurityFactory.setSecurityManagement(securityManagement);
    }

    /** {@inheritDoc} */
    @Override
    public void stop(StopContext context) {
        SecurityFactory.setSecurityManagement(previousSecurityManagement);
    }

    /** {@inheritDoc} */
    @Override
    public ISecurityManagement getValue() throws IllegalStateException {
        return securityManagement;
    }

    public Injector<ServiceModuleLoader> getServiceModuleLoaderInjectedValue() {
        return serviceModuleLoaderValue;
    }
}