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

org.jibx.ws.http.servlet.PathBasedServiceMapper Maven / Gradle / Ivy

/*
 * Copyright (c) 2008, Sosnoski Software Associates Limited. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 * following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
 * disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 * following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of
 * JiBX nor the names of its contributors may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.jibx.ws.http.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jibx.runtime.BindingDirectory;
import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.ws.WsException;
import org.jibx.ws.protocol.ProtocolDirectory;
import org.jibx.ws.server.Service;
import org.jibx.ws.server.ServiceDefinition;
import org.jibx.ws.server.ServiceFactory;
import org.jibx.ws.server.ServicePool;

/**
 * Maps a servlet request to a {@link Service} instance, based on the servlet path. This attempts to match the request
 * to a {@link ServiceDefinition} defined in the init-params for this servlet. The request is matched using:
 * 
    *
  1. The extra path information between the servlet path and query string, or
  2. *
  3. If no extra path information present, the servlet path.
  4. *
* * @author Dennis M. Sosnoski */ public final class PathBasedServiceMapper implements ServiceMapper { private static final long serialVersionUID = -4161361963133295719L; private static final Log logger = LogFactory.getLog(PathBasedServiceMapper.class); /** Singleton map from context+servlet names to service definition maps. */ private static HashMap s_servletMap = new HashMap(); /** Map from path to {@link ServiceDefinition} for the services. */ private Map m_serviceDefnMap; /** * Constructs the mapper. When the first instance of a servlet with a particular name within a particular context is * initialized it reads the service definitions associated with that name, which are then used to create the actual * service objects as needed to process received requests. * * @param servlet the servlet to create the mapper for * @throws UnavailableException on any initialization error that causes the servlet to be unavailable */ PathBasedServiceMapper(HttpServlet servlet) throws UnavailableException { // build key string from combination of context and servlet name String sname = servlet.getServletName(); if (sname.equals(servlet.getClass().getName())) { sname = ""; } String key = servlet.getServletContext().getServletContextName(); if (key == null) { key = ""; } key += "|" + sname; // check for existing service definition map synchronized (s_servletMap) { m_serviceDefnMap = (HashMap) s_servletMap.get(key); if (m_serviceDefnMap == null) { // need a new one, create it now with all service definitions m_serviceDefnMap = createServiceDefinitions(servlet); s_servletMap.put(key, m_serviceDefnMap); } } } /** * Initialize service configuration information. This uses the servlet initialization parameters as the list of * service definitions to be supported, reading and validating the actual service configurations from XML definition * files. * * @return hash map from paths to service definitions * @param servlet the servlet to create the mapper for * @throws UnavailableException if any error occurs that stops the mapper from being created */ private Map createServiceDefinitions(HttpServlet servlet) throws UnavailableException { // set up JiBX unmarshalling for service configuration files IUnmarshallingContext ctx = null; try { IBindingFactory factory = BindingDirectory.getFactory(ServiceDefinition.class); ctx = factory.createUnmarshallingContext(); } catch (JiBXException e) { logger.error("Unable to initialize unmarshalling", e); throw new UnavailableException("Unable to initialize unmarshalling. \n" + getErrorDetails(e)); } // read and validate service definitions String path = null; String file = null; try { // loop through all initialization parameter pairs HashMap map = new HashMap(); Enumeration pnum = servlet.getInitParameterNames(); ServletContext serv = servlet.getServletContext(); while (pnum.hasMoreElements()) { // parameter name is path and value is service definition file path = (String) pnum.nextElement(); file = "/WEB-INF/" + servlet.getInitParameter(path); InputStream is = null; try { is = serv.getResourceAsStream(file); if (is == null) { logger.error("Service definition not found for service " + path + " at " + file); throw new UnavailableException("Service definition not found for service " + path + " at " + file + ". Check configuration of servlet " + servlet.getServletName() + " in WEB-INF/web.xml."); } ServiceDefinition sdef = (ServiceDefinition) ctx.unmarshalDocument(is, null); if (!path.startsWith("/")) { path = "/" + path; } map.put(path, sdef); } finally { if (is != null) { try { is.close(); } catch (IOException ignore) { } } } } // return map with all services entered return map; } catch (JiBXException e) { logger.error("Error reading service definition " + file + " for service " + path, e); throw new UnavailableException("Error reading service definition " + file + " for service " + path + ".\n" + getErrorDetails(e)); } } /** * Get service definition for servlet request. This attempts to match the request to a service definition defined in * the init-params for this servlet. The request is matched using: *
    *
  1. The extra path information between the servlet path and query string, or
  2. *
  3. If no extra path information present, the servlet path.
  4. *
* * @param req servlet request * @return definition, or null if no service definition found for path */ private ServiceDefinition getServiceDefinition(HttpServletRequest req) { String servicePath = req.getPathInfo(); if (servicePath == null) { servicePath = req.getServletPath(); } ServiceDefinition defn = (ServiceDefinition) m_serviceDefnMap.get(servicePath); if (defn == null && logger.isWarnEnabled()) { logger.warn("No service definition for service path '" + servicePath + "' based on " + (req.getPathInfo() != null ? "path info" : "servlet path") + " of request '" + req.getRequestURI() + "'"); } return defn; } /** {@inheritDoc} */ public Service getServiceInstance(HttpServletRequest req) throws WsException { ServiceDefinition sdef = getServiceDefinition(req); if (sdef == null) { return null; } ServiceFactory serviceFactory = ProtocolDirectory.getProtocol(sdef.getProtocolName()).getServiceFactory(); return ServicePool.getInstance(serviceFactory, sdef); } /** * Creates a string containing the exception message and the message of the root cause, if one exists. * * @param e exception * @return error details string */ private String getErrorDetails(JiBXException e) { String errorDetails = "Error details: " + e.getMessage(); if (e.getRootCause() != null) { errorDetails += "\nRoot cause: " + e.getRootCause().getMessage(); logger.error("Root cause: ", e.getRootCause()); } return errorDetails; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy