All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.petals.microkernel.jbi.component.context.ComponentContextImpl Maven / Gradle / Ivy

There is a newer version: 4.3.0
Show newest version
/**
 * Copyright (c) 2005-2012 Fossil E-Commerce, 2005-2012 EBM WebSourcing, 2012-2016 Linagora
 * 
 * This program/library 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 program/library 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 program/library; If not, see http://www.gnu.org/licenses/
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.microkernel.jbi.component.context;

import static org.ow2.petals.microkernel.api.container.ContainerService.COMPONENT_LOGGER_PREFIX;

import java.util.Collection;
import java.util.HashSet;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.logging.Logger;

import javax.jbi.JBIException;
import javax.jbi.component.Component;
import javax.jbi.management.MBeanNames;
import javax.jbi.messaging.MessagingException;
import javax.jbi.servicedesc.ServiceEndpoint;
import javax.management.MBeanServer;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.namespace.QName;

import org.ow2.petals.clientserverapi.jbi.messaging.endpoint.exception.EndpointDirectoryException;
import org.ow2.petals.jbi.messaging.PetalsDeliveryChannel;
import org.ow2.petals.jbi.messaging.exchange.PetalsMessageExchange;
import org.ow2.petals.jbi.servicedesc.endpoint.Location;
import org.ow2.petals.jbi.servicedesc.endpoint.PetalsServiceEndpoint;
import org.ow2.petals.jbi.servicedesc.endpoint.util.ServiceEndpointHelper;
import org.ow2.petals.microkernel.api.configuration.ContainerConfiguration;
import org.ow2.petals.microkernel.api.container.ComponentContextCommunication;
import org.ow2.petals.microkernel.api.jbi.component.PetalsComponentContext;
import org.ow2.petals.microkernel.api.jbi.messaging.RouterService;
import org.ow2.petals.microkernel.api.jbi.messaging.endpoint.exception.EndpointDoesNotExistsException;
import org.ow2.petals.microkernel.api.jbi.messaging.exception.RoutingException;
import org.ow2.petals.microkernel.api.jbi.security.SecurityContext;
import org.ow2.petals.microkernel.jbi.messaging.exchange.DeliveryChannelImpl;
import org.ow2.petals.microkernel.util.ParameterCheckHelper;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;

import com.ebmwebsourcing.easycommons.log.LoggingUtil;

/**
 * @author Rafael Marins - Fossil E-Commerce
 * @author wjoseph - EBM WebSourcing
 */
public class ComponentContextImpl implements PetalsComponentContext {

    protected DeliveryChannelImpl deliveryChannel;

    /**
     * references of registered external serviceEndpoints
     */
    protected final Set externalEndpoints;

    /**
     * references of registered internal serviceEndpoints
     */
    protected final Set internalEndpoints;

    protected Component jbiComponent;

    protected final ComponentContextCommunication installerServices;

    private final ComponentInitialContext initialContext;

    /**
     * The consumer location
     */
    private final Location location;

    private final LoggingUtil logger;

    private SecurityContext securityContext;

    public ComponentContextImpl(final ComponentContextCommunication installerServices)
            throws NamingException {
        this.installerServices = installerServices;
        
        this.internalEndpoints = new HashSet();
        this.externalEndpoints = new HashSet();

        this.initialContext = new ComponentInitialContext(this.installerServices.getJNDIService().getUsersContext());

        this.location = new Location(
                this.installerServices.getConfigurationService().getContainerConfiguration().getName(),
                getComponentName());

        this.logger = new LoggingUtil(
                Logger.getLogger(Constants.FRACTAL_COMPONENT_LOGGER_NAME + "." + getComponentName()));

    }

    @Override
    public void offerExchange(final PetalsMessageExchange exchange) throws RoutingException {
        try {
            if (deliveryChannel == null) {
                // if there is no delivery channel, then let's create it
                // Note: we don't want to create a new delivery channel if it's closed because
                // it is not the responsibility of the router to do that!
                getDeliveryChannel();
            }
            
            // if the channel is closed, it will send an exception
            this.deliveryChannel.offerExchange(exchange);
        } catch (final MessagingException e) {
            throw new RoutingException("Can't create delivery channel", e);
        }
    }

    @Override
    public ServiceEndpoint activateEndpoint(final QName serviceName, final String endpointName) throws JBIException {
        this.logger.start();

        ParameterCheckHelper.isNullParameter(serviceName, "serviceName");
        ParameterCheckHelper.isNullParameter(serviceName, "endpointName");

        Document doc = this.getComponent().getServiceDescription(new ServiceEndpoint() {
            public DocumentFragment getAsReference(QName operationName) {
                return null;
            }

            public String getEndpointName() {
                return endpointName;
            }

            public QName[] getInterfaces() {
                return new QName[] {};
            }

            public QName getServiceName() {
                return serviceName;
            }

        });

        // switch the classloader to the container one
        // CAUTION : this must be done AFTER getServiceDescription is called
        ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

        final QName[] interfaces = ServiceEndpointHelper.getInterfacesForEndpoint(serviceName, endpointName, doc,
                this.logger.getLogger());

        final ServiceEndpoint se;
        try {
            this.logger.debug("Activating a new endpoint in the registry");
            se = this.installerServices.getEndpointDirectory().activateEndpoint(serviceName, endpointName, interfaces,
                    doc, getComponentName());
        } catch (final EndpointDirectoryException e) {
            throw new JBIException(e);
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
        }
        this.internalEndpoints.add(se);
        this.logger.end();
        return se;
    }

    @Override
    public void clear() {
        this.deliveryChannel = null;
        this.jbiComponent = null;
    }

    @Override
    public void deactivateEndpoint(ServiceEndpoint endpoint) throws JBIException {
        this.logger.start();

        ParameterCheckHelper.isNullParameter(endpoint, "endpoint");

        // switch the classloader to the container one
        ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

        try {
            this.installerServices.getEndpointDirectory().deactivateEndpoint(endpoint.getEndpointName(),
                    endpoint.getServiceName(), getComponentName());
            this.deliveryChannel.notifyEndpointDeactivated(endpoint);
        } catch (final EndpointDirectoryException e) {
            throw new JBIException(e);
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
        }

        this.internalEndpoints.remove(endpoint);
        this.logger.end();
    }

    /**
     * TODO maybe the {@link DeliveryChannelImpl} should simply ask the endpoint directory to cleanup things related to
     * the component instead of storing the endpoints here internally...
     */
    @Override
    public void deactivateAllEndpoints() {
        this.logger.start();

        // switch the classloader to the container one
        ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        try {
            for (ServiceEndpoint se : this.internalEndpoints) {
                try {
                    this.installerServices.getEndpointDirectory().deactivateEndpoint(se.getEndpointName(),
                        se.getServiceName(), getComponentName());
                } catch (final EndpointDirectoryException e) {
                    this.logger.warning("Can't deactivate endpoint: " + se, e);
                }
            }

            for (ServiceEndpoint se : this.externalEndpoints) {
                try {
                    this.installerServices.getEndpointDirectory().deregisterExternalEndpoint(se, getComponentName());
                } catch (final EndpointDirectoryException e) {
                    this.logger.warning("Can't deregister external endpoint: " + se, e);
                }
            }

        } finally {
            this.internalEndpoints.clear();
            this.externalEndpoints.clear();
            Thread.currentThread().setContextClassLoader(componentClassLoader);

            this.logger.end();
        }
    }

    @Override
    public void deregisterExternalEndpoint(ServiceEndpoint externalEndpoint) throws JBIException {
        this.logger.start();

        ParameterCheckHelper.isNullParameter(externalEndpoint, "externalEndpoint");

        try {
            this.installerServices.getEndpointDirectory().deregisterExternalEndpoint(externalEndpoint,
                    getComponentName());
            this.externalEndpoints.remove(externalEndpoint);
        } catch (final EndpointDirectoryException e) {
            throw new JBIException(e);
        } finally {
            this.logger.end();
        }
    }

    @Override
    public Component getComponent() {
        return this.jbiComponent;
    }

    @Override
    public String getComponentName() {
        return this.installerServices.getJBIDescriptor().getComponent().getIdentification().getName();
    }

    @Override
    public ContainerConfiguration getContainerConfiguration() {
        return this.installerServices.getConfigurationService().getContainerConfiguration();
    }

    @Override
    public PetalsDeliveryChannel getDeliveryChannel() throws MessagingException {
        this.logger.start();

        if (this.deliveryChannel == null || !this.deliveryChannel.isOpened()) {
            this.deliveryChannel = new DeliveryChannelImpl(this.location, this, this.logger.getLogger());
        } else {
            // Do not throw an exception to be TCK and other containers compliant
            // throw new MessagingException("Delivery Channel already open");
        }

        this.logger.end();
        return this.deliveryChannel;
    }
    
    @Override
    public PetalsDeliveryChannel getDeliveryChannelInstance() {
        return this.deliveryChannel;
    }

    @Override
    public ServiceEndpoint getEndpoint(QName service, String name) {
        this.logger.start();

        ParameterCheckHelper.isNullParameter(service, "service");
        ParameterCheckHelper.isNullParameter(name, "name");

        // switch the classloader to the container one
        final ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        try {
            return this.installerServices.getEndpointDirectory().getInternalEndpoint(service, name);
        } catch (Exception e) {
            this.logger.warning("Error while retrieving endpoint for service " + service + ", endpoint " + name,
                    e);
            return null;
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
            this.logger.end();
        }
    }

    @Override
    public Document getEndpointDescriptor(final ServiceEndpoint endpoint) throws JBIException {
        this.logger.start();
        ParameterCheckHelper.isNullParameter(endpoint, "endpoint");

        // switch the classloader to the container one
        // TODO document why?
        ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        try {
            final Document result = this.installerServices.getEndpointDirectory().getDescription(endpoint);
            if (result == null) {
                this.logger.debug("Cannot find the service description in the service endpoint");
            }
            return result;
        } catch (final EndpointDoesNotExistsException e) {
            throw new JBIException("Invalid endpoint reference");
        } catch (final EndpointDirectoryException e) {
            this.logger.warning("Error while retrieving endpoint description for " + endpoint.getEndpointName());
            return null;
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
            this.logger.end();
        }
    }

    @Override
    public ServiceEndpoint[] getEndpoints(final QName interfaceName) {
        this.logger.start();

        // switch the classloader to the container one
        final ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        try {
            final Collection endpoints;
            if (interfaceName != null) {
                endpoints = this.installerServices.getEndpointDirectory()
                    .getInternalEndpointsForInterface(interfaceName);
            } else {
                endpoints = this.installerServices.getEndpointDirectory().getInternalEndpoints();
            }
            return endpoints.toArray(new ServiceEndpoint[endpoints.size()]);
        } catch (Exception e) {
            this.logger.warning("Error while retrieving endpoints for interface " + interfaceName, e);
            return new ServiceEndpoint[] {};
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
            this.logger.end();
        }
    }

    @Override
    public ServiceEndpoint[] getEndpointsForService(final QName serviceName) {
        this.logger.start();

        ParameterCheckHelper.isNullParameter(serviceName, "serviceName");

        // switch the classloader to the container one
        final ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        try {
            final Collection endpoints = this.installerServices.getEndpointDirectory()
                    .getInternalEndpointsForService(serviceName);
            return endpoints.toArray(new ServiceEndpoint[endpoints.size()]);
        } catch (final EndpointDirectoryException e) {
            this.logger.warning("Error while retrieving endpoints for service " + serviceName, e);
            return new ServiceEndpoint[] {};
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
            this.logger.end();
        }
    }

    @Override
    public ServiceEndpoint[] getExternalEndpoints(final QName interfaceName) {
        this.logger.start();

        ParameterCheckHelper.isNullParameter(interfaceName, "interfaceName");

        // switch the classloader to the container one
        final ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        try {
            final Collection endpoints = this.installerServices.getEndpointDirectory()
                    .getExternalEndpointsForInterface(interfaceName);
            return endpoints.toArray(new ServiceEndpoint[endpoints.size()]);
        } catch (final EndpointDirectoryException e) {
            this.logger.warning("Error while retrieving external endpoints for interface " + interfaceName, e);
            return new ServiceEndpoint[] {};
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
            this.logger.end();
        }
    }

    @Override
    public ServiceEndpoint[] getExternalEndpointsForService(QName serviceName) {
        this.logger.start();

        ParameterCheckHelper.isNullParameter(serviceName, "serviceName");

        // switch the classloader to the container one
        final ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        try {
            final Collection endpoints = this.installerServices.getEndpointDirectory()
                    .getExternalEndpointsForService(serviceName);
            return endpoints.toArray(new ServiceEndpoint[endpoints.size()]);
        } catch (final EndpointDirectoryException e) {
            this.logger.warning("Error while retrieving external endpoints for service " + serviceName, e);
            return new ServiceEndpoint[] {};
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
            this.logger.end();
        }
    }

    @Override
    public String getInstallRoot() {
        this.logger.call();

        return this.installerServices.getInstallationRoot();
    }

    @Override
    public Logger getLogger(String suffix, String resourceBundleName)
            throws MissingResourceException, JBIException {
        this.logger.start();

        String loggerName = this.getComponentName();

        // append the suffix to the logger Name
        if (suffix == null) {
            throw new IllegalArgumentException("suffix cannot be null");
        } else {
            if (suffix.length() > 0) {
                loggerName += "." + suffix;
            }
        }

        // get a new logger or retrieve it
        final Logger newLogger;
        try {
            newLogger = Logger.getLogger(COMPONENT_LOGGER_PREFIX + "." + loggerName, resourceBundleName);
        } catch (final IllegalArgumentException e) {
            // note: the message of e contains the names of conflicting resources bundles names
            throw new JBIException("Logger already exists for suffix " + loggerName, e);
        }

        this.logger.end();
        return newLogger;
    }

    @Override
    public MBeanNames getMBeanNames() {
        this.logger.call();

        return this.installerServices.getAdminService().getMBeanNames();
    }

    @Override
    public MBeanServer getMBeanServer() {
        this.logger.call();

        return this.installerServices.getAdminService().getMBeanServer();
    }

    @Override
    public InitialContext getNamingContext() {
        this.logger.call();

        return this.initialContext;
    }

    @Override
    public RouterService getRouter() {
        this.logger.call();

        return this.installerServices.getRouterService();
    }

    @Override
    public SecurityContext getSecurityContext() {
        return this.securityContext;
    }

    @Override
    public Object getTransactionManager() {
        this.logger.call();

        // this is not implemented (and never will, see PETALSDISTRIB-151)
        return null;
    }

    @Override
    public String getWorkspaceRoot() {
        this.logger.call();

        return this.installerServices.getWorkspaceRoot();
    }

    @Override
    public void registerExternalEndpoint(final ServiceEndpoint externalEndpoint) throws JBIException {
        this.logger.start();

        ParameterCheckHelper.isNullParameter(externalEndpoint, "externalEndpoint");

        // switch the classloader to the container one
        ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        try {
            this.logger.debug("Registering a new external endpoint in the registry");

            this.installerServices.getEndpointDirectory().registerExternalEndpoint(externalEndpoint,
                    getComponentName());
        } catch (final EndpointDirectoryException e) {
            throw new JBIException(e);
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
        }
        this.externalEndpoints.add(externalEndpoint);

        this.logger.end();
    }

    @Override
    public ServiceEndpoint resolveEndpointReference(DocumentFragment epr) {
        this.logger.start();

        ParameterCheckHelper.isNullParameter(epr, "epr");

        // switch the classloader to the container one
        ClassLoader componentClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
        try {
            return this.installerServices.getEndpointDirectory().resolveEndpointReference(epr);
        } catch (final EndpointDirectoryException e) {
            this.logger.warning("Can't resolve EPR", e);
            return null;
        } finally {
            Thread.currentThread().setContextClassLoader(componentClassLoader);
            this.logger.end();
        }
    }

    @Override
    public void setComponent(Component component) {
        this.jbiComponent = component;
    }

    @Override
    public void setSecurityContext(SecurityContext securityContext) {
        this.securityContext = securityContext;
    }

    @Override
    public boolean hasExchangesInDeliveryChannel() {
        return this.deliveryChannel != null && this.deliveryChannel.isOpened()
                && this.deliveryChannel.hasExchangesInQueue();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy