/*
 * 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 org.jboss.as.ee.logging.EeLogger;
import org.jboss.as.naming.ContextListManagedReferenceFactory;
import org.jboss.as.naming.ManagedReference;
import org.jboss.as.naming.ManagedReferenceFactory;
import org.jboss.msc.inject.InjectionException;

/**
 * A managed reference factory for a component view.
 *
 * @author David M. Lloyd
 */
public final class ViewManagedReferenceFactory implements ContextListManagedReferenceFactory {
    private final ComponentView view;

    /**
     * Construct a new instance.
     *
     * @param view the component view
     */
    public ViewManagedReferenceFactory(final ComponentView view) {
        this.view = view;
    }

    @Override
    public String getInstanceClassName() {
        return view.getComponent().getComponentClass().getName();
    }

    /** {@inheritDoc} */
    public ManagedReference getReference() {
        try {
            return view.createInstance();
        } catch (Exception e) {
            throw EeLogger.ROOT_LOGGER.componentViewConstructionFailure(e);
        }
    }

    /**
     * The bridge injector for binding views into JNDI.  Injects a {@link ComponentView}
     * wrapped as a {@link ManagedReferenceFactory}.
     */
    public static class Injector implements org.jboss.msc.inject.Injector<ComponentView> {
        private final org.jboss.msc.inject.Injector<ManagedReferenceFactory> referenceFactoryInjector;

        /**
         * Construct a new instance.
         *
         * @param referenceFactoryInjector the injector from the binder service
         */
        public Injector(final org.jboss.msc.inject.Injector<ManagedReferenceFactory> referenceFactoryInjector) {
            this.referenceFactoryInjector = referenceFactoryInjector;
        }

        /** {@inheritDoc} */
        public void inject(final ComponentView value) throws InjectionException {
            referenceFactoryInjector.inject(new ViewManagedReferenceFactory(value));
        }

        /** {@inheritDoc} */
        public void uninject() {
            referenceFactoryInjector.uninject();
        }
    }

}


/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2011, Red Hat Middleware LLC, 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.webservices.tomcat;

import java.util.Arrays;
import java.util.List;

import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.web.common.WarMetaData;
import org.jboss.as.webservices.config.ServerHostInfo;
import org.jboss.as.webservices.logging.WSLogger;
import org.jboss.as.webservices.util.ASHelper;
import org.jboss.as.webservices.util.WebMetaDataHelper;
import org.jboss.metadata.ear.spec.EarMetaData;
import org.jboss.metadata.javaee.spec.SecurityRolesMetaData;
import org.jboss.metadata.merge.javaee.spec.SecurityRolesMetaDataMerger;
import org.jboss.metadata.web.jboss.JBossServletsMetaData;
import org.jboss.metadata.web.jboss.JBossWebMetaData;
import org.jboss.metadata.web.spec.LoginConfigMetaData;
import org.jboss.metadata.web.spec.SecurityConstraintMetaData;
import org.jboss.metadata.web.spec.ServletMappingMetaData;
import org.jboss.metadata.web.spec.WebResourceCollectionsMetaData;
import org.jboss.ws.common.integration.WSHelper;
import org.jboss.wsf.spi.deployment.Deployment;
import org.jboss.wsf.spi.deployment.Endpoint;
import org.jboss.wsf.spi.deployment.HttpEndpoint;

/**
 * @author Richard Opalka
 */
final class WebMetaDataCreator {

    private static final String EJB_WEBSERVICE_REALM = "EJBWebServiceEndpointServlet Realm";

    private final SecurityMetaDataAccessorEJB ejb3SecurityAccessor = new SecurityMetaDataAccessorEJB3();

    WebMetaDataCreator() {
        super();
    }

    /**
     * Creates web meta data for EJB deployments.
     *
     * @param dep webservice deployment
     */
    void create(final Deployment dep) {
        final DeploymentUnit unit = WSHelper.getRequiredAttachment(dep, DeploymentUnit.class);
        WarMetaData warMD = ASHelper.getOptionalAttachment(unit, WarMetaData.ATTACHMENT_KEY);
        JBossWebMetaData jbossWebMD = warMD != null ? warMD.getMergedJBossWebMetaData() : null;

        if (warMD == null) {
            warMD = new WarMetaData();
        }
        if (jbossWebMD == null) {
            jbossWebMD = new JBossWebMetaData();
            warMD.setMergedJBossWebMetaData(jbossWebMD);
            unit.putAttachment(WarMetaData.ATTACHMENT_KEY, warMD);
        }

        createWebAppDescriptor(dep, jbossWebMD);
        createJBossWebAppDescriptor(dep, jbossWebMD);

        dep.addAttachment(JBossWebMetaData.class, jbossWebMD);
    }

    /**
     * Creates web.xml descriptor meta data.
     *
     * @param dep        webservice deployment
     * @param jbossWebMD jboss web meta data
     */
    private void createWebAppDescriptor(final Deployment dep, final JBossWebMetaData jbossWebMD) {
        WSLogger.ROOT_LOGGER.trace("Creating web.xml descriptor");
        createServlets(dep, jbossWebMD);
        createServletMappings(dep, jbossWebMD);
        createSecurityConstraints(dep, jbossWebMD);
        createLoginConfig(dep, jbossWebMD);
        createSecurityRoles(dep, jbossWebMD);
    }

    /**
     * Creates jboss-web.xml descriptor meta data.
     *

     *

     * <jboss-web>
     *   <security-domain>java:/jaas/custom-security-domain</security-domain>
     *   <context-root>/custom-context-root</context-root>
     *   <virtual-host>host1</virtual-host>
     *   ...
     *   <virtual-host>hostN</virtual-host>
     * </jboss-web>
     *

     *
     * @param dep        webservice deployment
     * @param jbossWebMD jboss web meta data
     */
    private void createJBossWebAppDescriptor(final Deployment dep, final JBossWebMetaData jbossWebMD) {
         WSLogger.ROOT_LOGGER.trace("Creating jboss-web.xml descriptor");

        // Set security domain
        final String securityDomain = ejb3SecurityAccessor.getSecurityDomain(dep);
        final boolean hasSecurityDomain = securityDomain != null;

        if (hasSecurityDomain) {
             WSLogger.ROOT_LOGGER.tracef("Setting security domain: %s", securityDomain);
            jbossWebMD.setSecurityDomain(securityDomain);
        }

        // Set virtual host
        final String virtualHost = dep.getService().getVirtualHost();
        ServerHostInfo serverHostInfo = new ServerHostInfo(virtualHost);
        if (serverHostInfo.getHost() != null) {
            WSLogger.ROOT_LOGGER.tracef("Setting virtual host: %s", serverHostInfo.getHost());
            jbossWebMD.setVirtualHosts(Arrays.asList(serverHostInfo.getHost()));
            if (serverHostInfo.getServerInstanceName() != null) {
                jbossWebMD.setServerInstanceName(serverHostInfo.getServerInstanceName());
            }
        }
    }

    /**
     * Creates servlets part of web.xml descriptor.
     *

     *

     * <servlet>
     *   <servlet-name>EJBEndpointShortName</servlet-name>
     *   <servlet-class>EJBEndpointTargetBeanName</servlet-class>
     * </servlet>
     *

     *
     * @param dep        webservice deployment
     * @param jbossWebMD jboss web meta data
     */
    private void createServlets(final Deployment dep, final JBossWebMetaData jbossWebMD) {
         WSLogger.ROOT_LOGGER.trace("Creating servlets");
        final JBossServletsMetaData servlets = WebMetaDataHelper.getServlets(jbossWebMD);

        for (final Endpoint endpoint : dep.getService().getEndpoints()) {
            final String endpointName = endpoint.getShortName();
            final String endpointClassName = endpoint.getTargetBeanName();

             WSLogger.ROOT_LOGGER.tracef("Servlet name: %s, class: %s", endpointName, endpointClassName);
            WebMetaDataHelper.newServlet(endpointName, endpointClassName, servlets);
        }
    }

    /**
     * Creates servlet-mapping part of web.xml descriptor.
     *

     *

     * <servlet-mapping>
     *   <servlet-name>EJBEndpointShortName</servlet-name>
     *   <url-pattern>EJBEndpointURLPattern</url-pattern>
     * </servlet-mapping>
     *

     *
     * @param dep        webservice deployment
     * @param jbossWebMD jboss web meta data
     */
    private void createServletMappings(final Deployment dep, final JBossWebMetaData jbossWebMD) {
         WSLogger.ROOT_LOGGER.trace("Creating servlet mappings");
        final List<ServletMappingMetaData> servletMappings = WebMetaDataHelper.getServletMappings(jbossWebMD);

        for (final Endpoint ep : dep.getService().getEndpoints()) {
            if (ep instanceof HttpEndpoint) {
                final String endpointName = ep.getShortName();
                final List<String> urlPatterns = WebMetaDataHelper.getUrlPatterns(((HttpEndpoint) ep).getURLPattern());

                 WSLogger.ROOT_LOGGER.tracef("Servlet name: %s, URL patterns: %s", endpointName, urlPatterns);
                WebMetaDataHelper.newServletMapping(endpointName, urlPatterns, servletMappings);
            }
        }
    }

    /**
     * Creates security constraints part of web.xml descriptor.
     *

     *

     * <security-constraint>
     *   <web-resource-collection>
     *     <web-resource-name>EJBEndpointShortName</web-resource-name>
     *     <url-pattern>EJBEndpointURLPattern</url-pattern>
     *     <http-method>GET</http-method>
     *     <http-method>POST</http-method>
     *   </web-resource-collection>
     *   <auth-constraint>
     *     <role-name>*</role-name>
     *   </auth-constraint>
     *   <user-data-constraint>
     *     <transport-guarantee>EjbTransportGuarantee</transport-guarantee>
     *   </user-data-constraint>
     * </security-constraint>
     *

     *
     * @param dep        webservice deployment
     * @param jbossWebMD jboss web meta data
     */
    private void createSecurityConstraints(final Deployment dep, final JBossWebMetaData jbossWebMD) {
         WSLogger.ROOT_LOGGER.trace("Creating security constraints");
        for (final Endpoint ejbEndpoint : dep.getService().getEndpoints()) {
            final boolean secureWsdlAccess = ejb3SecurityAccessor.isSecureWsdlAccess(ejbEndpoint);
            final String transportGuarantee = ejb3SecurityAccessor.getTransportGuarantee(ejbEndpoint);
            final boolean hasTransportGuarantee = transportGuarantee != null;
            final String authMethod = ejb3SecurityAccessor.getAuthMethod(ejbEndpoint);
            final boolean hasAuthMethod = authMethod != null;

            if (ejbEndpoint instanceof HttpEndpoint && (hasAuthMethod || hasTransportGuarantee)) {
                final List<SecurityConstraintMetaData> securityConstraints = WebMetaDataHelper
                        .getSecurityConstraints(jbossWebMD);

                // security-constraint
                final SecurityConstraintMetaData securityConstraint = WebMetaDataHelper
                        .newSecurityConstraint(securityConstraints);

                // web-resource-collection
                final WebResourceCollectionsMetaData webResourceCollections = WebMetaDataHelper
                        .getWebResourceCollections(securityConstraint);
                final String endpointName = ejbEndpoint.getShortName();
                final String urlPattern = ((HttpEndpoint) ejbEndpoint).getURLPattern();
                 WSLogger.ROOT_LOGGER.tracef("Creating web resource collection for endpoint: %s, URL pattern: %s", endpointName, urlPattern);
                WebMetaDataHelper.newWebResourceCollection(endpointName, urlPattern, secureWsdlAccess,
                        webResourceCollections);

                // auth-constraint
                if (hasAuthMethod) {
                     WSLogger.ROOT_LOGGER.tracef("Creating auth constraint for endpoint: %s", endpointName);
                    WebMetaDataHelper.newAuthConstraint(WebMetaDataHelper.getAllRoles(), securityConstraint);
                }

                // user-data-constraint
                if (hasTransportGuarantee) {
                     WSLogger.ROOT_LOGGER.tracef("Creating new user data constraint for endpoint: %s, transport guarantee: %s", endpointName, transportGuarantee);
                    WebMetaDataHelper.newUserDataConstraint(transportGuarantee, securityConstraint);
                }
            }
        }
    }

    /**
     * Creates login-config part of web.xml descriptor.
     *

     *

     * <login-config>
     *   <auth-method>EjbDeploymentAuthMethod</auth-method>
     *   <realm-name>EJBWebServiceEndpointServlet Realm</realm-name>
     * </login-config>
     *

     *
     * @param dep        webservice deployment
     * @param jbossWebMD jboss web meta data
     */
    private void createLoginConfig(final Deployment dep, final JBossWebMetaData jbossWebMD) {
        final String authMethod = getAuthMethod(dep);
        final boolean hasAuthMethod = authMethod != null;
        final String realmName = getRealmName(dep);

        if (hasAuthMethod) {
             WSLogger.ROOT_LOGGER.tracef("Creating new login config: %s, auth method: %s", EJB_WEBSERVICE_REALM, authMethod);
            final LoginConfigMetaData loginConfig = WebMetaDataHelper.getLoginConfig(jbossWebMD);
            if (realmName != null) {
                loginConfig.setRealmName(realmName);
            } else {
                loginConfig.setRealmName(WebMetaDataCreator.EJB_WEBSERVICE_REALM);
            }
            loginConfig.setAuthMethod(authMethod);
        }
    }

    /**
     * Creates security roles part of web.xml descriptor.
     *

     *

     * <security-role>
     *   <role-name>role1</role-name>
     *   ...
     *   <role-name>roleN</role-name>
     * </security-role>
     *

     *
     * @param dep        webservice deployment
     * @param jbossWebMD jboss web meta data
     */
    private void createSecurityRoles(final Deployment dep, final JBossWebMetaData jbossWebMD) {
        final String authMethod = getAuthMethod(dep);
        final boolean hasAuthMethod = authMethod != null;

        if (hasAuthMethod) {
            final SecurityRolesMetaData securityRolesMD = ejb3SecurityAccessor.getSecurityRoles(dep);
            final boolean hasSecurityRolesMD = securityRolesMD != null && !securityRolesMD.isEmpty();

            if (hasSecurityRolesMD) {
                 WSLogger.ROOT_LOGGER.trace("Setting security roles");
                jbossWebMD.setSecurityRoles(securityRolesMD);
            }
        }

        //merge security roles from the ear
        //TODO: is there somewhere better to put this?
        final DeploymentUnit unit = dep.getAttachment(DeploymentUnit.class);
        DeploymentUnit parent = unit.getParent();
        if (parent != null) {
            final EarMetaData earMetaData = parent.getAttachment(org.jboss.as.ee.structure.Attachments.EAR_METADATA);
            if (earMetaData != null) {
                if (jbossWebMD.getSecurityRoles() == null) {
                    jbossWebMD.setSecurityRoles(new SecurityRolesMetaData());
                }

                SecurityRolesMetaData earSecurityRolesMetaData = earMetaData.getSecurityRoles();
                if (earSecurityRolesMetaData != null) {
                    SecurityRolesMetaDataMerger.merge(jbossWebMD.getSecurityRoles(), jbossWebMD.getSecurityRoles(), earSecurityRolesMetaData);
                }
            }
        }
    }

    /**
     * Returns deployment authentication method.
     *
     * @param dep webservice deployment
     * @return deployment authentication method
     */
    private String getAuthMethod(final Deployment dep) {
        for (final Endpoint ejbEndpoint : dep.getService().getEndpoints()) {
            final String beanAuthMethod = ejb3SecurityAccessor.getAuthMethod(ejbEndpoint);
            final boolean hasBeanAuthMethod = beanAuthMethod != null;

            if (hasBeanAuthMethod) {
                // First found auth-method defines war
                // login-config/auth-method
                return beanAuthMethod;
            }
        }

        return null;
    }

    private String getRealmName(final Deployment dep) {
        for (final Endpoint ejbEndpoint : dep.getService().getEndpoints()) {
            final String realmName = ejb3SecurityAccessor.getRealmName(ejbEndpoint);
            final boolean hasRealmName = realmName != null;
            if (hasRealmName) {
                return realmName;
            }
        }
        return null;
    }

}


/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2010, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.as.service;

import java.io.InputStream;
import java.util.Locale;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;

import org.jboss.as.ee.structure.JBossDescriptorPropertyReplacement;
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.service.descriptor.JBossServiceXmlDescriptor;
import org.jboss.as.service.descriptor.JBossServiceXmlDescriptorParser;
import org.jboss.as.service.descriptor.ParseResult;
import org.jboss.as.service.logging.SarLogger;
import org.jboss.staxmapper.XMLMapper;
import org.jboss.vfs.VFSUtils;
import org.jboss.vfs.VirtualFile;

/**
 * DeploymentUnitProcessor responsible for parsing a jboss-service.xml descriptor and attaching the corresponding JBossServiceXmlDescriptor.
 *
 * @author John E. Bailey
 */
public class ServiceDeploymentParsingProcessor implements DeploymentUnitProcessor {
    static final String SERVICE_DESCRIPTOR_PATH = "META-INF/jboss-service.xml";
    static final String SERVICE_DESCRIPTOR_SUFFIX = "-service.xml";
    private final XMLInputFactory inputFactory = XMLInputFactory.newInstance();

    /**
     * Construct a new instance.
     */
    public ServiceDeploymentParsingProcessor() {
    }

    /**
     * Process a deployment for jboss-service.xml files. Will parse the xml file and attach a configuration discovered
     * during processing.
     *
     * @param phaseContext the deployment unit context
     * @throws DeploymentUnitProcessingException
     */
    public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {

        final VirtualFile deploymentRoot = phaseContext.getDeploymentUnit().getAttachment(Attachments.DEPLOYMENT_ROOT).getRoot();

        if(deploymentRoot == null || !deploymentRoot.exists())
            return;

        VirtualFile serviceXmlFile = null;
        if(deploymentRoot.isDirectory()) {
            serviceXmlFile = deploymentRoot.getChild(SERVICE_DESCRIPTOR_PATH);
        } else if(deploymentRoot.getName().toLowerCase(Locale.ENGLISH).endsWith(SERVICE_DESCRIPTOR_SUFFIX)) {
            serviceXmlFile = deploymentRoot;
        }
        if(serviceXmlFile == null || !serviceXmlFile.exists())
            return;

        final XMLMapper xmlMapper = XMLMapper.Factory.create();
        final JBossServiceXmlDescriptorParser jBossServiceXmlDescriptorParser = new JBossServiceXmlDescriptorParser(JBossDescriptorPropertyReplacement.propertyReplacer(phaseContext.getDeploymentUnit()));
        xmlMapper.registerRootElement(new QName("urn:jboss:service:7.0", "server"), jBossServiceXmlDescriptorParser);
        xmlMapper.registerRootElement(new QName(null, "server"), jBossServiceXmlDescriptorParser);

        InputStream xmlStream = null;
        try {
            xmlStream = serviceXmlFile.openStream();
            final XMLStreamReader reader = inputFactory.createXMLStreamReader(xmlStream);
            final ParseResult<JBossServiceXmlDescriptor> result = new ParseResult<JBossServiceXmlDescriptor>();
            xmlMapper.parseDocument(result, reader);
            final JBossServiceXmlDescriptor xmlDescriptor = result.getResult();
            if(xmlDescriptor != null)
                phaseContext.getDeploymentUnit().putAttachment(JBossServiceXmlDescriptor.ATTACHMENT_KEY, xmlDescriptor);
            else
                throw SarLogger.ROOT_LOGGER.failedXmlParsing(serviceXmlFile);
        } catch(Exception e) {
            throw SarLogger.ROOT_LOGGER.failedXmlParsing(e, serviceXmlFile);
        } finally {
            VFSUtils.safeClose(xmlStream);
        }
    }

    public void undeploy(final 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.ejb3.deployment.processors.dd;

import java.lang.reflect.Method;

import javax.interceptor.InvocationContext;

import org.jboss.as.ee.component.ComponentDescription;
import org.jboss.as.ee.component.EEModuleDescription;
import org.jboss.as.ee.component.interceptors.InterceptorClassDescription;
import org.jboss.as.ee.utils.ClassLoadingUtils;
import org.jboss.as.ejb3.logging.EjbLogger;
import org.jboss.as.ejb3.component.EJBComponentDescription;
import org.jboss.as.ejb3.component.messagedriven.MessageDrivenComponentDescription;
import org.jboss.as.ejb3.component.session.SessionBeanComponentDescription;
import org.jboss.as.ejb3.component.stateless.StatelessComponentDescription;
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.server.deployment.reflect.ClassReflectionIndexUtil;
import org.jboss.as.server.deployment.reflect.DeploymentReflectionIndex;
import org.jboss.invocation.proxy.MethodIdentifier;
import org.jboss.metadata.ejb.spec.AroundInvokeMetaData;
import org.jboss.metadata.ejb.spec.AroundInvokesMetaData;
import org.jboss.metadata.ejb.spec.EnterpriseBeanMetaData;
import org.jboss.metadata.ejb.spec.MessageDrivenBeanMetaData;
import org.jboss.metadata.ejb.spec.SessionBeanMetaData;
import org.jboss.metadata.javaee.spec.LifecycleCallbackMetaData;
import org.jboss.metadata.javaee.spec.LifecycleCallbacksMetaData;
import org.jboss.modules.Module;

/**
 * Deployment descriptor that resolves interceptor methods defined in ejb-jar.xml that could not be resolved at
 * DD parse time.
 *
 * @author Stuart Douglas
 */
public class DeploymentDescriptorMethodProcessor implements DeploymentUnitProcessor {
    @Override
    public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {

        final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
        final EEModuleDescription eeModuleDescription = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
        final DeploymentReflectionIndex reflectionIndex = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.REFLECTION_INDEX);
        final Module module = deploymentUnit.getAttachment(Attachments.MODULE);

        if (eeModuleDescription != null) {
            for (final ComponentDescription component : eeModuleDescription.getComponentDescriptions()) {
                if (component instanceof EJBComponentDescription) {
                    try {
                        if (component instanceof SessionBeanComponentDescription || component instanceof MessageDrivenComponentDescription)
                            handleSessionBean((EJBComponentDescription) component, module, reflectionIndex);
                        if (component instanceof StatelessComponentDescription || component instanceof MessageDrivenComponentDescription) {
                            handleStatelessSessionBean((EJBComponentDescription) component, module, reflectionIndex);
                        }
                    } catch (ClassNotFoundException e) {
                        throw EjbLogger.ROOT_LOGGER.failToLoadComponentClass(e, component.getComponentName());
                    }
                }
            }
        }

    }

    /**
     * Handles setting up the ejbCreate and ejbRemove methods  for stateless session beans and MDB's
     *
     * @param component       The component
     * @param module      The module
     * @param reflectionIndex The reflection index
     */
    private void handleStatelessSessionBean(final EJBComponentDescription component, final Module module, final DeploymentReflectionIndex reflectionIndex) throws ClassNotFoundException, DeploymentUnitProcessingException {

        final Class<?> componentClass = ClassLoadingUtils.loadClass(component.getComponentClassName(), module);
        final MethodIdentifier ejbCreateId = MethodIdentifier.getIdentifier(void.class, "ejbCreate");
        final Method ejbCreate = ClassReflectionIndexUtil.findMethod(reflectionIndex, componentClass, ejbCreateId);
        if (ejbCreate != null) {
            final InterceptorClassDescription.Builder builder = InterceptorClassDescription.builder();
            builder.setPostConstruct(ejbCreateId);
            component.addInterceptorMethodOverride(ejbCreate.getDeclaringClass().getName(), builder.build());
        }
        final MethodIdentifier ejbRemoveId = MethodIdentifier.getIdentifier(void.class, "ejbRemove");
        final Method ejbRemove = ClassReflectionIndexUtil.findMethod(reflectionIndex, componentClass, ejbRemoveId);
        if (ejbRemove != null) {
            final InterceptorClassDescription.Builder builder = InterceptorClassDescription.builder();
            builder.setPreDestroy(ejbRemoveId);
            component.addInterceptorMethodOverride(ejbRemove.getDeclaringClass().getName(), builder.build());
        }
    }

    private void handleSessionBean(final EJBComponentDescription component, final Module module, final DeploymentReflectionIndex reflectionIndex) throws ClassNotFoundException, DeploymentUnitProcessingException {

        if (component.getDescriptorData() == null) {
            return;
        }
        final Class<?> componentClass = ClassLoadingUtils.loadClass(component.getComponentClassName(), module);

        final EnterpriseBeanMetaData metaData = component.getDescriptorData();

        AroundInvokesMetaData aroundInvokes = null;
        if (metaData instanceof SessionBeanMetaData) {
            aroundInvokes = ((SessionBeanMetaData) metaData).getAroundInvokes();
        } else if (metaData instanceof MessageDrivenBeanMetaData) {
            aroundInvokes = ((MessageDrivenBeanMetaData) metaData).getAroundInvokes();
        }

        if (aroundInvokes != null) {
            for (AroundInvokeMetaData aroundInvoke : aroundInvokes) {
                final InterceptorClassDescription.Builder builder = InterceptorClassDescription.builder();
                String methodName = aroundInvoke.getMethodName();
                MethodIdentifier methodIdentifier = MethodIdentifier.getIdentifier(Object.class, methodName, InvocationContext.class);
                builder.setAroundInvoke(methodIdentifier);
                if (aroundInvoke.getClassName() == null || aroundInvoke.getClassName().isEmpty()) {
                    final String className = ClassReflectionIndexUtil.findRequiredMethod(reflectionIndex, componentClass, methodIdentifier).getDeclaringClass().getName();
                    component.addInterceptorMethodOverride(className, builder.build());
                } else {
                    component.addInterceptorMethodOverride(aroundInvoke.getClassName(), builder.build());
                }
            }
        }

        // post-construct(s) of the interceptor configured (if any) in the deployment descriptor
        LifecycleCallbacksMetaData postConstructs = metaData.getPostConstructs();
        if (postConstructs != null) {
            for (LifecycleCallbackMetaData postConstruct : postConstructs) {
                final InterceptorClassDescription.Builder builder = InterceptorClassDescription.builder();
                String methodName = postConstruct.getMethodName();
                MethodIdentifier methodIdentifier = MethodIdentifier.getIdentifier(void.class, methodName);
                builder.setPostConstruct(methodIdentifier);
                if (postConstruct.getClassName() == null || postConstruct.getClassName().isEmpty()) {
                    final String className = ClassReflectionIndexUtil.findRequiredMethod(reflectionIndex, componentClass, methodIdentifier).getDeclaringClass().getName();
                    component.addInterceptorMethodOverride(className, builder.build());
                } else {
                    component.addInterceptorMethodOverride(postConstruct.getClassName(), builder.build());
                }
            }
        }

        // pre-destroy(s) of the interceptor configured (if any) in the deployment descriptor
        final LifecycleCallbacksMetaData preDestroys = metaData.getPreDestroys();
        if (preDestroys != null) {
            for (final LifecycleCallbackMetaData preDestroy : preDestroys) {
                final InterceptorClassDescription.Builder builder = InterceptorClassDescription.builder();
                final String methodName = preDestroy.getMethodName();
                final MethodIdentifier methodIdentifier = MethodIdentifier.getIdentifier(void.class, methodName);
                builder.setPreDestroy(methodIdentifier);
                if (preDestroy.getClassName() == null || preDestroy.getClassName().isEmpty()) {
                    final String className = ClassReflectionIndexUtil.findRequiredMethod(reflectionIndex, componentClass, methodIdentifier).getDeclaringClass().getName();
                    component.addInterceptorMethodOverride(className, builder.build());
                } else {
                    component.addInterceptorMethodOverride(preDestroy.getClassName(), builder.build());
                }
            }
        }

        if (component.isStateful()) {

            final SessionBeanMetaData sessionBeanMetadata = (SessionBeanMetaData) metaData;
            // pre-passivate(s) of the interceptor configured (if any) in the deployment descriptor
            final LifecycleCallbacksMetaData prePassivates = sessionBeanMetadata.getPrePassivates();
            if (prePassivates != null) {
                for (final LifecycleCallbackMetaData prePassivate : prePassivates) {
                    final InterceptorClassDescription.Builder builder = InterceptorClassDescription.builder();
                    final String methodName = prePassivate.getMethodName();
                    final MethodIdentifier methodIdentifier = MethodIdentifier.getIdentifier(void.class, methodName);
                    builder.setPrePassivate(methodIdentifier);
                    if (prePassivate.getClassName() == null || prePassivate.getClassName().isEmpty()) {
                        final String className = ClassReflectionIndexUtil.findRequiredMethod(reflectionIndex, componentClass, methodIdentifier).getDeclaringClass().getName();
                        component.addInterceptorMethodOverride(className, builder.build());
                    } else {
                        component.addInterceptorMethodOverride(prePassivate.getClassName(), builder.build());
                    }
                }
            }

            final LifecycleCallbacksMetaData postActivates = sessionBeanMetadata.getPostActivates();
            if (postActivates != null) {
                for (final LifecycleCallbackMetaData postActivate : postActivates) {
                    final InterceptorClassDescription.Builder builder = InterceptorClassDescription.builder();
                    final String methodName = postActivate.getMethodName();
                    final MethodIdentifier methodIdentifier = MethodIdentifier.getIdentifier(void.class, methodName);
                    builder.setPostActivate(methodIdentifier);
                    if (postActivate.getClassName() == null || postActivate.getClassName().isEmpty()) {
                        final String className = ClassReflectionIndexUtil.findRequiredMethod(reflectionIndex, componentClass, methodIdentifier).getDeclaringClass().getName();
                        component.addInterceptorMethodOverride(className, builder.build());
                    } else {
                        component.addInterceptorMethodOverride(postActivate.getClassName(), builder.build());
                    }
                }
            }
        }
    }

    @Override
    public void undeploy(final DeploymentUnit context) {
    }
}


/*
 * 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.ejb3.iiop.stub;

import org.jboss.as.ejb3.logging.EjbLogger;
import org.jboss.classfilewriter.ClassFile;
import com.sun.corba.se.impl.presentation.rmi.StubFactoryBase;
import com.sun.corba.se.impl.presentation.rmi.StubFactoryFactoryDynamicBase;
import com.sun.corba.se.spi.presentation.rmi.PresentationManager;
import org.wildfly.security.manager.WildFlySecurityManager;

/**
 * @author Stuart Douglas
 */
public class DynamicStubFactoryFactory extends StubFactoryFactoryDynamicBase {

    @Override
    public PresentationManager.StubFactory makeDynamicStubFactory(final PresentationManager pm, final PresentationManager.ClassData classData, final ClassLoader classLoader) {
        final Class<?> myClass = classData.getMyClass();
        Class<?> theClass = makeStubClass(myClass);
        return new StubFactory(classData, theClass);
    }

    /**
     * Makes a dynamic stub class, if it does not already exist.
     * @param myClass The class to create a stub for
     * @return The dynamic stub class
     */
    public static Class<?> makeStubClass(final Class<?> myClass) {
        final String stubClassName = myClass + "_Stub";
        ClassLoader cl = WildFlySecurityManager.getCurrentContextClassLoaderPrivileged();
        if (cl == null) {
            cl = myClass.getClassLoader();
        }
        if (cl == null) {
            throw EjbLogger.ROOT_LOGGER.couldNotFindClassLoaderForStub(stubClassName);
        }
        Class<?> theClass;
        try {
            theClass = cl.loadClass(stubClassName);
        } catch (ClassNotFoundException e) {
            try {
                final ClassFile clazz = IIOPStubCompiler.compile(myClass, stubClassName);
                theClass = clazz.define(cl, myClass.getProtectionDomain());
            } catch (Throwable ex) {
                //there is a possibility that another thread may have defined the same class in the meantime
                try {
                    theClass = cl.loadClass(stubClassName);
                } catch (ClassNotFoundException e1) {
                    EjbLogger.ROOT_LOGGER.dynamicStubCreationFailed(stubClassName, ex);
                    throw ex;
                }
            }
        }
        return theClass;
    }

    private static final class StubFactory extends StubFactoryBase {

        private final Class<?> clazz;

        protected StubFactory(PresentationManager.ClassData classData, final Class<?> clazz) {
            super(classData);

            this.clazz = clazz;
        }

        @Override
        public org.omg.CORBA.Object makeStub() {
            try {
                return (org.omg.CORBA.Object) clazz.newInstance();
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }
}


/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2008, Red Hat Middleware LLC, 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.wildfly.iiop.openjdk.rmi.ir;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.omg.CORBA.ArrayDef;
import org.omg.CORBA.Contained;
import org.omg.CORBA.ContainedHelper;
import org.omg.CORBA.DefinitionKind;
import org.omg.CORBA.FixedDef;
import org.omg.CORBA.IRObject;
import org.omg.CORBA.ORB;
import org.omg.CORBA.PrimitiveDef;
import org.omg.CORBA.Repository;
import org.omg.CORBA.RepositoryOperations;
import org.omg.CORBA.RepositoryPOATie;
import org.omg.CORBA.SequenceDef;
import org.omg.CORBA.StringDef;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.WstringDef;
import org.omg.PortableServer.POA;
import org.wildfly.iiop.openjdk.logging.IIOPLogger;

/**
 * An Interface Repository.
 *
 * @author Ole Husgaard
 */
class RepositoryImpl extends ContainerImpl implements RepositoryOperations, LocalContainer {

    public RepositoryImpl(ORB orb, POA poa, String name) {
        super(DefinitionKind.dk_Repository, null);

        this.orb = orb;
        this.poa = poa;
        oid = name.getBytes(StandardCharsets.UTF_8);
        oidPrefix = name + ":";
        anonOidPrefix = oidPrefix + "anon";

        repository = this;
    }

    public IRObject getReference() {
        if (ref == null) {
            ref = org.omg.CORBA.RepositoryHelper.narrow(
                    servantToReference(new RepositoryPOATie(this)));
        }
        return ref;
    }

    public void allDone()
            throws IRConstructionException {
        super.allDone();

        // call allDone() for all our sequences
        Iterator iter = sequenceMap.values().iterator();
        while (iter.hasNext())
            ((SequenceDefImpl) iter.next()).allDone();
    }

    public void shutdown() {
        // shutdown all anonymous IR objects in this IR
        for (long i = 1; i < nextPOAId; i++) {
            try {
                getPOA().deactivate_object(getAnonymousObjectId(i));
            } catch (org.omg.CORBA.UserException ex) {
                IIOPLogger.ROOT_LOGGER.warnCouldNotDeactivateAnonIRObject(ex);
            }
        }

        // shutdown this IR's top-level container
        super.shutdown();
    }

    // Repository implementation -------------------------------------

    public Contained lookup_id(java.lang.String search_id) {
        LocalContained c = _lookup_id(search_id);

        if (c == null)
            return null;

        return ContainedHelper.narrow(c.getReference());
    }

    public TypeCode get_canonical_typecode(org.omg.CORBA.TypeCode tc) {
        // TODO
        return null;
    }

    public PrimitiveDef get_primitive(org.omg.CORBA.PrimitiveKind kind) {
        // TODO
        return null;
    }

    public StringDef create_string(int bound) {
        throw IIOPLogger.ROOT_LOGGER.cannotChangeRMIIIOPMapping();
    }

    public WstringDef create_wstring(int bound) {
        throw IIOPLogger.ROOT_LOGGER.cannotChangeRMIIIOPMapping();
    }

    public SequenceDef create_sequence(int bound, org.omg.CORBA.IDLType element_type) {
        throw IIOPLogger.ROOT_LOGGER.cannotChangeRMIIIOPMapping();
    }

    public ArrayDef create_array(int length, org.omg.CORBA.IDLType element_type) {
        throw IIOPLogger.ROOT_LOGGER.cannotChangeRMIIIOPMapping();
    }

    public FixedDef create_fixed(short digits, short scale) {
        throw IIOPLogger.ROOT_LOGGER.cannotChangeRMIIIOPMapping();
    }

    // Y overrides ---------------------------------------------------

    // Package protected ---------------------------------------------

    /**
     * The ORB that I use.
     */
    ORB orb = null;

    /**
     * The POA that I use.
     */
    POA poa = null;

    /**
     * The POA object ID of this repository.
     */
    private byte[] oid = null;

    /**
     * Prefix for POA object IDs of IR objects in this repository.
     */
    private String oidPrefix = null;

    /**
     * Prefix for POA object IDs of "anonymous" IR objects in this repository.
     */
    private String anonOidPrefix = null;

    /**
     * Maps typecodes of sequences defined in this IR to the sequences.
     */
    Map sequenceMap = new HashMap();

    /**
     * Maps repository IDs of sequences defined in this IR to the sequences.
     */
    Map sequenceIdMap = new HashMap();

    LocalContained _lookup_id(java.lang.String search_id) {
        // mapping of arrays are special
        if (search_id.startsWith("RMI:["))
            return (ValueBoxDefImpl) sequenceIdMap.get(search_id);

        // convert id
        String name = scopedName(search_id);

        // look it up if converted id not null
        //return (name == null) ? null : _lookup(name);
        LocalContained ret = (name == null) ? null : _lookup(name);
        return ret;
    }

    SequenceDefImpl getSequenceImpl(TypeCode typeCode) {
        return (SequenceDefImpl) sequenceMap.get(typeCode);
    }

    void putSequenceImpl(String id, TypeCode typeCode, SequenceDefImpl sequence,
                         ValueBoxDefImpl valueBox) {
        sequenceIdMap.put(id, valueBox);
        sequenceMap.put(typeCode, sequence);
    }

    String getObjectIdPrefix() {
        return oidPrefix;
    }

    // Protected -----------------------------------------------------

    /**
     * Return the POA object ID of this IR object.
     */
    protected byte[] getObjectId() {
        return (byte[]) oid.clone();
    }

    /**
     * Generate the ID of the n-th "anonymous" object created in this IR.
     */
    protected byte[] getAnonymousObjectId(long n) {
        String s = anonOidPrefix + Long.toString(n);
        return s.getBytes(StandardCharsets.UTF_8);
    }

    /**
     * The next "anonymous" POA object ID.
     * While contained IR objects can generate a sensible ID from their
     * repository ID, non-contained objects use this method to get an
     * ID that is unique within the IR.
     */
    protected byte[] getNextObjectId() {
        return getAnonymousObjectId(nextPOAId++);
    }

    // Private -------------------------------------------------------

    /**
     * My CORBA reference.
     */
    private Repository ref = null;

    /**
     * The next "anonymous" POA object ID.
     */
    private long nextPOAId = 1;

    /**
     * Convert a repository ID to an IDL scoped name.
     * Returns null if the ID cannot be understood.
     */
    private String scopedName(String id) {
        if (id == null)
            return null;

        if (id.startsWith("IDL:")) {
            // OMG IDL format

            // Check for base types
            if ("IDL:omg.org/CORBA/Object:1.0".equals(id) ||
                    "IDL:omg.org/CORBA/ValueBase:1.0".equals(id))
                return null;

            // Get 2nd component of ID
            int idx2 = id.indexOf(':', 4); // 2nd colon
            if (idx2 == -1)
                return null; // invalid ID, version part missing
            String base = id.substring(4, id.indexOf(':', 4));

            // Check special prefixes
            if (base.startsWith("omg.org"))
                base = "org/omg" + base.substring(7);
            if (base.startsWith("w3c.org"))
                base = "org/w3c" + base.substring(7);

            // convert '/' to "::"
            StringBuffer b = new StringBuffer();
            for (int i = 0; i < base.length(); ++i) {
                char c = base.charAt(i);

                if (c != '/')
                    b.append(c);
                else
                    b.append("::");
            }

            return b.toString();
        } else if (id.startsWith("RMI:")) {
            // RMI hashed format

            // Get 2nd component of ID
            int idx2 = id.indexOf(':', 4); // 2nd colon
            if (idx2 == -1)
                return null; // invalid ID, version part missing
            String base = id.substring(4, id.indexOf(':', 4));

            // convert '.' to "::"
            StringBuffer b = new StringBuffer();
            for (int i = 0; i < base.length(); ++i) {
                char c = base.charAt(i);

                if (c != '.')
                    b.append(c);
                else
                    b.append("::");
            }

            return b.toString();
        } else
            return null;
    }

    // Inner classes -------------------------------------------------
}


/*
 * 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.clustering.controller.transform;

import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.transform.OperationResultTransformer;
import org.jboss.as.controller.transform.TransformationContext;
import org.jboss.dmr.ModelNode;

/**
 * @author Paul Ferraro
 */
public class SimpleOperationTransformer implements org.jboss.as.controller.transform.OperationTransformer {

    private final OperationTransformer operationTransformer;
    private final OperationResultTransformer resultTransformer;

    public SimpleOperationTransformer(OperationTransformer transformer) {
        this(transformer, OperationResultTransformer.ORIGINAL_RESULT);
    }

    public SimpleOperationTransformer(OperationTransformer operationTransformer, OperationResultTransformer resultTransformer) {
        this.operationTransformer = operationTransformer;
        this.resultTransformer = resultTransformer;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public TransformedOperation transformOperation(TransformationContext context, PathAddress address, ModelNode operation) {
        return new TransformedOperation(this.operationTransformer.transformOperation(operation), this.resultTransformer);
    }
}


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

import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.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.SubsystemRegistration;
import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver;
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
import org.jboss.as.controller.parsing.ExtensionParsingContext;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.weld.logging.WeldLogger;

/**
 * Domain extension used to initialize the weld subsystem.
 *
 * @author Stuart Douglas
 * @author Emanuel Muckenhuber
 * @author Jozef Hartinger
 */
public class WeldExtension implements Extension {

    public static final String SUBSYSTEM_NAME = "weld";

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

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

    private static final ModelVersion CURRENT_MODEL_VERSION = ModelVersion.create(4, 0, 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, WeldExtension.class.getClassLoader(), true, false);
    }

    /** {@inheritDoc} */
    @Override
    public void initialize(final ExtensionContext context) {
        WeldLogger.ROOT_LOGGER.debug("Activating Weld Extension");
        final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, CURRENT_MODEL_VERSION);
        final ManagementResourceRegistration registration = subsystem.registerSubsystemModel(WeldResourceDefinition.INSTANCE);
        registration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
        subsystem.registerXMLElementWriter(WeldSubsystem40Parser.INSTANCE);

    }

    /** {@inheritDoc} */
    @Override
    public void initializeParsers(final ExtensionParsingContext context) {
        context.setSubsystemXmlMapping(SUBSYSTEM_NAME, WeldSubsystem10Parser.NAMESPACE, () -> WeldSubsystem10Parser.INSTANCE);
        context.setSubsystemXmlMapping(SUBSYSTEM_NAME, WeldSubsystem20Parser.NAMESPACE, () -> WeldSubsystem20Parser.INSTANCE);
        context.setSubsystemXmlMapping(SUBSYSTEM_NAME, WeldSubsystem30Parser.NAMESPACE, () -> WeldSubsystem30Parser.INSTANCE);
        context.setSubsystemXmlMapping(SUBSYSTEM_NAME, WeldSubsystem40Parser.NAMESPACE, () -> WeldSubsystem40Parser.INSTANCE);
    }

}


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

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.jboss.as.naming.ManagedReference;
import org.jboss.as.server.deployment.SetupAction;
import org.jboss.as.service.component.ServiceComponentInstantiator;
import org.jboss.as.service.logging.SarLogger;
import org.jboss.msc.service.StartContext;
import org.jboss.msc.service.StartException;
import org.jboss.msc.service.StopContext;

/**
 * Service wrapper for legacy JBoss services that controls the service create and destroy lifecycle.
 *
 * @author John E. Bailey
 * @author Richard Opalka
 * @author Eduardo Martins
 */
final class CreateDestroyService extends AbstractService {

    private final Method createMethod;
    private final Method destroyMethod;

    private final ServiceComponentInstantiator componentInstantiator;
    private final Map<Method, Supplier<Object>> injections = new HashMap<>();
    private ManagedReference managedReference;

    CreateDestroyService(final Object mBeanInstance, final Method createMethod, final Method destroyMethod, ServiceComponentInstantiator componentInstantiator,
                         List<SetupAction> setupActions, final ClassLoader mbeanContextClassLoader, final Consumer<Object> mBeanInstanceConsumer, final Supplier<ExecutorService> executorSupplier) {
        super(mBeanInstance, setupActions, mbeanContextClassLoader, mBeanInstanceConsumer, executorSupplier);
        this.createMethod = createMethod;
        this.destroyMethod = destroyMethod;
        this.componentInstantiator = componentInstantiator;
    }

    /** {@inheritDoc} */
    public void start(final StartContext context) {
        super.start(context);
        if (SarLogger.ROOT_LOGGER.isTraceEnabled()) {
            SarLogger.ROOT_LOGGER.tracef("Creating Service: %s", context.getController().getName());
        }
        final Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    injectDependencies();
                    invokeLifecycleMethod(createMethod, context);
                    if (componentInstantiator != null) {
                        managedReference = componentInstantiator.initializeInstance(mBeanInstance);
                    }
                    context.complete();
                } catch (Throwable e) {
                    uninjectDependencies();
                    context.failed(new StartException(SarLogger.ROOT_LOGGER.failedExecutingLegacyMethod("create()"), e));
                }
            }
        };
        try {
            executorSupplier.get().submit(task);
        } catch (RejectedExecutionException e) {
            task.run();
        } finally {
            context.asynchronous();
        }
    }

    /** {@inheritDoc} */
    public void stop(final StopContext context) {
        super.stop(context);
        if (SarLogger.ROOT_LOGGER.isTraceEnabled()) {
            SarLogger.ROOT_LOGGER.tracef("Destroying Service: %s", context.getController().getName());
        }
        final Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    if(managedReference != null) {
                        managedReference.release();
                    }
                    invokeLifecycleMethod(destroyMethod, context);
                } catch (Exception e) {
                    SarLogger.ROOT_LOGGER.error(SarLogger.ROOT_LOGGER.failedExecutingLegacyMethod("destroy()"), e);
                } finally {
                    uninjectDependencies();
                    context.complete();
                }
            }
        };
        try {
            executorSupplier.get().submit(task);
        } catch (RejectedExecutionException e) {
            task.run();
        } finally {
            context.asynchronous();
        }
    }

    void inject(final Method setter, final Supplier<Object> injectionSupplier) {
        injections.put(setter, injectionSupplier);
    }

    private void injectDependencies() throws IllegalAccessException, InvocationTargetException {
        Method setter;
        Object arg;
        for (final Entry<Method, Supplier<Object>> injection : injections.entrySet()) {
            setter = injection.getKey();
            arg = injection.getValue().get();
            setter.invoke(mBeanInstance, arg);
        }
    }

    private void uninjectDependencies() {
        Method setter;
        for (final Entry<Method, Supplier<Object>> injection : injections.entrySet()) {
            try {
                setter = injection.getKey();
                setter.invoke(mBeanInstance, (Object[]) null);
            } catch (final Throwable ignored) {}
        }
    }

}


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

import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.RestartParentWriteAttributeHandler;
import org.jboss.as.controller.registry.Resource;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.service.ServiceName;

/**
 * @author Jason T. Greene
 */
public class SecurityDomainReloadWriteHandler extends RestartParentWriteAttributeHandler {

    protected SecurityDomainReloadWriteHandler(final AttributeDefinition ... definition) {
        super(Constants.SECURITY_DOMAIN, definition);
    }

    @Override
    protected void recreateParentService(OperationContext context, PathAddress parentAddress, ModelNode parentModel) throws OperationFailedException {
        String domainName = parentAddress.getLastElement().getValue();
        SecurityDomainAdd.INSTANCE.launchServices(context, domainName, parentModel);
    }

    @Override
    protected ServiceName getParentServiceName(PathAddress parentAddress) {
        return SecurityDomainResourceDefinition.getSecurityDomainServiceName(parentAddress);
    }

    // TODO: Remove this method once WFCORE-3055 and WFCORE-3056 are fixed
    @Override
    protected void validateUpdatedModel(OperationContext context, Resource model) throws OperationFailedException {
        SecurityDomainResourceDefinition.CACHE_TYPE.validateOperation(model.getModel());
    }
}


/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2017, 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.wildfly.extension.undertow;

import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.operations.validation.ModelTypeValidator;
import org.jboss.dmr.ModelNode;
import org.jboss.dmr.ModelType;
import org.wildfly.extension.undertow.logging.UndertowLogger;
import io.undertow.predicate.PredicateParser;

/**
 * @author Stuart Douglas
 */
public class PredicateValidator extends ModelTypeValidator {

    public static final PredicateValidator INSTANCE = new PredicateValidator();

    private PredicateValidator() {
        super(ModelType.STRING, true, true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void validateParameter(String parameterName, ModelNode value) throws OperationFailedException {
        super.validateParameter(parameterName, value);
        if (value.isDefined() && value.getType() != ModelType.EXPRESSION) {
            String val = value.asString();
            try {
                PredicateParser.parse(val, getClass().getClassLoader());
            } catch (Exception e) {
                throw new OperationFailedException(UndertowLogger.ROOT_LOGGER.predicateNotValid(val, e.getMessage()), e);
            }
        }
    }
}


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

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceProviderResolver;

import org.jboss.as.jpa.messages.JpaLogger;
import org.jboss.modules.ModuleClassLoader;
import org.wildfly.security.manager.WildFlySecurityManager;

/**
 * Implementation of PersistenceProviderResolver
 *
 * @author Scott Marlow
 */
public class PersistenceProviderResolverImpl implements PersistenceProviderResolver {

    private Map<ClassLoader, List<Class<? extends PersistenceProvider>>> persistenceProviderPerClassLoader = new HashMap<>();

    private List<Class<? extends PersistenceProvider>> providers = new CopyOnWriteArrayList<>();

    private static final PersistenceProviderResolverImpl INSTANCE = new PersistenceProviderResolverImpl();

    public static PersistenceProviderResolverImpl getInstance() {
        return INSTANCE;
    }

    public PersistenceProviderResolverImpl() {
    }

    /**
     * Return a new instance of each persistence provider class
     *
     * @return
     */
    @Override
    public List<PersistenceProvider> getPersistenceProviders() {
        List<PersistenceProvider> providersCopy = new ArrayList<>(providers.size());

        /**
         * Add the application specified providers first so they are found before the global providers
         */
        synchronized(persistenceProviderPerClassLoader) {
            if (persistenceProviderPerClassLoader.size() > 0) {
                // get the deployment or subdeployment classloader
                ClassLoader deploymentClassLoader = findParentModuleCl(WildFlySecurityManager.getCurrentContextClassLoaderPrivileged());
                ROOT_LOGGER.tracef("get application level Persistence Provider for classloader %s" , deploymentClassLoader);
                // collect persistence providers associated with deployment/each sub-deployment
                List<Class<? extends PersistenceProvider>> deploymentSpecificPersistenceProviders = persistenceProviderPerClassLoader.get(deploymentClassLoader);
                ROOT_LOGGER.tracef("got application level Persistence Provider list %s" , deploymentSpecificPersistenceProviders);
                if (deploymentSpecificPersistenceProviders != null) {

                    for (Class<? extends PersistenceProvider> providerClass : deploymentSpecificPersistenceProviders) {
                        try {
                            ROOT_LOGGER.tracef("application has its own Persistence Provider %s", providerClass.getName());
                            providersCopy.add(providerClass.newInstance());
                        } catch (InstantiationException e) {
                            throw JpaLogger.ROOT_LOGGER.couldNotCreateInstanceProvider(e, providerClass.getName());
                        } catch (IllegalAccessException e) {
                            throw JpaLogger.ROOT_LOGGER.couldNotCreateInstanceProvider(e, providerClass.getName());
                        }
                    }
                }
            }
        }

        // add global persistence providers last (so application packaged providers have priority)
        for (Class<?> providerClass : providers) {
            try {
                providersCopy.add((PersistenceProvider) providerClass.newInstance());
                ROOT_LOGGER.tracef("returning global (module) Persistence Provider %s", providerClass.getName());
            } catch (InstantiationException e) {
                throw JpaLogger.ROOT_LOGGER.couldNotCreateInstanceProvider(e, providerClass.getName());
            } catch (IllegalAccessException e) {
                throw JpaLogger.ROOT_LOGGER.couldNotCreateInstanceProvider(e, providerClass.getName());
            }
        }
        return providersCopy;
    }

    @Override
    public void clearCachedProviders() {
        providers.clear();
    }

    /**
     * Cleared at application undeployment time to remove any persistence providers that were deployed with the application
     *
     * @param deploymentClassLoaders
     */
    public void clearCachedDeploymentSpecificProviders(Set<ClassLoader> deploymentClassLoaders) {

        synchronized(persistenceProviderPerClassLoader) {
            for (ClassLoader deploymentClassLoader: deploymentClassLoaders) {
                persistenceProviderPerClassLoader.remove(deploymentClassLoader);
            }
        }
    }

    /**
     * Set at application deployment time to the persistence providers packaged in the application
     *
     * @param persistenceProvider
     * @param deploymentClassLoaders
     */
    public void addDeploymentSpecificPersistenceProvider(PersistenceProvider persistenceProvider, Set<ClassLoader> deploymentClassLoaders) {

        synchronized(persistenceProviderPerClassLoader) {

            for (ClassLoader deploymentClassLoader: deploymentClassLoaders) {
                List<Class<? extends PersistenceProvider>> list = persistenceProviderPerClassLoader.get(deploymentClassLoader);
                ROOT_LOGGER.tracef("getting persistence provider list (%s) for deployment (%s)", list, deploymentClassLoader );
                if (list == null) {
                    list = new ArrayList<>();
                    persistenceProviderPerClassLoader.put(deploymentClassLoader, list);
                    ROOT_LOGGER.tracef("saving new persistence provider list (%s) for deployment (%s)", list, deploymentClassLoader );
                }
                list.add(persistenceProvider.getClass());
                ROOT_LOGGER.tracef("added new persistence provider (%s) to provider list (%s)", persistenceProvider.getClass().getName(), list);
            }
        }
    }

    /**
     * If a custom CL is in use we want to get the module CL it delegates to
     * @param classLoader The current CL
     * @returnThe corresponding module CL
     */
    private ClassLoader findParentModuleCl(ClassLoader classLoader) {
        ClassLoader c = classLoader;
        while (c != null && !(c instanceof ModuleClassLoader)) {
            c = c.getParent();
        }
        return c;
    }

    public void addPersistenceProvider(PersistenceProvider persistenceProvider) {
        providers.add(persistenceProvider.getClass());
    }

}