Package org.jboss.soa.esb.listeners.gateway

Source Code of org.jboss.soa.esb.listeners.gateway.HttpGatewayListener

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*
* (C) 2005-2006, JBoss Inc.
*/
package org.jboss.soa.esb.listeners.gateway;

import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLEncoder;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.management.ObjectName;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.LinkRef;
import javax.naming.NamingException;

import org.apache.catalina.LifecycleException;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardWrapper;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.deploy.SecurityCollection;
import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.startup.ContextConfig;
import org.apache.log4j.Logger;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.naming.Util;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.addressing.EPR;
import org.jboss.soa.esb.addressing.eprs.HTTPEpr;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.helpers.KeyValuePair;
import org.jboss.soa.esb.listeners.ListenerTagNames;
import org.jboss.soa.esb.listeners.gateway.http.HttpRequestWrapper;
import org.jboss.soa.esb.listeners.lifecycle.AbstractManagedLifecycle;
import org.jboss.soa.esb.listeners.lifecycle.ManagedLifecycleException;
import org.jboss.soa.esb.listeners.message.UncomposedMessageDeliveryAdapter;
import org.jboss.soa.esb.services.registry.RegistryException;
import org.jboss.soa.esb.services.registry.RegistryFactory;
import org.jboss.soa.esb.util.ClassUtil;

/**
* Tomcat Listener provides the functionality to pass the http request
* to ESB service .
* <p> This class will generate {@link org.apache.catalina.connector.Connector},
* {@link org.apache.catalina.core.StandardHost} and {@link org.apache.catalina.core.StandardContext}
* for user defined http port, host and context. These generated tomcat components will be
* attached to jboss embedded tomcat(aka jboss web). You can monitor and control these new generated
* components through jboss JMX console.  When this listener is stopped, these components will be
* destroyed automatically.
*
* <p>The different tomcat listener can be started in same port with different context.for example:
* <code> http://localhost:8765/jbossesb/servicecategory/servicename </code>
*
* <p>This class uses the {@link HttpMessageComposer}
* by default.
* @see org.jboss.soa.esb.listeners.gateway.HttpMessageComposer
* @see org.jboss.soa.esb.listeners.gateway.HttpDispatchServlet
* @author <a href="mailto:ema@redhat.com">Jim Ma</a>
* @deprecated
*/
public class HttpGatewayListener extends AbstractManagedLifecycle {

  private static Logger logger = Logger.getLogger(HttpGatewayListener.class);


  /**The tag used to read the host value from configuration */
  public static final String SERVER_HOST_TAG = "http_host";

  /**The tag used to read the port value from configuration */
  public static final String SERVER_PORT_TAG = "http_port";

  /**The tag used to read the context value from configuration */
  public static final String REQUEST_CONTEXT_TAG = "http_context";

  /**The tag used to read the dispatch servlet class name value from configuration */
  public static final String DISPATCH_SERVLET_CLASS = "dispatch_servlet";

  /**Allow http method config attribute name*/
    public static final String ALLOW_HTTP_METHOD = "allowHttpMethod";

    /**Auth method config attribute name */
    public static final String AUTH_METHOD = "authMethod";

    /**Security domain config attribute name */
    public static final String SECURITY_DOMAIN = "securityDomain";

    /**Security role config attribute name */
    public static final String SECURITY_ROLE = "securityRole";

  /**Http host value*/
  public String host = null;

  /**Http address value*/
  public String address = null;

  /**Http port value*/
  public String port = null;

  /** Default max threads */

  public String maxThreads = "5";

  /**listener contenxt */
  public String httpContext = null;

  /** Endpoint reference that presents this listener */
  private EPR endpointReference = null;

  /**Service category*/
  private String serviceCategory = null;

  /**Service name*/
  private String serviceName = null;

  /**The new created tomcat standard context, it reprents a web app*/
  private StandardContext ctx = null;

  /** The default servlet used to dispatch the http request to ESB service*/
  private String dispatchServletClassName = HttpDispatchServlet.class.getName();

  /** Protocol value */
  private Object protocol = "http";

  /** Imply if the port number is the jboss.web used, if yes , the new created context will be attched to jboss web Servlet engine */
  private boolean useJBossWebServletEngine = false;

  /**Constuct the TomcatGatewyListner
   * @param config The listener configuration
   * @throws ConfigurationException Exception during construction
   */
  @SuppressWarnings("unchecked")
  public HttpGatewayListener(ConfigTree config) throws ConfigurationException {
    super(config);
    host = config.getAttribute(SERVER_HOST_TAG);
    try {
         address = InetAddress.getByName(host).getHostAddress();
    }catch (Exception e) {
      throw new ConfigurationException("Invalid host configuration");
    }
    port = config.getAttribute(SERVER_PORT_TAG);
    httpContext = config.getAttribute(REQUEST_CONTEXT_TAG);
    serviceCategory = config.getAttribute(ListenerTagNames.TARGET_SERVICE_CATEGORY_TAG);
    serviceName = config.getAttribute(ListenerTagNames.TARGET_SERVICE_NAME_TAG);

    if (config.getAttribute(DISPATCH_SERVLET_CLASS) != null) {
      dispatchServletClassName = config.getAttribute(DISPATCH_SERVLET_CLASS);
    }

        boolean synchronous = !config.getAttribute("synchronous", "true").equalsIgnoreCase("false");
        if (!synchronous) {
      String asyncResponse = config.getAttribute("asyncResponse");
      if (asyncResponse != null) {
        if (ClassUtil.getResourceAsStream(asyncResponse, getClass()) == null) {
          throw new ConfigurationException("Asynchronous response resource file '" + asyncResponse
                  + "' not found on classpath.");
        }
      }
    }

        //validate allow http method configuration
        if (config.getAttribute(ALLOW_HTTP_METHOD) != null) {
          String allowMethods = config.getAttribute(ALLOW_HTTP_METHOD);
          String[] methods = allowMethods.split(",");
          List<String> standardMesthods = new ArrayList<String>();
          standardMesthods.add("GET");
          standardMesthods.add("POST");
          standardMesthods.add("DELETE");
          standardMesthods.add("PUT");
          standardMesthods.add("OPTIONS");
          standardMesthods.add("HEAD");
          standardMesthods.add("TRACE");

          for (String method : methods) {
            if (!standardMesthods.contains(method.toUpperCase())) {
              throw new ConfigurationException("Invalid allow http method configuration, please specify the specify method list with comma-separated(e.g. POST,GET,PUT,DELETE");
            }
          }
        }

    try {
      Set ports = HttpServerDelegate.getInstance().queryObjects("jboss.web:port="+ port+",type=Connector,*");
      if (ports.size() > 0) {
        //When this gateway stared on JBoss default port 8080 or 80, the configured host will be ignored
        Set contexts = HttpServerDelegate.getInstance().queryObjects("jboss.web:host=localhost"  + ",path=" + httpContext + ",*");
          if (contexts.size() > 0) {
          throw new ConfigurationException("There is already an http context named " + httpContext + ", choose another one");
        }
          logger.info("This http gateway listener [" + config.getAttribute(ListenerTagNames.NAME_TAG) "] will be started on JBoss default port " + port + " and the configured host will be ignored.");
        //the created context will be attached jboss.web domain
        useJBossWebServletEngine = true;
      } else {
        //if the port is not the jboss.web used, check if the http context name is duplicate
        Set contexts = HttpServerDelegate.getInstance().queryObjects(HttpServerDelegate.DOMAIN_NAME + ":host=" + HttpServerDelegate.defaultVHost  + ",path=" + httpContext + ",*");
        if (contexts.size() > 0) {
          throw new ConfigurationException("There is already an http context named " + httpContext + ", choose another one");
        }
      }
    } catch (Exception e) {
      throw new ConfigurationException(e);
    }

    //Check the http security configuration
    if (config.getAttribute(AUTH_METHOD) != null) {
      if (config.getAttribute(SECURITY_DOMAIN) == null) {
        throw new ConfigurationException("Security domain configuration for this context not found for http authentication method " + config.getAttribute(AUTH_METHOD));
      }

      if (config.getAttribute(SECURITY_ROLE) == null) {
        throw new ConfigurationException("Security role configuration for this context not found for http authentication method " + config.getAttribute(AUTH_METHOD));
      }
        }
  }

  /*
   * Start the Tomcat listner
   *
   * @see org.jboss.soa.esb.listeners.lifecycle.AbstractManagedLifecycle#doStart()
   */
  protected void doStart() throws ManagedLifecycleException {

    try {
      startHttpServer();
    } catch (Exception e) {
      throw new ManagedLifecycleException(
          "Failed to start Http gateway listener", e);
    }

    try {
      registerEndpoint();
    } catch (Throwable t) {
      logger.error("Unable to register service endpoint '" + endpointReference.getAddr().getAddress()
                    + "' for service '" + serviceCategory + ":" + serviceName + "'.  Stopping Http Listener Server...", t);
      try {
        stopHttpServer();
      } catch (Exception e) {
        throw new ManagedLifecycleException(
            "Failed to stop Http gateway listener", e);
      }
    }
  }

  /*
   * Stop the tomcat listener
   *
   * @see org.jboss.soa.esb.listeners.lifecycle.AbstractManagedLifecycle#doStop()
   */
  protected void doStop() throws ManagedLifecycleException {
    unregisterEndpoint();
    try {
      stopHttpServer();
    } catch (Exception e) {
      throw new ManagedLifecycleException(
          "Failed to stop Http gateway listener", e);
    }


  }

  /*
   * Initialize the tomcat listener
   *
   * @see org.jboss.soa.esb.listeners.lifecycle.AbstractManagedLifecycle#doInitialise()
   */
  protected void doInitialise() throws ManagedLifecycleException {

  }

  /*
   * Destory the tomcat listener
   *
   * @see org.jboss.soa.esb.listeners.lifecycle.AbstractManagedLifecycle#doDestroy()
   */
  protected void doDestroy() throws ManagedLifecycleException {
  }



  /**
   * Start the tomcat http server.It will check if it really needs to create
   * Tomcat connector and host. Then add these new tomcat component to tomcat Engine
   * tree through JMX server.
   * @throws Exception For error during start tomcat context
   */
  @SuppressWarnings("unchecked")
  protected void startHttpServer() throws Exception {

    ctx = new StandardContext();
    final URL[] urls = new URL[]{};
    URLClassLoader urlClassLoader = AccessController.doPrivileged(new PrivilegedAction<URLClassLoader>() {
      public URLClassLoader run() {
        return new URLClassLoader(urls, getClass().getClassLoader());
      }
    });

    WebappLoader loader = new WebappLoader(urlClassLoader);
    ctx.setLoader(loader);
    ContextConfig ctxCfg = new ContextConfig();
    ctx.addLifecycleListener(ctxCfg);

    ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML");
    ctx.setPath(httpContext);
    ctx.setDocBase(".");


    ClassLoader oldloader = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(urlClassLoader);
    initWebappDefaults(ctx);
    Thread.currentThread().setContextClassLoader(oldloader);
    String encodedAddr = URLEncoder.encode("/" + address);
    String connectorName = HttpServerDelegate.DOMAIN_NAME + ":address=" + encodedAddr + ",port=" + port + ",type=Connector";
    if (!useJBossWebServletEngine) {
      //Create default Tomcat standard vHost "localhost"
      HttpServerDelegate.getInstance().createHost(HttpServerDelegate.defaultVHost);

      List<KeyValuePair> properties = getConfig().childPropertyList();
      if (getConfig().getAttribute(ListenerTagNames.MAX_THREADS_TAG) != null) {
        maxThreads = getConfig().getAttribute(ListenerTagNames.MAX_THREADS_TAG);
      }
      properties.add(new KeyValuePair("maxThreads", maxThreads));

      HttpServerDelegate.getInstance().createConnector(address, port, properties);
      HttpServerDelegate.getInstance().addContext(HttpServerDelegate.defaultVHost, ctx);
    } else {
      //add it to jboss.web servlet engine
      connectorName = "jboss.web:port=" + port + ",type=Connector,*";
      HttpServerDelegate.getInstance().addContext(new ObjectName("jboss.web:host=localhost,type=Host"), ctx);
    }

    Set connectors = HttpServerDelegate.getInstance().queryObjects(connectorName);
    if (connectors.isEmpty()) {
      throw new javax.management.InstanceNotFoundException("ObjectName: "+ connectorName + " Not found");
    }
    ObjectName obj = (ObjectName)connectors.iterator().next();
    try {
          protocol = MBeanServerLocator.locateJBoss().getAttribute(obj, "scheme");
    } catch (Exception e) {
            //do nothing and use default http
      protocol = "http";
    }

  }

    /**Register this endpoint
     * @throws ConfigurationException For configuration error
     * @throws RegistryException For registry error when register this EPR
     */
    private void registerEndpoint() throws ConfigurationException, RegistryException {
      try {
      endpointReference = new HTTPEpr(new URI(protocol + "://"+ address + ":" + port + this.httpContext));
      endpointReference.getAddr().addExtension("is-gateway", "true");
    } catch (Exception e) {
      throw new RegistryException("Tomcat gateway listener registration failed", e);
    }
      String serviceDescription = getConfig().getAttribute(ListenerTagNames.SERVICE_DESCRIPTION_TAG);
        RegistryFactory.getRegistry().registerEPR(serviceCategory, serviceName, serviceDescription,
                endpointReference, endpointReference.getAddr().getAddress());
    }

    /**Unregister this endpoint
     */
    private void unregisterEndpoint() {
        try {
            RegistryFactory.getRegistry().unRegisterEPR(serviceCategory, serviceName, endpointReference);
        } catch (Throwable t) {
            logger.error("Unable to unregister service endpoint '" + endpointReference.getAddr().getAddress()
                    + "' for service '" + serviceCategory + ":" + serviceName + "'.", t);
        }
    }

  /**Stop tomcat server. It will destroy the generated tomcat connector or host .
   * Before do it , it will check if the reference count for it is zero .When there
   * is no tomcat listener uses the generated host or connector, it will destroy it
   * @throws Exception For errors during stop tomcat connector or host
   */
    @SuppressWarnings("unchecked")
  public void stopHttpServer() throws Exception {
    //Destroy the created context
        if (!useJBossWebServletEngine) {
           HttpServerDelegate.getInstance().destroyContext(HttpServerDelegate.defaultVHost, address, port, httpContext);
        } else {
         Set<ObjectName> contexts = HttpServerDelegate.getInstance().queryObjects("jboss.web:j2eeType=WebModule,name=//localhost"  + httpContext + ",*");
         for (ObjectName obName : contexts) {
            HttpServerDelegate.getInstance().destroyContext(obName);
         }
      }
    }

  /**Get the uncomposed message delivery dapater
   * @return uncomposed message delivery adapter
   * @throws ConfigurationException For configuation error
   */
  protected UncomposedMessageDeliveryAdapter createDeliveryAdapter()
      throws ConfigurationException {
    return UncomposedMessageDeliveryAdapter.getGatewayDeliveryAdapter(
        getConfig(),
        new HttpMessageComposer<HttpRequestWrapper>());
  }

  /**Initialize the StandardContext.By default it will uses
   * {@link HttpDispatchServlet} as default servlet mapping
   * @param ctx Created tomcat standard context
   * @throws Exception For errors during initialization
   */
  protected void initWebappDefaults(StandardContext ctx) throws Exception {
    if (isHttpAuthConfiured()) {
     
      InitialContext iniCtx = new InitialContext();
         
      Context envCtx;
          try {
            envCtx = (Context) iniCtx.lookup("java:comp/env");
          } catch (NamingException e) {
            envCtx = (Context) iniCtx.lookup("java:comp");
            envCtx = envCtx.createSubcontext("env");
          }
         
          String securityDomain = getConfig().getAttribute(SECURITY_DOMAIN);
          Util.bind(envCtx, "security/securityMgr", new LinkRef(securityDomain));
          Util.bind(envCtx, "security/realmMapping", new LinkRef(securityDomain));
          Util.bind(envCtx, "security/security-domain", new LinkRef(securityDomain));
          Util.bind(envCtx, "security/subject", new LinkRef(securityDomain));
    }
   
      StandardWrapper sw = (StandardWrapper) ctx.createWrapper();
   
    sw.setServletClass(dispatchServletClassName);
    sw.setName("default");
    ctx.addChild(sw);
    ctx.getServletContext().setAttribute("config", this.getConfig());

    sw.addInitParameter("listings", "false");
    sw.setLoadOnStartup(1);

    try {
      sw.start();
    } catch (LifecycleException e) {
      logger.error("Unexpected error when start the default servlet");
      throw e;
    }
    ctx.addServletMapping("/", "default");
   
   
    //Add security support
    if (isHttpAuthConfiured()) {
      String securityRole = this.getConfig().getAttribute(SECURITY_ROLE);
      SecurityConstraint constraint = new SecurityConstraint();
      constraint.addAuthRole(securityRole);
      SecurityCollection collection = new SecurityCollection("all");
      collection.addPattern("/*");
      constraint.addCollection(collection);
      ctx.addConstraint(constraint);

      ctx.addSecurityRole(securityRole);

      String authMethod = this.getConfig().getAttribute(AUTH_METHOD);
      LoginConfig config = new LoginConfig(authMethod, securityRole,
          null, null);
      ctx.setLoginConfig(config);
    }
  }
 
  private boolean isHttpAuthConfiured() {
    if (getConfig().getAttribute(AUTH_METHOD) != null) {
      return true;
    }
    return false;
  }

}
TOP

Related Classes of org.jboss.soa.esb.listeners.gateway.HttpGatewayListener

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.