Package org.apache.openejb.server.webservices

Source Code of org.apache.openejb.server.webservices.WsService

/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.openejb.server.webservices;

import org.apache.openejb.BeanContext;
import org.apache.openejb.Injection;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.Assembler;
import org.apache.openejb.assembler.classic.DeploymentListener;
import org.apache.openejb.assembler.classic.EjbJarInfo;
import org.apache.openejb.assembler.classic.EnterpriseBeanInfo;
import org.apache.openejb.assembler.classic.PortInfo;
import org.apache.openejb.assembler.classic.ServletInfo;
import org.apache.openejb.assembler.classic.SingletonBeanInfo;
import org.apache.openejb.assembler.classic.StatelessBeanInfo;
import org.apache.openejb.assembler.classic.WebAppInfo;
import org.apache.openejb.assembler.classic.WsBuilder;
import org.apache.openejb.core.CoreContainerSystem;
import org.apache.openejb.core.WebContext;
import org.apache.openejb.core.webservices.PortAddressRegistry;
import org.apache.openejb.core.webservices.PortAddressRegistryImpl;
import org.apache.openejb.core.webservices.PortData;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.server.SelfManaging;
import org.apache.openejb.server.ServerService;
import org.apache.openejb.server.ServiceException;
import org.apache.openejb.server.httpd.HttpListener;
import org.apache.openejb.server.httpd.HttpListenerRegistry;
import org.apache.openejb.server.httpd.util.HttpUtil;
import org.apache.openejb.spi.ContainerSystem;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.StringTemplate;

import javax.naming.Context;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;

public abstract class WsService implements ServerService, SelfManaging, DeploymentListener {
    public static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_WS, WsService.class);
    public static final String WS_ADDRESS_FORMAT = "openejb.wsAddress.format";
    public static final String WS_FORCE_ADDRESS = "openejb.webservice.deployment.address";
    private static final boolean OLD_WEBSERVICE_DEPLOYMENT = SystemInstance.get().getOptions().get("openejb.webservice.old-deployment", false);
    private StringTemplate wsAddressTemplate;

    private PortAddressRegistry portAddressRegistry;
    private CoreContainerSystem containerSystem;
    private Assembler assembler;
    private WsRegistry wsRegistry;
    private String realmName;
    private String transportGuarantee;
    private String authMethod;
    private String virtualHost;
    private final Set<AppInfo> deployedApplications = new HashSet<AppInfo>();
    private final Set<WebAppInfo> deployedWebApps = new HashSet<WebAppInfo>();
    private final Map<String,String> ejbLocations = new TreeMap<String,String>();
    private final Map<String,String> ejbAddresses = new TreeMap<String,String>();
    private final Map<String,String> servletAddresses = new TreeMap<String,String>();

    public WsService() {
        String format = SystemInstance.get().getOptions().get(WS_ADDRESS_FORMAT, "/{ejbDeploymentId}");
        this.wsAddressTemplate = new StringTemplate(format);
    }

    public StringTemplate getWsAddressTemplate() {
        return wsAddressTemplate;
    }

    public void setWsAddressTemplate(StringTemplate wsAddressTemplate) {
        this.wsAddressTemplate = wsAddressTemplate;
    }

    public String getRealmName() {
        return realmName;
    }

    public void setRealmName(String realmName) {
        this.realmName = realmName;
    }

    public String getTransportGuarantee() {
        return transportGuarantee;
    }

    public void setTransportGuarantee(String transportGuarantee) {
        this.transportGuarantee = transportGuarantee;
    }

    public String getAuthMethod() {
        return authMethod;
    }

    public void setAuthMethod(String authMethod) {
        this.authMethod = authMethod;
    }

    public String getVirtualHost() {
        return virtualHost;
    }

    public void setVirtualHost(String virtualHost) {
        this.virtualHost = virtualHost;
    }

    public String getIP() {
        return "n/a";
    }

    public int getPort() {
        return -1;
    }

    public void init(Properties props) throws Exception {
        if (props == null) return;

        String format = props.getProperty(WS_ADDRESS_FORMAT);
        if (format != null) {
            this.wsAddressTemplate = new StringTemplate(format);
        }

        realmName = props.getProperty("realmName");
        transportGuarantee = props.getProperty("transportGuarantee");
        authMethod = props.getProperty("authMethod");
        virtualHost = props.getProperty("virtualHost");
    }

    public void start() throws ServiceException {
        wsRegistry = SystemInstance.get().getComponent(WsRegistry.class);
        if (wsRegistry == null && SystemInstance.get().getComponent(HttpListenerRegistry.class) != null) {
            wsRegistry = new OpenEJBHttpWsRegistry();
        }

        if (portAddressRegistry == null) {
            portAddressRegistry = new PortAddressRegistryImpl();
            SystemInstance.get().setComponent(PortAddressRegistry.class, portAddressRegistry);
        }
        containerSystem = (CoreContainerSystem) SystemInstance.get().getComponent(ContainerSystem.class);
        portAddressRegistry = SystemInstance.get().getComponent(PortAddressRegistry.class);
        assembler = SystemInstance.get().getComponent(Assembler.class);
        SystemInstance.get().setComponent(WsService.class, this);
        if (assembler != null) {
            assembler.addDeploymentListener(this);
            for (AppInfo appInfo : assembler.getDeployedApplications()) {
                afterApplicationCreated(appInfo);
            }
        }
    }

    public void stop() throws ServiceException {
        if (assembler != null) {
            assembler.removeDeploymentListener(this);
            for (AppInfo appInfo : new ArrayList<AppInfo>(deployedApplications)) {
                beforeApplicationDestroyed(appInfo);
            }
            assembler = null;
            if (SystemInstance.get().getComponent(WsService.class) == this) {
                SystemInstance.get().removeComponent(WsService.class);
            }
        }
    }

    protected abstract HttpListener createEjbWsContainer(URL moduleBaseUrl, PortData port, BeanContext beanContext) throws Exception;

    protected abstract void destroyEjbWsContainer(String deploymentId);

    protected abstract HttpListener createPojoWsContainer(URL moduleBaseUrl, PortData port, String serviceId, Class target, Context context, String contextRoot) throws Exception;

    protected abstract void destroyPojoWsContainer(String serviceId);

    public void afterApplicationCreated(AppInfo appInfo) {
        if (deployedApplications.add(appInfo)) {
            Map<String, String> webContextByEjb = new HashMap<String, String>();
            for (WebAppInfo webApp : appInfo.webApps) {
                for (String ejb : webApp.ejbWebServices) {
                    webContextByEjb.put(ejb, webApp.contextRoot);
                }
            }

            Map<String,String> contextData = new HashMap<String,String>();
            contextData.put("appId", appInfo.path);
            for (EjbJarInfo ejbJar : appInfo.ejbJars) {
                Map<String, PortInfo> ports = new TreeMap<String,PortInfo>();
                for (PortInfo port : ejbJar.portInfos) {
                    ports.put(port.serviceLink, port);
                }

                URL moduleBaseUrl = null;
                if (ejbJar.path != null) {
                    try {
                        moduleBaseUrl = new File(ejbJar.path).toURI().toURL();
                    } catch (MalformedURLException e) {
                        logger.error("Invalid ejb jar location " + ejbJar.path, e);
                    }
                }

                StringTemplate deploymentIdTemplate = this.wsAddressTemplate;
                if (ejbJar.properties.containsKey(WS_ADDRESS_FORMAT)){
                    String format = ejbJar.properties.getProperty(WS_ADDRESS_FORMAT);
                    logger.info("Using "+ WS_ADDRESS_FORMAT +" '"+format+"'");
                    deploymentIdTemplate = new StringTemplate(format);
                }
                contextData.put("ejbJarId", ejbJar.moduleName);

                for (EnterpriseBeanInfo bean : ejbJar.enterpriseBeans) {
                    if (bean instanceof StatelessBeanInfo || bean instanceof SingletonBeanInfo) {

                        BeanContext beanContext = containerSystem.getBeanContext(bean.ejbDeploymentId);
                        if (beanContext == null) continue;

                        PortInfo portInfo = ports.get(bean.ejbName);
                        if (portInfo == null) continue;

                        try {
                            PortData port = WsBuilder.toPortData(portInfo, beanContext.getInjections(), moduleBaseUrl, beanContext.getClassLoader());

                            HttpListener container = createEjbWsContainer(moduleBaseUrl, port, beanContext);

                            // generate a location if one was not assigned
                            String location = port.getLocation();
                            if (location == null) {
                                location = autoAssignWsLocation(bean, port, contextData, deploymentIdTemplate);
                            }
                            if (!location.startsWith("/")) location = "/" + location;
                            ejbLocations.put(bean.ejbDeploymentId, location);

                            ClassLoader classLoader = beanContext.getClassLoader();
                            if (wsRegistry != null) {
                                String auth = authMethod;
                                String realm = realmName;
                                String transport = transportGuarantee;

                                if ("BASIC".equals(portInfo.authMethod) || "DIGEST".equals(portInfo.authMethod) || "CLIENT-CERT".equals(portInfo.authMethod)) {
                                    auth = portInfo.authMethod;
                                    realm = portInfo.realmName;
                                    transport = portInfo.transportGuarantee;
                                }

                                String context = webContextByEjb.get(bean.ejbClass);
                                if (context == null && !OLD_WEBSERVICE_DEPLOYMENT) {
                                    context = ejbJar.moduleName;
                                }
                                List<String> addresses = wsRegistry.addWsContainer(context, location, container, virtualHost, realm, transport, auth, classLoader);

                                // one of the registered addresses to be the canonical address
                                String address = HttpUtil.selectSingleAddress(addresses);

                                if (address != null) {
                                    // register wsdl location
                                    portAddressRegistry.addPort(portInfo.serviceId, portInfo.wsdlService, portInfo.portId, portInfo.wsdlPort, portInfo.seiInterfaceName, address);
                                    logger.info("Webservice(wsdl=" + address + ", qname=" + port.getWsdlService() + ") --> Ejb(id=" + portInfo.portId + ")");
                                    ejbAddresses.put(bean.ejbDeploymentId, address);
                                }
                            }
                        } catch (Throwable e) {
                            logger.error("Error deploying JAX-WS Web Service for EJB " + beanContext.getDeploymentID(), e);
                        }
                    }
                }
            }
            for (WebAppInfo webApp : appInfo.webApps) {
                afterApplicationCreated(webApp);
            }
        }
    }

    public void afterApplicationCreated(WebAppInfo webApp) {
        WebContext webContext = containerSystem.getWebContext(webApp.moduleId);
        if (webContext == null) return;

        // if already deployed skip this webapp
        if (!deployedWebApps.add(webApp)) return;

        Map<String,PortInfo> ports = new TreeMap<String,PortInfo>();
        for (PortInfo port : webApp.portInfos) {
            ports.put(port.serviceLink, port);
        }

        URL moduleBaseUrl = null;
        try {
            moduleBaseUrl = new File(webApp.path).toURI().toURL();
        } catch (MalformedURLException e) {
            logger.error("Invalid ejb jar location " + webApp.path, e);
        }

        for (ServletInfo servlet : webApp.servlets) {
            PortInfo portInfo = ports.get(servlet.servletName);
            if (portInfo == null) continue;

            try {
                ClassLoader classLoader = webContext.getClassLoader();
                Collection<Injection> injections = webContext.getInjections();
                Context context = webContext.getJndiEnc();
                Class target = classLoader.loadClass(servlet.servletClass);

                PortData port = WsBuilder.toPortData(portInfo, injections, moduleBaseUrl, classLoader);

                HttpListener container = createPojoWsContainer(moduleBaseUrl, port, portInfo.serviceLink, target, context, webApp.contextRoot);

                if (wsRegistry != null) {
                    // give servlet a reference to the webservice container
                    List<String> addresses = wsRegistry.setWsContainer(virtualHost, webApp.contextRoot, servlet.servletName, container);

                    // one of the registered addresses to be the connonical address
                    String address = HttpUtil.selectSingleAddress(addresses);

                    // add address to global registry
                    portAddressRegistry.addPort(portInfo.serviceId, portInfo.wsdlService, portInfo.portId, portInfo.wsdlPort, portInfo.seiInterfaceName, address);
                    logger.info("Webservice(wsdl=" + address + ", qname=" + port.getWsdlService() + ") --> Pojo(id=" + portInfo.portId + ")");
                    servletAddresses.put(webApp.moduleId + "." + servlet.servletName, address);
                }
            } catch (Throwable e) {
                logger.error("Error deploying CXF webservice for servlet " + portInfo.serviceLink, e);
            }
        }
    }

    public void beforeApplicationDestroyed(AppInfo appInfo) {
        if (deployedApplications.remove(appInfo)) {
            for (EjbJarInfo ejbJar : appInfo.ejbJars) {
                Map<String,PortInfo> ports = new TreeMap<String,PortInfo>();
                for (PortInfo port : ejbJar.portInfos) {
                    ports.put(port.serviceLink, port);
                }

                for (EnterpriseBeanInfo enterpriseBean : ejbJar.enterpriseBeans) {
                    if (enterpriseBean instanceof StatelessBeanInfo || enterpriseBean instanceof SingletonBeanInfo) {

                        PortInfo portInfo = ports.get(enterpriseBean.ejbName);
                        if (portInfo == null) continue;

                        // remove wsdl addresses from global registry
                        String address = ejbAddresses.remove(enterpriseBean.ejbDeploymentId);
                        if (address != null) {
                            portAddressRegistry.removePort(portInfo.serviceId, portInfo.wsdlService, portInfo.portId);
                        }

                        // remove container from web server
                        String location = ejbLocations.get(enterpriseBean.ejbDeploymentId);
                        if (this.wsRegistry != null && location != null) {
                            this.wsRegistry.removeWsContainer(location);
                        }

                        // destroy webservice container
                        destroyEjbWsContainer(enterpriseBean.ejbDeploymentId);
                    }
                }
            }
            for (WebAppInfo webApp : appInfo.webApps) {
                deployedWebApps.remove(webApp);

                Map<String,PortInfo> ports = new TreeMap<String,PortInfo>();
                for (PortInfo port : webApp.portInfos) {
                    ports.put(port.serviceLink, port);
                }

                for (ServletInfo servlet : webApp.servlets) {
                    PortInfo portInfo = ports.get(servlet.servletClass);
                    if (portInfo == null) continue;

                    // remove wsdl addresses from global registry
                    String address = servletAddresses.remove(webApp.moduleId + "." + servlet.servletName);
                    if (address != null) {
                        portAddressRegistry.removePort(portInfo.serviceId, portInfo.wsdlService, portInfo.portId);
                    }

                    // clear servlet's reference to the webservice container
                    if (this.wsRegistry != null) {
                        this.wsRegistry.clearWsContainer(virtualHost, webApp.contextRoot, servlet.servletName);
                    }

                    // destroy webservice container
                    destroyPojoWsContainer(portInfo.serviceLink);
                }
            }
        }
    }

    private String autoAssignWsLocation(EnterpriseBeanInfo bean, PortData port, Map<String, String> contextData, StringTemplate template) {
        if (bean.properties.containsKey(WS_FORCE_ADDRESS)) {
            return bean.properties.getProperty(WS_FORCE_ADDRESS);
        }
        contextData.put("ejbDeploymentId", bean.ejbDeploymentId);
        contextData.put("ejbType", getEjbType(bean.type));
        contextData.put("ejbClass", bean.ejbClass);
        contextData.put("ejbClass.simpleName", bean.ejbClass.substring(bean.ejbClass.lastIndexOf('.') + 1));
        contextData.put("ejbName", bean.ejbName);
        contextData.put("portComponentName", port.getPortName().getLocalPart());
        contextData.put("wsdlPort", port.getWsdlPort().getLocalPart());
        contextData.put("wsdlService", port.getWsdlService().getLocalPart());
        return template.apply(contextData);
    }

    public static String getEjbType(int type) {
        if (type == EnterpriseBeanInfo.STATEFUL) {
            return "StatefulBean";
        } else if (type == EnterpriseBeanInfo.STATELESS) {
            return "StatelessBean";
        } else if (type == EnterpriseBeanInfo.SINGLETON) {
            return "SingletonBean";
        } else if (type == EnterpriseBeanInfo.MANAGED) {
            return "ManagedBean";
        } else if (type == EnterpriseBeanInfo.MESSAGE) {
            return "MessageDrivenBean";
        } else if (type == EnterpriseBeanInfo.ENTITY) {
            return "StatefulBean";
        } else {
            return "UnknownBean";
        }
    }

    public void service(InputStream in, OutputStream out) throws ServiceException, IOException {
        throw new UnsupportedOperationException("CxfService cannot be invoked directly");
    }

    public void service(Socket socket) throws ServiceException, IOException {
        throw new UnsupportedOperationException("CxfService cannot be invoked directly");
    }
}
TOP

Related Classes of org.apache.openejb.server.webservices.WsService

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