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

import static org.jboss.as.webservices.util.ASHelper.getJBossWebMetaData;
import static org.jboss.as.webservices.util.ASHelper.getOptionalAttachment;
import static org.jboss.as.webservices.util.WSAttachmentKeys.CLASSLOADER_KEY;
import static org.jboss.as.webservices.util.WSAttachmentKeys.DEPLOYMENT_KEY;
import static org.jboss.as.webservices.util.WSAttachmentKeys.JAXWS_ENDPOINTS_KEY;
import static org.jboss.as.webservices.util.WSAttachmentKeys.JBOSS_WEBSERVICES_METADATA_KEY;
import static org.jboss.as.webservices.util.WSAttachmentKeys.REJECTION_RULE_KEY;
import static org.jboss.as.webservices.util.WSAttachmentKeys.WEBSERVICES_METADATA_KEY;

import org.jboss.as.ejb3.deployment.EjbDeploymentAttachmentKeys;
import org.jboss.as.server.deployment.Attachments;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.module.ResourceRoot;
import org.jboss.as.webservices.logging.WSLogger;
import org.jboss.as.webservices.metadata.model.JAXWSDeployment;
import org.jboss.as.webservices.util.VirtualFileAdaptor;
import org.jboss.metadata.ejb.spec.EjbJarMetaData;
import org.jboss.metadata.web.jboss.JBossWebMetaData;
import org.jboss.modules.Module;
import org.jboss.vfs.VirtualFile;
import org.jboss.ws.common.ResourceLoaderAdapter;
import org.jboss.wsf.spi.SPIProvider;
import org.jboss.wsf.spi.SPIProviderResolver;
import org.jboss.wsf.spi.deployment.AnnotationsInfo;
import org.jboss.wsf.spi.deployment.ArchiveDeployment;
import org.jboss.wsf.spi.deployment.Deployment;
import org.jboss.wsf.spi.deployment.DeploymentModelFactory;
import org.jboss.wsf.spi.deployment.Endpoint;
import org.jboss.wsf.spi.deployment.EndpointType;
import org.jboss.wsf.spi.deployment.UnifiedVirtualFile;
import org.jboss.wsf.spi.invocation.RejectionRule;
import org.jboss.wsf.spi.metadata.webservices.JBossWebservicesMetaData;
import org.jboss.wsf.spi.metadata.webservices.WebservicesMetaData;

/**
 * Base class for all deployment model builders.
 *
 * @author Alessio Soldano
 * @author Richard Opalka
 */
abstract class AbstractDeploymentModelBuilder implements DeploymentModelBuilder {

    /** Deployment model factory. */
    private final DeploymentModelFactory deploymentModelFactory;

    /** Endpoint type this builder creates. */
    private final EndpointType endpointType;

    /**
     * Constructor.
     */
    protected AbstractDeploymentModelBuilder(final EndpointType endpointType) {
        // deployment factory
        final ClassLoader cl = AbstractDeploymentModelBuilder.class.getClassLoader();
        final SPIProvider spiProvider = SPIProviderResolver.getInstance(cl).getProvider();
        this.deploymentModelFactory = spiProvider.getSPI(DeploymentModelFactory.class, cl);
        this.endpointType = endpointType;
    }

    /**
     * @see org.jboss.webservices.integration.deployers.deployment.DeploymentModelBuilder#newDeploymentModel(DeploymentUnit)
     *
     * @param unit deployment unit
     */
    public final void newDeploymentModel(final DeploymentUnit unit) {
        final ArchiveDeployment dep;
        if (unit.hasAttachment(DEPLOYMENT_KEY)) {
            dep = (ArchiveDeployment) unit.getAttachment(DEPLOYMENT_KEY);
        } else {
            dep = newDeployment(unit);
            propagateAttachments(unit, dep);
        }

        this.build(dep, unit);
    }

    private void propagateAttachments(final DeploymentUnit unit, final ArchiveDeployment dep) {
        dep.addAttachment(DeploymentUnit.class, unit);
        unit.putAttachment(DEPLOYMENT_KEY, dep);

        final JBossWebMetaData webMD = getJBossWebMetaData(unit);
        dep.addAttachment(JBossWebMetaData.class, webMD);

        final WebservicesMetaData webservicesMD = getOptionalAttachment(unit, WEBSERVICES_METADATA_KEY);
        dep.addAttachment(WebservicesMetaData.class, webservicesMD);

        JBossWebservicesMetaData jbossWebservicesMD = getOptionalAttachment(unit, JBOSS_WEBSERVICES_METADATA_KEY);
        if (unit.getParent() != null) {
            jbossWebservicesMD = JBossWebservicesMetaData.merge(
                    getOptionalAttachment(unit.getParent(), JBOSS_WEBSERVICES_METADATA_KEY), jbossWebservicesMD);
        }
        dep.addAttachment(JBossWebservicesMetaData.class, jbossWebservicesMD);

        final JAXWSDeployment jaxwsDeployment = getOptionalAttachment(unit, JAXWS_ENDPOINTS_KEY);
        dep.addAttachment(JAXWSDeployment.class, jaxwsDeployment);

        final EjbJarMetaData ejbJarMD = getOptionalAttachment(unit, EjbDeploymentAttachmentKeys.EJB_JAR_METADATA);
        dep.addAttachment(EjbJarMetaData.class, ejbJarMD);

        final RejectionRule rr = getOptionalAttachment(unit, REJECTION_RULE_KEY);
        if (rr != null) {
            dep.addAttachment(RejectionRule.class, rr);

        }
    }

    /**
     * Template method for subclasses to implement.
     *
     * @param dep webservice deployment
     * @param unit deployment unit
     */
    protected abstract void build(Deployment dep, DeploymentUnit unit);

    /**
     * Creates new Http Web Service endpoint.
     *
     * @param endpointClass endpoint class name
     * @param endpointName endpoint name
     * @param dep deployment
     * @return WS endpoint
     */
    protected final Endpoint newHttpEndpoint(final String endpointClass, final String endpointName, final Deployment dep) {
        if (endpointName == null) throw WSLogger.ROOT_LOGGER.nullEndpointName();
        if (endpointClass == null) throw WSLogger.ROOT_LOGGER.nullEndpointClass();

        final Endpoint endpoint = this.deploymentModelFactory.newHttpEndpoint(endpointClass);
        endpoint.setShortName(endpointName);
        endpoint.setType(endpointType);
        dep.getService().addEndpoint(endpoint);

        return endpoint;
    }

    /**
     * Creates new JMS Web Service endpoint.
     *
     * @param endpointClass endpoint class name
     * @param endpointName endpoint name
     * @param dep deployment
     * @return WS endpoint
     */
    protected final Endpoint newJMSEndpoint(final String endpointClass, final String endpointName, final String soapAddress, final Deployment dep) {
        if (endpointName == null) throw WSLogger.ROOT_LOGGER.nullEndpointName();
        if (endpointClass == null) throw WSLogger.ROOT_LOGGER.nullEndpointClass();

        final Endpoint endpoint = deploymentModelFactory.newJMSEndpoint(endpointClass);
        endpoint.setAddress(soapAddress);
        endpoint.setShortName(endpointName);
        endpoint.setType(endpointType);
        dep.getService().addEndpoint(endpoint);

        return endpoint;
    }

    /**
     * Creates new Web Service deployment.
     *
     * @param unit deployment unit
     * @return archive deployment
     */
    private ArchiveDeployment newDeployment(final DeploymentUnit unit) {
        WSLogger.ROOT_LOGGER.tracef("Creating new unified WS deployment model for %s", unit);
        final ResourceRoot deploymentRoot = unit.getAttachment(Attachments.DEPLOYMENT_ROOT);
        final VirtualFile root = deploymentRoot != null ? deploymentRoot.getRoot() : null;
        final ClassLoader classLoader;
        final Module module = unit.getAttachment(Attachments.MODULE);
        if (module == null) {
            classLoader = unit.getAttachment(CLASSLOADER_KEY);
            if (classLoader == null) {
                throw WSLogger.ROOT_LOGGER.classLoaderResolutionFailed(unit);
            }
        } else {
            classLoader = module.getClassLoader();
        }

        ArchiveDeployment parentDep = null;
        if (unit.getParent() != null) {
            final Module parentModule = unit.getParent().getAttachment(Attachments.MODULE);
            if (parentModule == null) {
                throw WSLogger.ROOT_LOGGER.classLoaderResolutionFailed(deploymentRoot);
            }
            WSLogger.ROOT_LOGGER.tracef("Creating new unified WS deployment model for %s", unit.getParent());
            parentDep = this.newDeployment(null, unit.getParent().getName(), parentModule.getClassLoader(), null);
        }

        final UnifiedVirtualFile uvf = root != null ? new VirtualFileAdaptor(root) : new ResourceLoaderAdapter(classLoader);
        final ArchiveDeployment dep = this.newDeployment(parentDep, unit.getName(), classLoader, uvf);

        //add an AnnotationInfo attachment that uses composite jandex index
        dep.addAttachment(AnnotationsInfo.class, new JandexAnnotationsInfo(unit));

        return dep;
    }

    private ArchiveDeployment newDeployment(final ArchiveDeployment parent, final String name, final ClassLoader loader, final UnifiedVirtualFile rootFile) {
        if (parent != null) {
            return (ArchiveDeployment) this.deploymentModelFactory.newDeployment(parent, name, loader, rootFile);
        } else {
            return (ArchiveDeployment) this.deploymentModelFactory.newDeployment(name, loader, rootFile);
        }

    }
}


/*
 * Copyright 2017 Red Hat, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.wildfly.iiop.openjdk.csiv2;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.Principal;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

import com.sun.corba.se.impl.interceptors.ClientRequestInfoImpl;
import com.sun.corba.se.impl.transport.SocketOrChannelContactInfoImpl;
import com.sun.corba.se.pept.transport.ContactInfo;
import com.sun.corba.se.spi.transport.CorbaConnection;
import org.jboss.as.controller.capability.RuntimeCapability;
import org.jboss.as.server.CurrentServiceContainer;
import org.jboss.msc.service.ServiceContainer;
import org.jboss.msc.service.ServiceName;
import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.CompletionStatus;
import org.omg.CORBA.LocalObject;
import org.omg.CORBA.ORB;
import org.omg.CSI.AuthorizationElement;
import org.omg.CSI.EstablishContext;
import org.omg.CSI.GSS_NT_ExportedNameHelper;
import org.omg.CSI.ITTAnonymous;
import org.omg.CSI.IdentityToken;
import org.omg.CSI.MTContextError;
import org.omg.CSI.SASContextBody;
import org.omg.CSI.SASContextBodyHelper;
import org.omg.CSIIOP.CompoundSecMech;
import org.omg.CSIIOP.EstablishTrustInClient;
import org.omg.CSIIOP.IdentityAssertion;
import org.omg.GSSUP.InitialContextToken;
import org.omg.IOP.Codec;
import org.omg.IOP.CodecPackage.FormatMismatch;
import org.omg.IOP.CodecPackage.InvalidTypeForEncoding;
import org.omg.IOP.CodecPackage.TypeMismatch;
import org.omg.IOP.ServiceContext;
import org.omg.PortableInterceptor.ClientRequestInfo;
import org.omg.PortableInterceptor.ClientRequestInterceptor;
import org.omg.PortableInterceptor.ForwardRequest;
import org.wildfly.iiop.openjdk.logging.IIOPLogger;
import org.wildfly.security.auth.client.AuthenticationConfiguration;
import org.wildfly.security.auth.client.AuthenticationContext;
import org.wildfly.security.auth.client.AuthenticationContextConfigurationClient;
import org.wildfly.security.auth.client.MatchRule;
import org.wildfly.security.auth.principal.AnonymousPrincipal;
import org.wildfly.security.auth.server.SecurityDomain;
import org.wildfly.security.auth.server.SecurityIdentity;
import org.wildfly.security.manager.WildFlySecurityManager;

/**
 * This implementation of {@code org.omg.PortableInterceptor.ClientRequestInterceptor} inserts the security attribute
 * service (SAS) context into outgoing IIOP requests and handles the SAS messages received from the target security
 * service in the SAS context of incoming IIOP replies.
 *

 * When creating the SAS context, this implementation looks for an Elytron {@link AuthenticationConfiguration} that matches
 * the target URI (in the form iiop://hostname:port) and then uses the configuration to obtain the security info (like
 * username and password) that is inserted into the security tokens that are set in the SAS context.
 *

 * The type of security tokens that are constructed depends on the target security requirements:
 *

 *

 *         If the target supports identity propagation, the identity obtained from the Elytron configuration that matches
 *         the target URI to build the {@link IdentityToken} that is inserted into the SAS context. This usually means using
 *         a configuration backed by a security domain so that the current authenticated identity in that domain is used
 *         to build the identity token.
 *

 *

 *         If in addition to the identity token the target requires username/password authentication, it means the target
 *         expects this runtime (server) to identify itself using its own username and credentials. Once this runtime
 *         has been authenticated, the identity contained in the identity token is used as a run-as identity.
 *

 *         In terms of configuration, it must match the target URI and it is usually a config that defines this
 *         server's auth-name and associated credential via credential-reference.
 *

 *

 *         If the target doesn't support identity propagation but supports username/password authentication, the identity
 *         and credentials obtained from the Elytron configuration that matches the target URI to build
 *         the {@link InitialContextToken}. Again, this usually means using a configuration backed by a security domain so
 *         that the current authenticated identity in that domain and its associated credentials are used to build the
 *         initial context token.
 *

 *

 */
public class ElytronSASClientInterceptor extends LocalObject implements ClientRequestInterceptor {

    private static final int SAS_CONTEXT_ID = org.omg.IOP.SecurityAttributeService.value;

    private static final String AUTHENTICATION_CONTEXT_CAPABILITY =  "org.wildfly.security.authentication-context";

    private static final RuntimeCapability<Void> AUTHENTICATION_CONTEXT_RUNTIME_CAPABILITY = RuntimeCapability
            .Builder.of(AUTHENTICATION_CONTEXT_CAPABILITY, true, AuthenticationContext.class)
            .build();

    private static final AuthenticationContextConfigurationClient AUTH_CONFIG_CLIENT =
            AccessController.doPrivileged(AuthenticationContextConfigurationClient.ACTION);

    private static final IdentityToken ABSENT_IDENTITY_TOKEN;

    static {
        ABSENT_IDENTITY_TOKEN = new IdentityToken();
        ABSENT_IDENTITY_TOKEN.absent(true);
    }

    private static final byte[] NO_AUTHENTICATION_TOKEN = {};

    private static final AuthorizationElement[] NO_AUTHORIZATION_TOKEN = {};

    private static String authenticationContextName;

    public static void setAuthenticationContextName(final String authenticationContextName) {
        ElytronSASClientInterceptor.authenticationContextName = authenticationContextName;
    }

    private Codec codec;

    private AuthenticationContext authContext;

    public ElytronSASClientInterceptor(final Codec codec) {
        this.codec = codec;

        // initialize the authentication context.
        final ServiceContainer container = this.currentServiceContainer();
        if(authenticationContextName != null) {
            final ServiceName authContextServiceName = AUTHENTICATION_CONTEXT_RUNTIME_CAPABILITY.getCapabilityServiceName(authenticationContextName);
            this.authContext = (AuthenticationContext) container.getRequiredService(authContextServiceName).getValue();
        } else {
            this.authContext = null;
        }
    }

    @Override
    public void send_request(ClientRequestInfo ri) throws ForwardRequest {
        try {
            CompoundSecMech secMech = CSIv2Util.getMatchingSecurityMech(ri, codec,
                    EstablishTrustInClient.value,  /* client supports */
                    (short) 0                       /* client requires */);
            if (secMech == null) {
                return;
            }

            // these "null tokens" will be changed if needed.
            IdentityToken identityToken = ABSENT_IDENTITY_TOKEN;
            byte[] encodedAuthenticationToken = NO_AUTHENTICATION_TOKEN;
            final URI uri = this.getURI(ri);
            if(uri == null) {
                return;
            }
            SecurityDomain domain = SecurityDomain.getCurrent();
            SecurityIdentity currentIdentity = null;
            if(domain != null) {
                currentIdentity = domain.getCurrentSecurityIdentity();
            }
            final AuthenticationContext authContext;
            if(this.authContext != null) {
                authContext = this.authContext;
            } else if(currentIdentity == null || currentIdentity.isAnonymous()) {
                authContext = AuthenticationContext.captureCurrent();
            } else {
                authContext = AuthenticationContext.empty().with(MatchRule.ALL, AuthenticationConfiguration.empty().useForwardedIdentity(domain));
            }

            if ((secMech.sas_context_mech.target_supports & IdentityAssertion.value) != 0) {
                final AuthenticationConfiguration configuration = AUTH_CONFIG_CLIENT.getAuthenticationConfiguration(uri, authContext, -1, null, null);
                final Principal principal = AUTH_CONFIG_CLIENT.getPrincipal(configuration);

                if (principal != null && principal != AnonymousPrincipal.getInstance()) {
                    // The name scope needs to be externalized.
                    String name = principal.getName();
                    if (name.indexOf('@') < 0) {
                        name += "@default"; // hardcoded (REVISIT!)
                    }
                    byte[] principalName = name.getBytes(StandardCharsets.UTF_8);

                    // encode the principal name as mandated by RFC2743.
                    byte[] encodedName = CSIv2Util.encodeGssExportedName(principalName);

                    // encapsulate the encoded name.
                    Any any = ORB.init().create_any();
                    byte[] encapsulatedEncodedName;
                    GSS_NT_ExportedNameHelper.insert(any, encodedName);
                    try {
                        encapsulatedEncodedName = codec.encode_value(any);
                    } catch (InvalidTypeForEncoding e) {
                        throw IIOPLogger.ROOT_LOGGER.unexpectedException(e);
                    }

                    // create identity token.
                    identityToken = new IdentityToken();
                    identityToken.principal_name(encapsulatedEncodedName);
                } else if ((secMech.sas_context_mech.supported_identity_types & ITTAnonymous.value) != 0) {
                    // no run-as or caller identity and the target supports ITTAnonymous: use the anonymous identity.
                    identityToken = new IdentityToken();
                    identityToken.anonymous(true);
                }

                // target might require an additional initial context token with a username/password pair for authentication.
                if ((secMech.as_context_mech.target_requires & EstablishTrustInClient.value) != 0) {
                    encodedAuthenticationToken = this.createInitialContextToken(uri, secMech);
                }
            }
            else if ((secMech.as_context_mech.target_supports & EstablishTrustInClient.value) != 0) {
                // target doesn't require an identity token but supports username/password authentication - try to build
                // an initial context token using the configuration.
                encodedAuthenticationToken = this.createInitialContextToken(uri, secMech);
            }

            if (identityToken != ABSENT_IDENTITY_TOKEN || encodedAuthenticationToken != NO_AUTHENTICATION_TOKEN) {
                // at least one non-null token was created, create EstablishContext message with it.
                EstablishContext message = new EstablishContext(0, // stateless ctx id
                        NO_AUTHORIZATION_TOKEN, identityToken, encodedAuthenticationToken);

                // create SAS context with the EstablishContext message.
                SASContextBody contextBody = new SASContextBody();
                contextBody.establish_msg(message);

                // stuff the SAS context into the outgoing request.
                final Any any = ORB.init().create_any();
                SASContextBodyHelper.insert(any, contextBody);
                ServiceContext sc = new ServiceContext(SAS_CONTEXT_ID, codec.encode_value(any));
                ri.add_request_service_context(sc, true /*replace existing context*/);

            }
        } catch (Exception e) {
            throw IIOPLogger.ROOT_LOGGER.unexpectedException(e);
        }

    }

    @Override
    public void send_poll(ClientRequestInfo ri) {
    }

    @Override
    public void receive_reply(ClientRequestInfo ri) {
        try {
            ServiceContext sc = ri.get_reply_service_context(SAS_CONTEXT_ID);
            Any msg = codec.decode_value(sc.context_data, SASContextBodyHelper.type());
            SASContextBody contextBody = SASContextBodyHelper.extract(msg);

            // At this point contextBody should contain a CompleteEstablishContext message, which does not require any
            // treatment. ContextError messages should arrive via receive_exception().
            IIOPLogger.ROOT_LOGGER.tracef("receive_reply: got SAS reply, type %d", contextBody.discriminator());

            if (contextBody.discriminator() == MTContextError.value) {
                // should not happen.
                throw IIOPLogger.ROOT_LOGGER.unexpectedContextErrorInSASReply(0, CompletionStatus.COMPLETED_YES);
            }
        } catch (BAD_PARAM e) {
            // no service context with sasContextId: do nothing
        } catch (FormatMismatch | TypeMismatch e) {
            throw IIOPLogger.ROOT_LOGGER.errorParsingSASReply(e, 0, CompletionStatus.COMPLETED_YES);
        }
    }

    @Override
    public void receive_exception(ClientRequestInfo ri) throws ForwardRequest {
        try {
            ServiceContext sc = ri.get_reply_service_context(SAS_CONTEXT_ID);
            Any msg = codec.decode_value(sc.context_data, SASContextBodyHelper.type());
            SASContextBody contextBody = SASContextBodyHelper.extract(msg);

            // At this point contextBody may contain either a CompleteEstablishContext message or a ContextError message.
            // Neither message requires any treatment. We decoded the context body just to check that it contains
            // a well-formed message.
            IIOPLogger.ROOT_LOGGER.tracef("receive_exception: got SAS reply, type %d", contextBody.discriminator());

        } catch (BAD_PARAM e) {
            // no service context with sasContextId: do nothing.
        } catch (FormatMismatch | TypeMismatch e) {
            throw IIOPLogger.ROOT_LOGGER.errorParsingSASReply(e, 0, CompletionStatus.COMPLETED_MAYBE);
        }
    }

    @Override
    public void receive_other(ClientRequestInfo ri) throws ForwardRequest {
    }

    @Override
    public String name() {
        return "ElytronSASClientInterceptor";
    }

    @Override
    public void destroy() {
    }

    /**
     * Get a reference to the current {@link ServiceContainer}.
     *
     * @return a reference to the current {@link ServiceContainer}.
     */
    private ServiceContainer currentServiceContainer() {
        if(WildFlySecurityManager.isChecking()) {
            return AccessController.doPrivileged(CurrentServiceContainer.GET_ACTION);
        }
        return CurrentServiceContainer.getServiceContainer();
    }

    /**
     * Build an {@link URI} using the information extracted from the specified {@link ClientRequestInfo}. The format of
     * the URI built by this method is "iiop://hostname:port".
     *
     * @param clientRequestInfo the {@link ClientRequestInfo} used to obtain the target information necessary to build
     *                          the {@link URI}.
     * @return the constructed {@link URI} instance.
     * @throws URISyntaxException if a syntax error is found when building the {@link URI}.
     */
    private URI getURI(final ClientRequestInfo clientRequestInfo) throws URISyntaxException {
        final StringBuilder builder = new StringBuilder("iiop:");
        if (clientRequestInfo instanceof ClientRequestInfoImpl) {
            ClientRequestInfoImpl infoImpl = (ClientRequestInfoImpl) clientRequestInfo;
            CorbaConnection connection = (CorbaConnection) infoImpl.connection();
            if(connection == null) {
                return null;
            }
            ContactInfo info = connection.getContactInfo();
            if (info instanceof SocketOrChannelContactInfoImpl) {
                String hostname = ((SocketOrChannelContactInfoImpl) info).getHost();
                if (hostname != null)
                    builder.append("//").append(hostname);
                int port = ((SocketOrChannelContactInfoImpl) info).getPort();
                if (port > 0)
                    builder.append(":").append(port);
            }
        } else {
            return null;
        }
        return new URI(builder.toString());
    }

    /**
     * Create an encoded {@link InitialContextToken} with an username/password pair obtained from an Elytron client configuration
     * matched by the specified {@link URI}.
     *
     * @param uri the target {@link URI}.
     * @param secMech a reference to the {@link CompoundSecMech} that was found in the {@link ClientRequestInfo}.
     * @return the encoded {@link InitialContextToken}, if a valid username is obtained from the matched configuration;
     *         an empty {@code byte[]} otherwise;
     * @throws Exception if an error occurs while building the encoded {@link InitialContextToken}.
     */
    private byte[] createInitialContextToken(final URI uri, final CompoundSecMech secMech) throws Exception {

        AuthenticationContext authContext = this.authContext == null ? AuthenticationContext.captureCurrent() : this.authContext;
        // obtain the configuration that matches the URI.
        final AuthenticationConfiguration configuration = AUTH_CONFIG_CLIENT.getAuthenticationConfiguration(uri, authContext, -1, null, null);

        // get the callback handler from the configuration and use it to obtain a username/password pair.
        final CallbackHandler handler = AUTH_CONFIG_CLIENT.getCallbackHandler(configuration);
        final NameCallback nameCallback = new NameCallback("Username: ");
        final PasswordCallback passwordCallback = new PasswordCallback("Password: ", false);
        try {
            handler.handle(new Callback[]{nameCallback, passwordCallback});
        } catch (UnsupportedCallbackException e) {
            return NO_AUTHENTICATION_TOKEN;
        }

        // if the name callback contains a valid username we create the initial context token.
        if (nameCallback.getName() != null && !nameCallback.getName().equals(AnonymousPrincipal.getInstance().getName())) {
            byte[] encodedTargetName = secMech.as_context_mech.target_name;
            String name = nameCallback.getName();
            if (name.indexOf('@') < 0) {
                byte[] decodedTargetName = CSIv2Util.decodeGssExportedName(encodedTargetName);
                String targetName = new String(decodedTargetName, StandardCharsets.UTF_8);
                name += "@" + targetName; // "@default"
            }
            byte[] username = name.getBytes(StandardCharsets.UTF_8);
            byte[] password = {};
            if (passwordCallback.getPassword() != null)
                password = new String(passwordCallback.getPassword()).getBytes(StandardCharsets.UTF_8);

            // create the initial context token and ASN.1-encode it, as defined in RFC 2743.
            InitialContextToken authenticationToken = new InitialContextToken(username, password, encodedTargetName);
            return CSIv2Util.encodeInitialContextToken(authenticationToken, codec);
        }
        return NO_AUTHENTICATION_TOKEN;
    }
}


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

import org.jboss.as.server.deployment.AttachmentKey;
import org.jboss.as.server.deployment.DeploymentUnit;

/**
 * Marker for JAX-RS deployments
 *
 * @author Stuart Douglas
 */
public class JaxrsDeploymentMarker {
    private static final AttachmentKey<Boolean> ATTACHMENT_KEY = AttachmentKey.create(Boolean.class);

    public static void mark(DeploymentUnit deployment) {
        if (deployment.getParent() != null) {
            deployment.getParent().putAttachment(ATTACHMENT_KEY, true);
        } else {
            deployment.putAttachment(ATTACHMENT_KEY, true);
        }
    }

    //This actually tells whether the deployment unit is potentially part of a JAX-RS deployment;
    //in practice, we might not be dealing with a JAX-RS deployment (it depends on which/where
    //JAX-RS annotations are found in the deployment, especially if it's an EAR one)
    public static boolean isJaxrsDeployment(DeploymentUnit deploymentUnit) {
        DeploymentUnit deployment = deploymentUnit.getParent() == null ? deploymentUnit : deploymentUnit.getParent();
        Boolean val = deployment.getAttachment(ATTACHMENT_KEY);
        return val != null && val;
    }
}


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

import java.io.Serializable;
import java.util.Date;
import java.util.concurrent.Semaphore;

import javax.ejb.EJBException;
import javax.ejb.ScheduleExpression;
import javax.ejb.Timer;
import javax.ejb.TimerHandle;

import org.jboss.as.ejb3.logging.EjbLogger;
import org.jboss.as.ejb3.component.allowedmethods.AllowedMethodsInformation;
import org.jboss.as.ejb3.component.allowedmethods.MethodType;
import org.jboss.as.ejb3.timerservice.spi.TimedObjectInvoker;

/**
 * Implementation of EJB3.1 {@link Timer}
 *
 * @author Carlo de Wolf
 * @version $Revision: $
 */
public class TimerImpl implements Timer {
    /**
     * The output format with the cached final values, after the first toString() invocation
     */
    private String toStringTemplate = null;
    /**
     * Unique id for this timer instance
     */
    protected final String id;

    /**
     * The timer state
     */
    protected volatile TimerState timerState;

    /**
     * The {@link javax.ejb.TimerService} through which this timer was created
     */
    protected final TimerServiceImpl timerService;

    /**
     * The {@link TimedObjectInvoker} to which this timer corresponds
     */
    protected final TimedObjectInvoker timedObjectInvoker;

    /**
     * The info which was passed while creating the timer.
     */
    protected final Serializable info;

    /**
     * Indicates whether the timer is persistent
     */
    protected final boolean persistent;

    /**
     * A {@link javax.ejb.TimerHandle} for this timer
     */
    protected final TimerHandleImpl handle;

    /**
     * The initial (first) expiry date of this timer
     */
    protected final Date initialExpiration;

    /**
     * The duration in milli sec. between timeouts
     */
    protected final long intervalDuration;

    /**
     * If this is an entity bean then this is the primary key
     */
    protected final Object primaryKey;

    /**
     * Next expiry date of this timer
     */
    protected volatile Date nextExpiration;

    /**
     * The date of the previous run of this timer
     */
    protected volatile Date previousRun;

    private final String timedObjectId;

    /**
     * In use lock. This is held by timer invocations and cancellation within the scope of a transaction, all changes
     * to timer state after creation should be done within this lock, to prevent state being overwritten by multiple
     * threads.
     *

     * If the timer cancelled, but then rolled back we do not want the timer task to see this cancellation.
     *
     * todo: we can probably just use a sync block here
     */
    private final Semaphore inUseLock = new Semaphore(1);

    /**
     * The executing thread which is processing the timeout task This is only set to executing thread for TimerState.IN_TIMEOUT
     * and TimerState.RETRY_TIMEOUT
     */
    private volatile Thread executingThread = null;

    /**
     * Creates a {@link TimerImpl}
     *
     * @param builder          The builder with the timer information
     * @param service          The timer service through which this timer was created
     */
    protected TimerImpl(Builder builder, TimerServiceImpl service) {
        assert builder.id != null : "id is null";

        this.id = builder.id;
        this.timedObjectId = builder.timedObjectId;
        this.info = builder.info;
        this.persistent = builder.persistent;
        this.initialExpiration = builder.initialDate;
        this.intervalDuration = builder.repeatInterval;
        if (builder.newTimer && builder.nextDate == null) {
            this.nextExpiration = initialExpiration;
        } else {
            this.nextExpiration = builder.nextDate;
        }
        this.previousRun = builder.previousRun;
        this.primaryKey = builder.primaryKey;

        this.timerState = builder.timerState;
        this.timerService = service;
        this.timedObjectInvoker = service.getInvoker();
        this.handle = new TimerHandleImpl(this.id, this.timedObjectInvoker.getTimedObjectId(), service);
        this.executingThread = null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void cancel() throws IllegalStateException, EJBException {
        try {
            timerService.cancelTimer(this);
        } catch (InterruptedException e) {
            throw new EJBException(e);
        }
    }

    /**
     * Returns the id of this timer
     *
     * @return
     */
    public String getId() {
        return this.id;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isCalendarTimer() throws IllegalStateException, EJBException {
        // first check whether this timer has expired or cancelled
        this.assertTimerState();

        return false;
    }

    /**
     * {@inheritDoc}
     *
     * @see #getTimerHandle()
     */
    @Override
    public TimerHandle getHandle() throws IllegalStateException, EJBException {
        // make sure it's in correct state
        this.assertTimerState();

        // for non-persistent timers throws an exception (mandated by EJB3 spec)
        if (this.persistent == false) {
            throw EjbLogger.EJB3_TIMER_LOGGER.invalidTimerHandlersForPersistentTimers("EJB3.1 Spec 18.2.6");
        }
        return this.handle;
    }

    /**
     * This method returns the {@link javax.ejb.TimerHandle} corresponding to this {@link TimerImpl}.
     * Unlike the {@link #getHandle()} method, this method does not throw an {@link IllegalStateException}
     * or {@link javax.ejb.NoSuchObjectLocalException} or {@link javax.ejb.EJBException}, for non-persistent timers.
     * Instead this method returns the {@link javax.ejb.TimerHandle} corresponding to that non-persistent
     * timer (remember that {@link TimerImpl} creates {@link javax.ejb.TimerHandle} for both persistent and non-persistent timers)
     *
     * @return
     */
    public TimerHandle getTimerHandle() {
        return this.handle;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isPersistent() throws IllegalStateException, EJBException {
        // make sure the call is allowed in the current timer state
        this.assertTimerState();
        return this.persistent;
    }

    public boolean isTimerPersistent() {
        return this.persistent;
    }

    /**
     * {@inheritDoc}
     *
     * @see #getTimerInfo()
     */
    @Override
    public Serializable getInfo() throws IllegalStateException, EJBException {
        // make sure this call is allowed
        this.assertTimerState();
        return this.info;
    }

    /**
     * This method is similar to {@link #getInfo()}, except that this method does not check the timer state
     * and hence does not throw either {@link IllegalStateException} or {@link javax.ejb.NoSuchObjectLocalException}
     * or {@link javax.ejb.EJBException}.
     *
     * @return
     */
    public Serializable getTimerInfo() {
        return this.info;
    }

    /**
     * {@inheritDoc}
     *
     * @see #getNextExpiration()
     */
    @Override
    public Date getNextTimeout() throws IllegalStateException, EJBException {
        // first check the validity of the timer state
        this.assertTimerState();
        if (this.nextExpiration == null) {
            throw EjbLogger.EJB3_TIMER_LOGGER.noMoreTimeoutForTimer(this);
        }
        return this.nextExpiration;
    }

    /**
     * This method is similar to {@link #getNextTimeout()}, except that this method does not check the timer state
     * and hence does not throw either {@link IllegalStateException} or {@link javax.ejb.NoSuchObjectLocalException}
     * or {@link javax.ejb.EJBException}.
     *
     * @return
     */
    public Date getNextExpiration() {
        return this.nextExpiration;
    }

    /**
     * Sets the next timeout of this timer
     *
     * @param next The next scheduled timeout of this timer
     */
    public void setNextTimeout(Date next) {
        if(next == null) {
            setTimerState(TimerState.EXPIRED, null);
        }
        this.nextExpiration = next;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ScheduleExpression getSchedule() throws IllegalStateException, EJBException {
        this.assertTimerState();
        throw EjbLogger.EJB3_TIMER_LOGGER.invalidTimerNotCalendarBaseTimer(this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getTimeRemaining() throws IllegalStateException, EJBException {
        // TODO: Rethink this implementation

        // first check the validity of the timer state
        this.assertTimerState();
        if (this.nextExpiration == null) {
            throw EjbLogger.EJB3_TIMER_LOGGER.noMoreTimeoutForTimer(this);
        }
        long currentTimeInMillis = System.currentTimeMillis();
        long nextTimeoutInMillis = this.nextExpiration.getTime();

        // if the next expiration is *not* in future and the repeat interval isn't
        // a positive number (i.e. no repeats) then there won't be any more timeouts.
        // So throw a NoMoreTimeoutsException.
        // NOTE: We check for intervalDuration and not just nextExpiration because,
        // it's a valid case where the nextExpiration is in past (maybe the server was
        // down when the timeout was expected)
        //      if (nextTimeoutInMillis < currentTimeInMillis && this.intervalDuration <= 0)
        //      {
        //         throw new NoMoreTimeoutsException("No more timeouts for timer " + this);
        //      }
        return nextTimeoutInMillis - currentTimeInMillis;
    }

    public boolean isAutoTimer() {
        return false;
    }

    /**
     * Cancels any scheduled timer task for this timer
     */
    protected void cancelTimeout() {
        // delegate to the timerservice, so that it can cancel any scheduled Future
        // for this timer
        this.timerService.cancelTimeout(this);
    }

    /**
     * Returns the initial (first) timeout date of this timer
     *
     * @return
     */
    public Date getInitialExpiration() {
        return this.initialExpiration;
    }

    /**
     * Returns the interval (in milliseconds), between timeouts, of this timer.
     *
     * @return
     */
    public long getInterval() {
        return this.intervalDuration;
    }

    /**
     * Returns the timed object id to which this timer belongs
     *
     * @return
     */
    public String getTimedObjectId() {
        return timedObjectId;
    }

    /**
     * Returns the timer service through which this timer was created
     *
     * @return
     */
    public TimerServiceImpl getTimerService() {
        return this.timerService;
    }

    /**
     * Returns true if this timer is active. Else returns false.
     *

     * A timer is considered to be "active", if its {@link TimerState}
     * is neither of the following:
     *

     *
{@link TimerState#CANCELED}

     *
{@link TimerState#EXPIRED}

     *
has not been suspended

     *

     *

     * And if the corresponding timer service is still up
     *

     *

     *
     * @return
     */
    public boolean isActive() {
        return timerService.isStarted() && !isCanceled() && !isExpired() && (timerService.isScheduled(getId()) || timerState == TimerState.CREATED);
    }

    /**
     * Returns true if this timer is in {@link TimerState#CANCELED} state. Else returns false.
     *
     * @return
     */
    public boolean isCanceled() {
        return timerState == TimerState.CANCELED;
    }

    /**
     * Returns true if this timer is in {@link TimerState#EXPIRED} state. Else returns false
     *
     * @return
     */
    public boolean isExpired() {
        return timerState == TimerState.EXPIRED;
    }

    /**
     * Returns true if this timer is in {@link TimerState#RETRY_TIMEOUT}. Else returns false.
     *
     * @return
     */
    public boolean isInRetry() {
        return timerState == TimerState.RETRY_TIMEOUT;
    }

    /**
     * Returns the {@link java.util.Date} of the previous timeout of this timer
     *
     * @return
     */
    public Date getPreviousRun() {
        return this.previousRun;
    }

    /**
     * Sets the {@link java.util.Date} of the previous timeout of this timer
     *
     * @param previousRun
     */
    public void setPreviousRun(Date previousRun) {
        this.previousRun = previousRun;
    }

    /**
     * Returns the current state of this timer
     *
     * @return
     */
    public TimerState getState() {
        return this.timerState;
    }

    /**
     * Returns the executing thread which is processing the timeout task
     *
     * @return the executingThread
     */
    protected Thread getExecutingThread() {
        return executingThread;
    }

    /**
     * Asserts that the timer is not in any of the following states:
     *

     *
{@link TimerState#CANCELED}

     *
{@link TimerState#EXPIRED}

     *

     *
     * @throws javax.ejb.NoSuchObjectLocalException if the txtimer was canceled or has expired
     */
    protected void assertTimerState() {
        if (timerState == TimerState.EXPIRED)
            throw EjbLogger.EJB3_TIMER_LOGGER.timerHasExpired();
        if (timerState == TimerState.CANCELED)
            throw EjbLogger.EJB3_TIMER_LOGGER.timerWasCanceled();
        AllowedMethodsInformation.checkAllowed(MethodType.TIMER_SERVICE_METHOD);
    }

    /**
     * Sets the state of this timer
     *
     * @param state The state of this timer
     * @deprecated Use {@link #setTimerState(TimerState state, Thread thread)} instead.
     */
    public void setTimerState(TimerState state) {
        setTimerState(state, null);
    }

    /**
     * Sets the state and timer task executing thread of this timer
     *
     * @param state The state of this timer
     * @param thread The executing thread which is processing the timeout task
     */
    protected void setTimerState(TimerState state, Thread thread) {
        assert ((state == TimerState.IN_TIMEOUT || state == TimerState.RETRY_TIMEOUT) && thread != null) || thread == null : "Invalid to set timer state " + state + " with executing Thread " + thread;
        this.timerState = state;
        this.executingThread = thread;
    }

    /**
     * Suspends any currently scheduled task for this timer
     *

     * Note that, suspend does not cancel the {@link Timer}. Instead,
     * it just cancels the next scheduled timeout. So once the {@link Timer}
     * is restored (whenever that happens), the {@link Timer} will continue to
     * timeout at appropriate times.
     *

     */
    // TODO: Revisit this method, we probably don't need this any more.
    // In terms of implementation, this is just equivalent to cancelTimeout() method
    public void suspend() {
        // cancel any scheduled timer task (Future) for this timer
        this.cancelTimeout();
    }

    /**
     * Triggers timer, outside of normal expiration. Only used when running an explicit management trigger operation.
     *
     * The tigger operation simply runs the callback, it does not modify the timer state in any way, and there is no
     * protection against overlapping events when running it. This is the expected behaviour, as otherwise the semantics
     * of dealing with concurrent execution is complex and kinda weird.
     */
    public void invokeOneOff() throws Exception {
        this.getTimerTask().invokeBeanMethod(this);
    }
    /**
     * Creates and schedules a {@link TimerTask} for the next timeout of this timer
     *
     * @param newTimer true if this is a new timer being scheduled, and not a re-schedule due to a timeout
     */
    public void scheduleTimeout(boolean newTimer) {
        // just delegate to timerservice, for it to do the actual scheduling
        this.timerService.scheduleTimeout(this, newTimer);
    }

    /**
     * Returns the task which handles the timeouts of this {@link TimerImpl}
     *
     * @return
     * @see TimerTask
     */
    protected TimerTask<?> getTimerTask() {
        return new TimerTask<TimerImpl>(this);
    }

    public void lock() throws InterruptedException {
        inUseLock.acquire();
    }

    public void unlock() {
        inUseLock.release();
    }

    /**
     * A {@link javax.ejb.Timer} is equal to another {@link javax.ejb.Timer} if their
     * {@link javax.ejb.TimerHandle}s are equal
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (this.handle == null) {
            return false;
        }
        if (obj instanceof TimerImpl == false) {
            return false;
        }
        TimerImpl otherTimer = (TimerImpl) obj;
        return this.handle.equals(otherTimer.getTimerHandle());
    }

    @Override
    public int hashCode() {
        return this.handle.hashCode();
    }

    /**
     * A nice formatted string output for this timer
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        if (this.toStringTemplate == null) {
            // initialize with the first invocation
            StringBuilder sb = new StringBuilder();
            sb.append("[id=");
            sb.append(this.id);
            sb.append(" timedObjectId=");
            sb.append(timedObjectId);
            sb.append(" auto-timer?:");
            sb.append(this.isAutoTimer());
            sb.append(" persistent?:");
            sb.append(this.persistent);
            sb.append(" timerService=");
            sb.append(this.timerService);
            sb.append(" initialExpiration=");
            sb.append(this.initialExpiration);
            sb.append(" intervalDuration(in milli sec)=");
            sb.append(this.intervalDuration);
            this.toStringTemplate = sb.toString();
        }
        // complete with the dynamic values
        StringBuilder sb = new StringBuilder(this.toStringTemplate);
        sb.append(" nextExpiration=");
        sb.append(this.nextExpiration);
        sb.append(" timerState=");
        sb.append(this.timerState);
        sb.append(" info=");
        sb.append(this.info);
        sb.append("]");
        return sb.toString();
   }

    public Object getPrimaryKey() {
        return primaryKey;
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        protected String id;
        protected String timedObjectId;
        protected Date initialDate;
        protected long repeatInterval;
        protected Date nextDate;
        protected Date previousRun;
        protected Serializable info;
        protected Object primaryKey;
        protected TimerState timerState;
        protected boolean persistent;
        protected boolean newTimer;

        public Builder setId(final String id) {
            this.id = id;
            return this;
        }

        public Builder setTimedObjectId(final String timedObjectId) {
            this.timedObjectId = timedObjectId;
            return this;
        }

        public Builder setInitialDate(final Date initialDate) {
            this.initialDate = initialDate;
            return this;
        }

        public Builder setRepeatInterval(final long repeatInterval) {
            this.repeatInterval = repeatInterval;
            return this;
        }

        public Builder setNextDate(final Date nextDate) {
            this.nextDate = nextDate;
            return this;
        }

        public Builder setPreviousRun(final Date previousRun) {
            this.previousRun = previousRun;
            return this;
        }

        public Builder setInfo(final Serializable info) {
            this.info = info;
            return this;
        }

        public Builder setPrimaryKey(final Object primaryKey) {
            this.primaryKey = primaryKey;
            return this;
        }

        public Builder setTimerState(final TimerState timerState) {
            this.timerState = timerState;
            return this;
        }

        public Builder setPersistent(final boolean persistent) {
            this.persistent = persistent;
            return this;
        }

        public Builder setNewTimer(final boolean newTimer) {
            this.newTimer = newTimer;
            return this;
        }

        public String getId() {
            return id;
        }

        public String getTimedObjectId() {
            return timedObjectId;
        }

        public Date getInitialDate() {
            return initialDate;
        }

        public long getRepeatInterval() {
            return repeatInterval;
        }

        public Date getNextDate() {
            return nextDate;
        }

        public Date getPreviousRun() {
            return previousRun;
        }

        public Serializable getInfo() {
            return info;
        }

        public Object getPrimaryKey() {
            return primaryKey;
        }

        public TimerState getTimerState() {
            return timerState;
        }

        public boolean isPersistent() {
            return persistent;
        }

        public boolean isNewTimer() {
            return newTimer;
        }

        public TimerImpl build(final TimerServiceImpl timerService) {
            return new TimerImpl(this, timerService);
        }
    }
}


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

import org.jboss.as.server.deployment.DeploymentUnitProcessingException;

import javax.ws.rs.core.Application;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * @author Bill Burke
 */
public class ResteasyDeploymentData {
    private boolean scanAll;
    private boolean scanResources;
    private boolean scanProviders;
    private boolean dispatcherCreated;
    private final Set<String> scannedResourceClasses = new LinkedHashSet<String>();
    private final Set<String> scannedProviderClasses = new LinkedHashSet<String>();
    private List<Class<? extends Application>> scannedApplicationClasses = new ArrayList<>();
    private boolean bootClasses;
    private boolean unwrappedExceptionsParameterSet;
    private final Set<String> scannedJndiComponentResources = new LinkedHashSet<String>();

    /**
     * Merges a list of additional JAX-RS deployment data with this lot of deployment data.
     *
     * @param deploymentData
     */
    public void merge(final List<ResteasyDeploymentData> deploymentData) throws DeploymentUnitProcessingException {
        for (ResteasyDeploymentData data : deploymentData) {
            scannedApplicationClasses.addAll(data.getScannedApplicationClasses());
            if (scanResources) {
                scannedResourceClasses.addAll(data.getScannedResourceClasses());
                scannedJndiComponentResources.addAll(data.getScannedJndiComponentResources());
            }
            if (scanProviders) {
                scannedProviderClasses.addAll(data.getScannedProviderClasses());
            }
        }
    }

    public Set<String> getScannedJndiComponentResources() {
        return scannedJndiComponentResources;
    }

    public boolean isDispatcherCreated() {
        return dispatcherCreated;
    }

    public void setDispatcherCreated(boolean dispatcherCreated) {
        this.dispatcherCreated = dispatcherCreated;
    }

    public List<Class<? extends Application>> getScannedApplicationClasses() {
        return scannedApplicationClasses;
    }

    public boolean hasBootClasses() {
        return bootClasses;
    }

    public void setBootClasses(boolean bootClasses) {
        this.bootClasses = bootClasses;
    }

    public boolean shouldScan() {
        return scanAll || scanResources || scanProviders;
    }

    public boolean isScanAll() {
        return scanAll;
    }

    public void setScanAll(boolean scanAll) {
        if (scanAll) {
            scanResources = true;
            scanProviders = true;
        }
        this.scanAll = scanAll;
    }

    public boolean isScanResources() {
        return scanResources;
    }

    public void setScanResources(boolean scanResources) {
        this.scanResources = scanResources;
    }

    public boolean isScanProviders() {
        return scanProviders;
    }

    public void setScanProviders(boolean scanProviders) {
        this.scanProviders = scanProviders;
    }

    public Set<String> getScannedResourceClasses() {
        return scannedResourceClasses;
    }

    public Set<String> getScannedProviderClasses() {
        return scannedProviderClasses;
    }

    public boolean isUnwrappedExceptionsParameterSet() {
        return unwrappedExceptionsParameterSet;
    }

    public void setUnwrappedExceptionsParameterSet(boolean unwrappedExceptionsParameterSet) {
        this.unwrappedExceptionsParameterSet = unwrappedExceptionsParameterSet;
    }
}


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

import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.Set;

import javax.security.jacc.PolicyContext;

import org.jboss.as.core.security.ServerSecurityManager;
import org.jboss.as.ee.component.Component;
import org.jboss.as.ee.component.ComponentView;
import org.jboss.as.ejb3.logging.EjbLogger;
import org.jboss.as.ejb3.component.EJBComponent;
import org.jboss.as.ejb3.component.MethodIntf;
import org.jboss.invocation.Interceptor;
import org.jboss.invocation.InterceptorContext;
import org.jboss.metadata.ejb.spec.MethodInterfaceType;
import org.jboss.security.AnybodyPrincipal;
import org.jboss.security.NobodyPrincipal;
import org.jboss.security.SimplePrincipal;
import org.wildfly.security.manager.WildFlySecurityManager;

/**
 * EJB authorization interceptor responsible for handling invocation on EJB methods and doing the necessary authorization
 * checks on the invoked method.
 *

 * User: Jaikiran Pai
 */
public class AuthorizationInterceptor implements Interceptor {

    /**
     * EJB method security metadata
     */
    private final EJBMethodSecurityAttribute ejbMethodSecurityMetaData;

    /**
     * The view class name to which this interceptor is applicable
     */
    private final String viewClassName;

    /**
     * The view method to which this interceptor is applicable
     */
    private final Method viewMethod;

    /*
     * The JACC contextID to be used by this interceptor.
     */
    private final String contextID;

    public AuthorizationInterceptor(final EJBMethodSecurityAttribute ejbMethodSecurityMetaData, final String viewClassName, final Method viewMethod, final String contextID) {
        if (ejbMethodSecurityMetaData == null) {
            throw EjbLogger.ROOT_LOGGER.ejbMethodSecurityMetaDataIsNull();
        }
        if (viewClassName == null || viewClassName.trim().isEmpty()) {
            throw EjbLogger.ROOT_LOGGER.viewClassNameIsNull();
        }
        if (viewMethod == null) {
            throw EjbLogger.ROOT_LOGGER.viewMethodIsNull();
        }
        this.ejbMethodSecurityMetaData = ejbMethodSecurityMetaData;
        this.viewClassName = viewClassName;
        this.viewMethod = viewMethod;
        this.contextID = contextID;
    }

    @Override
    public Object processInvocation(InterceptorContext context) throws Exception {
        final Component component = context.getPrivateData(Component.class);
        if (component instanceof EJBComponent == false) {
            throw EjbLogger.ROOT_LOGGER.unexpectedComponent(component, EJBComponent.class);
        }
        final Method invokedMethod = context.getMethod();
        final ComponentView componentView = context.getPrivateData(ComponentView.class);
        final String viewClassOfInvokedMethod = componentView.getViewClass().getName();
        // shouldn't really happen if the interceptor was setup correctly. But let's be safe and do a check
        if (!this.viewClassName.equals(viewClassOfInvokedMethod) || !this.viewMethod.equals(invokedMethod)) {
            throw EjbLogger.ROOT_LOGGER.failProcessInvocation(this.getClass().getName(), invokedMethod, viewClassOfInvokedMethod, viewMethod, viewClassName);
        }
        final EJBComponent ejbComponent = (EJBComponent) component;
        final ServerSecurityManager securityManager = ejbComponent.getSecurityManager();
        final MethodInterfaceType methodIntfType = this.getMethodInterfaceType(componentView.getPrivateData(MethodIntf.class));

        // set the JACC contextID before calling the security manager.
        final String previousContextID = setContextID(this.contextID);
        try {
            if(WildFlySecurityManager.isChecking()) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public ProtectionDomain run() {

                            if (!securityManager.authorize(ejbComponent.getComponentName(), componentView.getProxyClass().getProtectionDomain().getCodeSource(),
                                    methodIntfType.name(), AuthorizationInterceptor.this.viewMethod, AuthorizationInterceptor.this.getMethodRolesAsPrincipals(), AuthorizationInterceptor.this.contextID)) {
                                throw EjbLogger.ROOT_LOGGER.invocationOfMethodNotAllowed(invokedMethod,ejbComponent.getComponentName());
                            }
                            return null;
                        }
                    });
                } catch (PrivilegedActionException e) {
                    throw e.getException();
                }
            } else {
                if (!securityManager.authorize(ejbComponent.getComponentName(), componentView.getProxyClass().getProtectionDomain().getCodeSource(),
                        methodIntfType.name(), this.viewMethod, this.getMethodRolesAsPrincipals(), this.contextID)) {
                    throw EjbLogger.ROOT_LOGGER.invocationOfMethodNotAllowed(invokedMethod,ejbComponent.getComponentName());
                }
            }
            // successful authorization, let the invocation proceed
            return context.proceed();
        }
        finally {
            // reset the previous JACC contextID.
            setContextID(previousContextID);
        }
    }

    /**
     *

     * Returns the method roles as a set of {@code Principal} instances. All roles specified in the method-permissions or
     * via {@code RolesAllowed} for this method are wrapped by a {@code SimplePrincipal}. If the method has been added to
     * the exclude-list or annotated with {@code DenyAll}, a NOBODY_PRINCIPAL is returned. If the method has been added
     * to the unchecked list or annotated with {@code PermitAll}, an ANYBODY_PRINCIPAL is returned.
     *

     *
     * @return the constructed set of role principals.
     */
    protected Set<Principal> getMethodRolesAsPrincipals() {
        Set<Principal> methodRoles = new HashSet<Principal>();
        if (this.ejbMethodSecurityMetaData.isDenyAll())
            methodRoles.add(NobodyPrincipal.NOBODY_PRINCIPAL);
        else if (this.ejbMethodSecurityMetaData.isPermitAll())
            methodRoles.add(AnybodyPrincipal.ANYBODY_PRINCIPAL);
        else {
            for (String role : this.ejbMethodSecurityMetaData.getRolesAllowed())
                methodRoles.add(new SimplePrincipal(role));
        }
        return methodRoles;
    }

    /**
     *

     * Gets the {@code MethodInterfaceType} that corresponds to the specified {@code MethodIntf}.
     *

     *
     * @param viewType the {@code MethodIntf} type to be converted.
     * @return the converted type or {@code null} if the type cannot be converted.
     */
    protected MethodInterfaceType getMethodInterfaceType(MethodIntf viewType) {
        switch (viewType) {
            case HOME:
                return MethodInterfaceType.Home;
            case LOCAL_HOME:
                return MethodInterfaceType.LocalHome;
            case SERVICE_ENDPOINT:
                return MethodInterfaceType.ServiceEndpoint;
            case LOCAL:
                return MethodInterfaceType.Local;
            case REMOTE:
                return MethodInterfaceType.Remote;
            case TIMER:
                return MethodInterfaceType.Timer;
            case MESSAGE_ENDPOINT:
                return MethodInterfaceType.MessageEndpoint;
            default:
                return null;
        }
    }

    /**
     *

     * Sets the JACC contextID using a privileged action and returns the previousID from the {@code PolicyContext}.
     *

     *
     * @param contextID the JACC contextID to be set.
     * @return the previous contextID as retrieved from the {@code PolicyContext}.
     */
    protected String setContextID(final String contextID) {
        if (! WildFlySecurityManager.isChecking()) {
            final String previousID = PolicyContext.getContextID();
            PolicyContext.setContextID(contextID);
            return previousID;
        } else {
            final PrivilegedAction<String> action = new SetContextIDAction(contextID);
            return AccessController.doPrivileged(action);
        }
    }

    /**
     * PrivilegedAction that sets the {@code PolicyContext} id.
     */
    private static class SetContextIDAction implements PrivilegedAction<String> {

        private String contextID;

        SetContextIDAction(final String contextID) {
            this.contextID = contextID;
        }

        @Override
        public String run() {
            final String previousID = PolicyContext.getContextID();
            PolicyContext.setContextID(this.contextID);
            return previousID;
        }
    }
}


/*
 * 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 org.omg.CORBA.ModuleDefOperations;
import org.omg.CORBA.ModuleDefPOATie;
import org.omg.CORBA.Any;
import org.omg.CORBA.IRObject;
import org.omg.CORBA.Contained;
import org.omg.CORBA.ContainedOperations;
import org.omg.CORBA.ContainedPackage.Description;
import org.omg.CORBA.IDLType;
import org.omg.CORBA.DefinitionKind;
import org.omg.CORBA.StructMember;
import org.omg.CORBA.UnionMember;
import org.omg.CORBA.InterfaceDef;
import org.omg.CORBA.ConstantDef;
import org.omg.CORBA.EnumDef;
import org.omg.CORBA.ValueDef;
import org.omg.CORBA.ValueBoxDef;
import org.omg.CORBA.Initializer;
import org.omg.CORBA.StructDef;
import org.omg.CORBA.UnionDef;
import org.omg.CORBA.ModuleDef;
import org.omg.CORBA.AliasDef;
import org.omg.CORBA.NativeDef;
import org.omg.CORBA.ExceptionDef;
import org.omg.CORBA.ModuleDescription;
import org.omg.CORBA.ModuleDescriptionHelper;

/**
 * Abstract base class for all contained IR entities.
 *
 * @author Ole Husgaard
 * @version $Revision: 81018 $
 */
class ModuleDefImpl
        extends ContainedImpl
        implements ModuleDefOperations, LocalContainer {
    // Constants -----------------------------------------------------

    // Attributes ----------------------------------------------------

    // Static --------------------------------------------------------

    // Constructors --------------------------------------------------

    ModuleDefImpl(String id, String name, String version,
                  LocalContainer defined_in, RepositoryImpl repository) {
        super(id, name, version, defined_in,
                DefinitionKind.dk_Module, repository);

        this.delegate = new ContainerImplDelegate(this);
    }

    // Public --------------------------------------------------------

    // LocalContainer implementation ---------------------------------

    public LocalContained _lookup(String search_name) {
        return delegate._lookup(search_name);
    }

    public LocalContained[] _contents(DefinitionKind limit_type,
                                      boolean exclude_inherited) {
        return delegate._contents(limit_type, exclude_inherited);
    }

    public LocalContained[] _lookup_name(String search_name,
                                         int levels_to_search,
                                         DefinitionKind limit_type,
                                         boolean exclude_inherited) {
        return delegate._lookup_name(search_name, levels_to_search, limit_type,
                exclude_inherited);
    }

    public void add(String name, LocalContained contained)
            throws IRConstructionException {
        delegate.add(name, contained);
    }

    // ContainerOperations implementation ----------------------------

    public Contained lookup(String search_name) {
        return delegate.lookup(search_name);
    }

    public Contained[] contents(DefinitionKind limit_type,
                                boolean exclude_inherited) {
        return delegate.contents(limit_type, exclude_inherited);
    }

    public Contained[] lookup_name(String search_name, int levels_to_search,
                                   DefinitionKind limit_type,
                                   boolean exclude_inherited) {
        return delegate.lookup_name(search_name, levels_to_search, limit_type,
                exclude_inherited);
    }

    public org.omg.CORBA.ContainerPackage.Description[]
    describe_contents(DefinitionKind limit_type,
                      boolean exclude_inherited,
                      int max_returned_objs) {
        return delegate.describe_contents(limit_type, exclude_inherited,
                max_returned_objs);
    }

    public ModuleDef create_module(String id, String name, String version) {
        return delegate.create_module(id, name, version);
    }

    public ConstantDef create_constant(String id, String name, String version,
                                       IDLType type, Any value) {
        return delegate.create_constant(id, name, version, type, value);
    }

    public StructDef create_struct(String id, String name, String version,
                                   StructMember[] members) {
        return delegate.create_struct(id, name, version, members);
    }

    public UnionDef create_union(String id, String name, String version,
                                 IDLType discriminator_type,
                                 UnionMember[] members) {
        return delegate.create_union(id, name, version, discriminator_type,
                members);
    }

    public EnumDef create_enum(String id, String name, String version,
                               String[] members) {
        return delegate.create_enum(id, name, version, members);
    }

    public AliasDef create_alias(String id, String name, String version,
                                 IDLType original_type) {
        return delegate.create_alias(id, name, version, original_type);
    }

    public InterfaceDef create_interface(String id, String name, String version,
                                         InterfaceDef[] base_interfaces,
                                         boolean is_abstract) {
        return delegate.create_interface(id, name, version,
                base_interfaces, is_abstract);
    }

    public ValueDef create_value(String id, String name, String version,
                                 boolean is_custom, boolean is_abstract,
                                 ValueDef base_value, boolean is_truncatable,
                                 ValueDef[] abstract_base_values,
                                 InterfaceDef[] supported_interfaces,
                                 Initializer[] initializers) {
        return delegate.create_value(id, name, version, is_custom, is_abstract,
                base_value, is_truncatable,
                abstract_base_values, supported_interfaces,
                initializers);
    }

    public ValueBoxDef create_value_box(String id, String name, String version,
                                        IDLType original_type_def) {
        return delegate.create_value_box(id, name, version, original_type_def);
    }

    public ExceptionDef create_exception(String id, String name, String version,
                                         StructMember[] members) {
        return delegate.create_exception(id, name, version, members);
    }

    public NativeDef create_native(String id, String name, String version) {
        return delegate.create_native(id, name, version);
    }

    // LocalIRObject implementation ----------------------------------

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

    public void allDone()
            throws IRConstructionException {
        getReference();
        delegate.allDone();
    }

    public void shutdown() {
        delegate.shutdown();
        super.shutdown();
    }

    // ContainedImpl implementation ----------------------------------

    public Description describe() {
        String defined_in_id = "IR";

        if (defined_in instanceof ContainedOperations)
            defined_in_id = ((ContainedOperations) defined_in).id();

        ModuleDescription md = new ModuleDescription(name, id, defined_in_id,
                version);

        Any any = getORB().create_any();

        ModuleDescriptionHelper.insert(any, md);

        return new Description(DefinitionKind.dk_Module, any);
    }

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

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

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

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

    /**
     * My delegate for Container functionality.
     */
    private ContainerImplDelegate delegate;

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

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


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

import static org.jboss.as.ee.subsystem.EeSubsystemRootResource.ECLIPSE_YASSON;
import static org.jboss.as.ee.subsystem.EeSubsystemRootResource.GLASSFISH_EL;
import static org.jboss.as.ee.subsystem.EeSubsystemRootResource.JSON_API;
import static org.jboss.as.ee.subsystem.EeSubsystemRootResource.JSON_BIND_API;
import static org.jboss.as.ee.subsystem.EeSubsystemRootResource.WILDFLY_NAMING;
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.module.ModuleDependency;
import org.jboss.as.server.deployment.module.ModuleSpecification;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoader;
import org.jboss.modules.filter.PathFilters;

/**
 * Deployment processor which adds the java EE APIs to EE deployments
 * <p/>
 *
 * @author John E. Bailey
 * @author Jason T. Greene
 * @author Stuart Douglas
 */
public class JavaEEDependencyProcessor implements DeploymentUnitProcessor {

    private static ModuleIdentifier JBOSS_INVOCATION_ID = ModuleIdentifier.create("org.jboss.invocation");
    private static ModuleIdentifier JBOSS_AS_EE = ModuleIdentifier.create("org.jboss.as.ee");

    private static final ModuleIdentifier[] JAVA_EE_API_MODULES = {
            ModuleIdentifier.create("javax.annotation.api"),
            ModuleIdentifier.create("javax.enterprise.concurrent.api"),
            ModuleIdentifier.create("javax.interceptor.api"),
            ModuleIdentifier.create(JSON_API),
            ModuleIdentifier.create(JSON_BIND_API),
            ModuleIdentifier.create("javax.resource.api"),
            ModuleIdentifier.create("javax.rmi.api"),
            ModuleIdentifier.create("javax.xml.bind.api"),
            ModuleIdentifier.create("javax.api"),
            // javax.json.bind.api (JSON-B) implementation
            ModuleIdentifier.create(ECLIPSE_YASSON),
            ModuleIdentifier.create(GLASSFISH_EL),
            ModuleIdentifier.create("org.glassfish.javax.enterprise.concurrent")
    };

    /**
     * Add the EE APIs as a dependency to all deployments
     *
     * @param phaseContext the deployment unit context
     * @throws DeploymentUnitProcessingException
     *
     */
    public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
        final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
        final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);

        final ModuleLoader moduleLoader = Module.getBootModuleLoader();

        //add jboss-invocation classes needed by the proxies
        ModuleDependency invocation = new ModuleDependency(moduleLoader, JBOSS_INVOCATION_ID, false, false, false, false);
        invocation.addImportFilter(PathFilters.is("org/jboss/invocation/proxy/classloading"), true);
        invocation.addImportFilter(PathFilters.acceptAll(), false);
        moduleSpecification.addSystemDependency(invocation);

        ModuleDependency ee = new ModuleDependency(moduleLoader, JBOSS_AS_EE, false, false, false, false);
        ee.addImportFilter(PathFilters.is("org/jboss/as/ee/component/serialization"), true);
        ee.addImportFilter(PathFilters.is("org/jboss/as/ee/concurrent"), true);
        ee.addImportFilter(PathFilters.is("org/jboss/as/ee/concurrent/handle"), true);
        ee.addImportFilter(PathFilters.acceptAll(), false);
        moduleSpecification.addSystemDependency(ee);

        // add dep for naming permission
        moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, ModuleIdentifier.create(WILDFLY_NAMING), false, false, false, false));

        //we always add all Java EE API modules, as the platform spec requires them to always be available
        //we do not just add the javaee.api module, as this breaks excludes

        for (final ModuleIdentifier moduleIdentifier : JAVA_EE_API_MODULES) {
            moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, moduleIdentifier, true, false, true, false));
        }
    }

    public void undeploy(final DeploymentUnit context) {
    }
}