You are viewing a plain text version of this content. The canonical link for it is here.
Posted to soap-dev@ws.apache.org by sa...@locus.apache.org on 2000/08/08 08:32:06 UTC

cvs commit: xml-soap/java/src/org/apache/soap/server/http RPCRouterServlet.java

sanjiva     00/08/07 23:32:05

  Added:       java/src/org/apache/soap/server/http RPCRouterServlet.java
  Log:
  servlet version of RPC Router. A detailed note is being posted to
  the soap-dev list .. see there for more.
  Submitted by:	Steven J. McDowall, "Noor Zaman" <no...@instill.com>
  Reviewed by:	Sanjiva Weerawarana
  
  Revision  Changes    Path
  1.1                  xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java
  
  Index: RPCRouterServlet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. 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.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "SOAP" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
   * ITS 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.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2000, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.soap.server.http;
  
  import java.io.*;
  import java.util.*;
  import java.lang.reflect.*;
  import javax.servlet.* ;
  import javax.servlet.http.* ;
  import org.w3c.dom.* ;
  import org.apache.soap.*;
  import org.apache.soap.rpc.*;
  import org.apache.soap.server.*;
  import org.apache.soap.encoding.*;
  import org.apache.soap.util.* ;
  import org.apache.soap.util.xml.* ;
  
  
  /**
   * @author Sanjiva Weerawarana <sa...@watson.ibm.com>
   * @author Mat
   * @author Steven McDowall <sj...@aptest.com>
   */
  
  public class RPCRouterServlet extends HttpServlet {
    private final static String RPC_ROUTER_ID = "rpcRouter";
    private final static String SERVICE_MANAGER_ID = "serviceManager";
    private static final String SCRIPT_CLASS = "com.ibm.bsf.BSFManager";
    private static final String SCRIPT_INVOKER = 
      "org.apache.soap.server.InvokeBSF";
  
    public void init () throws ServletException {
      ServletConfig config = getServletConfig ();
      ServletContext context = config.getServletContext ();
  
      // create the service manager if necessary. NOTE: This approach
      // will not work if this servlet is put in a webapp that is
      // marked distributed .. the servlet context is unique only
      // per JVM. In that case we'll have to use an external database
      // to store the global stuff.
      synchronized (context) {
        Object o = context.getAttribute (RPC_ROUTER_ID);
        if (o == null) { // isn't this always true?? (is init() called once?)
  	RPCRouter rpcRouter = new RPCRouter ();
  	ServiceManager serviceManager = new ServiceManager ();
  	rpcRouter.setServiceManager (serviceManager);
  	context.setAttribute (RPC_ROUTER_ID, rpcRouter);
  	context.setAttribute (SERVICE_MANAGER_ID, serviceManager);
        }
      }
    }
  
    public void doPost (HttpServletRequest req, HttpServletResponse res) 
         throws ServletException, IOException {
      // locate the rpcrouter and service manager
      ServletConfig config = getServletConfig ();
      ServletContext context = config.getServletContext ();
      HttpSession session = req.getSession ();
      RPCRouter rpcRouter = (RPCRouter) context.getAttribute (RPC_ROUTER_ID);
      ServiceManager serviceManager = 
        (ServiceManager) context.getAttribute (SERVICE_MANAGER_ID);
  
      Response resp = null;
      String targetID = null;
  
      String contentType = req.getContentType ();
      int contentLength = req.getContentLength ();
  
      // set the outgoing content type and pick up the writer to write
      // to *after* that
      res.setContentType (Constants.HEADERVAL_CONTENT_TYPE_UTF8);
      PrintWriter out = res.getWriter ();
      
      Call call = null;
      
      if ((contentType == null) ||
  	!contentType.equals (Constants.HEADERVAL_CONTENT_TYPE)) {
        res.sendError (res.SC_BAD_REQUEST, "Content type must be: '" + 
  		     Constants.HEADERVAL_CONTENT_TYPE + "'.");
        return;
      } else if (contentLength < 0) {
        res.sendError (res.SC_BAD_REQUEST, "Content length must be specified.");
        return;
      }
      
      try {
        System.err.println (">>(" + new Date() + ") Processing SOAP request...");
  
        Reader requestReader = req.getReader ();
        char[] payload       = new char[contentLength];
        int    offset        = 0;
  
        while (offset < contentLength) {
  	offset += requestReader.read (payload, offset, contentLength - offset);
        }
  
        // Parse the incoming request stream.
        org.apache.soap.util.xml.XMLParserLiaison xpl = 
  	new XercesParserLiaison ();
        Document callDoc = xpl.read("- SOAP HTTP RPC Call Envelope -",
  				  new CharArrayReader (payload));
        Element payloadEl = null;
        if (callDoc == null) {
  	throw new SOAPException(Constants.FAULT_CODE_PROTOCOL,
  				"DOM parsing error: " + payload);
        }
        
        // extract the call
        try {
  	payloadEl = callDoc.getDocumentElement ();
  	Envelope callEnv = Envelope.unmarshall (payloadEl);
  	call = rpcRouter.extractCallFromEnvelope (callEnv);
  	targetID = call.getTargetObjectURI ();
        } catch (IllegalArgumentException e) {
  	String msg = e.getMessage ();
  	String faultCode =
  	  (msg != null && msg.equals (Constants.ERR_MSG_VERSION_MISMATCH))
  	  ? Constants.FAULT_CODE_VERSION_MISMATCH
  	  : Constants.FAULT_CODE_CLIENT;
  	throw new SOAPException (faultCode, msg, e);
        }
        
        // call on a valid method name?
        if (!rpcRouter.validCall (call)) {
  	throw new SOAPException (Constants.FAULT_CODE_SERVER,
  				 "Method '" + call.getMethodName () + 
  				 "' is not supported.");
        }
        
        // lifecycle stuff of target object: what's the class to instantiate?
        DeploymentDescriptor dd = serviceManager.query (targetID);
        int scope = dd.getScope ();
        byte providerType = dd.getProviderType ();
        String className;
        Object targetObject = null;
        if (providerType == DeploymentDescriptor.PROVIDER_JAVA) {
  	className = dd.getProviderClass ();
        } else {
  	// for scripts, we need a new BSF manager basically
  	className = SCRIPT_CLASS;
        }
        
        // determine the scope and lock object to use to manage the lifecycle
        // of the service providing object
        Object scopeLock = null;
        if (scope == DeploymentDescriptor.SCOPE_REQUEST) {
  	scopeLock = this; // no need to register .. create, use and dink
        } else if (scope == DeploymentDescriptor.SCOPE_SESSION) {
  	scopeLock = session;
        } else if (scope == DeploymentDescriptor.SCOPE_APPLICATION) {
  	scopeLock = context;
        } else {
  	throw new SOAPException (Constants.FAULT_CODE_SERVER,
  				 "Service uses deprecated object scope " +
  				 "'page': inform provider of error");
        }
  
        // create the object if necessary
        boolean freshObject = false;
        
        // find the target object on which the requested method should
        // be invoked
        if (targetID.equals (ServerConstants.SERVICE_MANAGER_SERVICE_NAME)) {
  	targetObject = serviceManager;
        } else {
  	// locate (or create) the target object and invoke the method
  	synchronized (scopeLock) {
  	  if (scopeLock == session) {
  	    targetObject = session.getAttribute (targetID);
  	  } else if (scopeLock == context) {
  	    targetObject = context.getAttribute (targetID);
  	  } else {
  	    targetObject = null;
  	  }
  	  if (targetObject == null) {
  	    try {
  	      Class c = Class.forName (className);
  	      if (dd.getIsStatic ()) {
  		targetObject = c;
  	      } else {
  		targetObject = c.newInstance ();
  	      }
  	      freshObject = true;
  	    } catch (Exception e) {
  	      String msg;
  	      if (providerType == DeploymentDescriptor.PROVIDER_JAVA) {
  		msg = "Unable to resolve target object: " + e.getMessage ();
  	      } else {
  		msg = "Unable to load BSF: script services not available " +
  		  "without BSF: " + e.getMessage ();
  	      }
  	      throw new SOAPException (RPCConstants.FAULT_CODE_SERVER_BAD_TARGET_OBJECT_URI,
  				       msg, e);
  	    }
  	  }
  	  // remember the created instance if the scope is not REQUEST;
  	  // in that case the object is to be thrown away after handling
  	  // the request
  	  if (scopeLock == session) {
  	    session.setAttribute (targetID, targetObject);
  	  } else if (scopeLock == context) {
  	    context.setAttribute (targetID, targetObject);
  	  }
  	}
        }
        
        // if script provider type and first time to it, then load and
        // exec the script
        if (providerType != DeploymentDescriptor.PROVIDER_JAVA &&
  	  freshObject) {
  	// find the class that provides the BSF services (done
  	// this way via reflection to avoid a static dependency on BSF)
  	Class bc = Class.forName (SCRIPT_INVOKER);
  	
  	// get the script string to exec
  	String script = dd.getScriptFilenameOrString ();
  	if (providerType == DeploymentDescriptor.PROVIDER_SCRIPT_FILE) {
  	  String fileName = context.getRealPath (script);
  	  script = IOUtils.getStringFromReader (new FileReader (fileName));
  	}
  	
  	// exec it
  	Class[] sig = {DeploymentDescriptor.class,
  		       Object.class,
  		       String.class};
  	Method m = MethodUtils.getMethod (bc, "init", sig, true);
  	m.invoke (null, new Object[] {dd, targetObject, script});
        }
        
        // invoke the method on the target object
        resp = rpcRouter.invoke (call, targetObject);
  
      } catch (SOAPException e) {
  
        Fault fault = new Fault ();
        String faultCode = e.getFaultCode ();
        String faultString = e.getMessage ();
        
        if (faultCode == null || 
  	  faultCode.startsWith (Constants.FAULT_CODE_SERVER)) {
  	res.setStatus (ServerConstants.SC_INTERNAL_SERVER_ERROR);
        }
        else if (faultCode.startsWith (Constants.FAULT_CODE_CLIENT)) {
  	res.setStatus (ServerConstants.SC_BAD_REQUEST);
        }
        
        fault.setFaultCode (faultCode);
        fault.setFaultString (faultString);
        fault.setFaultActorURI (req.getRequestURI ());
        
        resp = new Response (null, null, fault, null, null, null);
  
      } catch (Throwable t) {
  
        // some unknown error occurred .. let's send the stacktrace out
        // hoping it'll be useful to someone (can't do a SOAPFault though
        // because if it was a SOAP problem it'd have been caught above)
        t.printStackTrace ();
        t.printStackTrace (out);
  
      }
    
      // Send it out.
      if (resp != null) {
        try {
  	// Build an envelope containing the response.
  	Envelope respEnvelope = resp.buildEnvelope ();
  	SOAPMappingRegistry smr = (call != null
  				   ? call.getSOAPMappingRegistry ()
  				   : new SOAPMappingRegistry());
  	
  	respEnvelope.marshall (out, smr);
        } catch (Exception e) {
  	throw new ServletException ("Error building response envelope", e);
        }
      }
    }
  }
  
  
  

RE: cvs commit: xml-soap/java/src/org/apache/soap/server/http RPCRouterServlet.java

Posted by "Steven J. McDowall" <sj...@uswest.net>.
Does something need to be added to build.xml to make this stuff
compile?

I tried to ant the newest tree and the Servlet stuff didn't happen..

-Steve

-----Original Message-----
From: sanjiva@locus.apache.org [mailto:sanjiva@locus.apache.org]
Sent: Tuesday, August 08, 2000 1:32 AM
To: xml-soap-cvs@apache.org
Subject: cvs commit: xml-soap/java/src/org/apache/soap/server/http
RPCRouterServlet.java


sanjiva     00/08/07 23:32:05

  Added:       java/src/org/apache/soap/server/http RPCRouterServlet.java
  Log:
  servlet version of RPC Router. A detailed note is being posted to
  the soap-dev list .. see there for more.
  Submitted by:	Steven J. McDowall, "Noor Zaman" <no...@instill.com>
  Reviewed by:	Sanjiva Weerawarana

  Revision  Changes    Path
  1.1
xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java

  Index: RPCRouterServlet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. 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.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "SOAP" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
   * ITS 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.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2000, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */

  package org.apache.soap.server.http;

  import java.io.*;
  import java.util.*;
  import java.lang.reflect.*;
  import javax.servlet.* ;
  import javax.servlet.http.* ;
  import org.w3c.dom.* ;
  import org.apache.soap.*;
  import org.apache.soap.rpc.*;
  import org.apache.soap.server.*;
  import org.apache.soap.encoding.*;
  import org.apache.soap.util.* ;
  import org.apache.soap.util.xml.* ;


  /**
   * @author Sanjiva Weerawarana <sa...@watson.ibm.com>
   * @author Mat
   * @author Steven McDowall <sj...@aptest.com>
   */

  public class RPCRouterServlet extends HttpServlet {
    private final static String RPC_ROUTER_ID = "rpcRouter";
    private final static String SERVICE_MANAGER_ID = "serviceManager";
    private static final String SCRIPT_CLASS = "com.ibm.bsf.BSFManager";
    private static final String SCRIPT_INVOKER =
      "org.apache.soap.server.InvokeBSF";

    public void init () throws ServletException {
      ServletConfig config = getServletConfig ();
      ServletContext context = config.getServletContext ();

      // create the service manager if necessary. NOTE: This approach
      // will not work if this servlet is put in a webapp that is
      // marked distributed .. the servlet context is unique only
      // per JVM. In that case we'll have to use an external database
      // to store the global stuff.
      synchronized (context) {
        Object o = context.getAttribute (RPC_ROUTER_ID);
        if (o == null) { // isn't this always true?? (is init() called
once?)
  	RPCRouter rpcRouter = new RPCRouter ();
  	ServiceManager serviceManager = new ServiceManager ();
  	rpcRouter.setServiceManager (serviceManager);
  	context.setAttribute (RPC_ROUTER_ID, rpcRouter);
  	context.setAttribute (SERVICE_MANAGER_ID, serviceManager);
        }
      }
    }

    public void doPost (HttpServletRequest req, HttpServletResponse res)
         throws ServletException, IOException {
      // locate the rpcrouter and service manager
      ServletConfig config = getServletConfig ();
      ServletContext context = config.getServletContext ();
      HttpSession session = req.getSession ();
      RPCRouter rpcRouter = (RPCRouter) context.getAttribute
(RPC_ROUTER_ID);
      ServiceManager serviceManager =
        (ServiceManager) context.getAttribute (SERVICE_MANAGER_ID);

      Response resp = null;
      String targetID = null;

      String contentType = req.getContentType ();
      int contentLength = req.getContentLength ();

      // set the outgoing content type and pick up the writer to write
      // to *after* that
      res.setContentType (Constants.HEADERVAL_CONTENT_TYPE_UTF8);
      PrintWriter out = res.getWriter ();

      Call call = null;

      if ((contentType == null) ||
  	!contentType.equals (Constants.HEADERVAL_CONTENT_TYPE)) {
        res.sendError (res.SC_BAD_REQUEST, "Content type must be: '" +
  		     Constants.HEADERVAL_CONTENT_TYPE + "'.");
        return;
      } else if (contentLength < 0) {
        res.sendError (res.SC_BAD_REQUEST, "Content length must be
specified.");
        return;
      }

      try {
        System.err.println (">>(" + new Date() + ") Processing SOAP
request...");

        Reader requestReader = req.getReader ();
        char[] payload       = new char[contentLength];
        int    offset        = 0;

        while (offset < contentLength) {
  	offset += requestReader.read (payload, offset, contentLength - offset);
        }

        // Parse the incoming request stream.
        org.apache.soap.util.xml.XMLParserLiaison xpl =
  	new XercesParserLiaison ();
        Document callDoc = xpl.read("- SOAP HTTP RPC Call Envelope -",
  				  new CharArrayReader (payload));
        Element payloadEl = null;
        if (callDoc == null) {
  	throw new SOAPException(Constants.FAULT_CODE_PROTOCOL,
  				"DOM parsing error: " + payload);
        }

        // extract the call
        try {
  	payloadEl = callDoc.getDocumentElement ();
  	Envelope callEnv = Envelope.unmarshall (payloadEl);
  	call = rpcRouter.extractCallFromEnvelope (callEnv);
  	targetID = call.getTargetObjectURI ();
        } catch (IllegalArgumentException e) {
  	String msg = e.getMessage ();
  	String faultCode =
  	  (msg != null && msg.equals (Constants.ERR_MSG_VERSION_MISMATCH))
  	  ? Constants.FAULT_CODE_VERSION_MISMATCH
  	  : Constants.FAULT_CODE_CLIENT;
  	throw new SOAPException (faultCode, msg, e);
        }

        // call on a valid method name?
        if (!rpcRouter.validCall (call)) {
  	throw new SOAPException (Constants.FAULT_CODE_SERVER,
  				 "Method '" + call.getMethodName () +
  				 "' is not supported.");
        }

        // lifecycle stuff of target object: what's the class to
instantiate?
        DeploymentDescriptor dd = serviceManager.query (targetID);
        int scope = dd.getScope ();
        byte providerType = dd.getProviderType ();
        String className;
        Object targetObject = null;
        if (providerType == DeploymentDescriptor.PROVIDER_JAVA) {
  	className = dd.getProviderClass ();
        } else {
  	// for scripts, we need a new BSF manager basically
  	className = SCRIPT_CLASS;
        }

        // determine the scope and lock object to use to manage the
lifecycle
        // of the service providing object
        Object scopeLock = null;
        if (scope == DeploymentDescriptor.SCOPE_REQUEST) {
  	scopeLock = this; // no need to register .. create, use and dink
        } else if (scope == DeploymentDescriptor.SCOPE_SESSION) {
  	scopeLock = session;
        } else if (scope == DeploymentDescriptor.SCOPE_APPLICATION) {
  	scopeLock = context;
        } else {
  	throw new SOAPException (Constants.FAULT_CODE_SERVER,
  				 "Service uses deprecated object scope " +
  				 "'page': inform provider of error");
        }

        // create the object if necessary
        boolean freshObject = false;

        // find the target object on which the requested method should
        // be invoked
        if (targetID.equals (ServerConstants.SERVICE_MANAGER_SERVICE_NAME))
{
  	targetObject = serviceManager;
        } else {
  	// locate (or create) the target object and invoke the method
  	synchronized (scopeLock) {
  	  if (scopeLock == session) {
  	    targetObject = session.getAttribute (targetID);
  	  } else if (scopeLock == context) {
  	    targetObject = context.getAttribute (targetID);
  	  } else {
  	    targetObject = null;
  	  }
  	  if (targetObject == null) {
  	    try {
  	      Class c = Class.forName (className);
  	      if (dd.getIsStatic ()) {
  		targetObject = c;
  	      } else {
  		targetObject = c.newInstance ();
  	      }
  	      freshObject = true;
  	    } catch (Exception e) {
  	      String msg;
  	      if (providerType == DeploymentDescriptor.PROVIDER_JAVA) {
  		msg = "Unable to resolve target object: " + e.getMessage ();
  	      } else {
  		msg = "Unable to load BSF: script services not available " +
  		  "without BSF: " + e.getMessage ();
  	      }
  	      throw new SOAPException
(RPCConstants.FAULT_CODE_SERVER_BAD_TARGET_OBJECT_URI,
  				       msg, e);
  	    }
  	  }
  	  // remember the created instance if the scope is not REQUEST;
  	  // in that case the object is to be thrown away after handling
  	  // the request
  	  if (scopeLock == session) {
  	    session.setAttribute (targetID, targetObject);
  	  } else if (scopeLock == context) {
  	    context.setAttribute (targetID, targetObject);
  	  }
  	}
        }

        // if script provider type and first time to it, then load and
        // exec the script
        if (providerType != DeploymentDescriptor.PROVIDER_JAVA &&
  	  freshObject) {
  	// find the class that provides the BSF services (done
  	// this way via reflection to avoid a static dependency on BSF)
  	Class bc = Class.forName (SCRIPT_INVOKER);

  	// get the script string to exec
  	String script = dd.getScriptFilenameOrString ();
  	if (providerType == DeploymentDescriptor.PROVIDER_SCRIPT_FILE) {
  	  String fileName = context.getRealPath (script);
  	  script = IOUtils.getStringFromReader (new FileReader (fileName));
  	}

  	// exec it
  	Class[] sig = {DeploymentDescriptor.class,
  		       Object.class,
  		       String.class};
  	Method m = MethodUtils.getMethod (bc, "init", sig, true);
  	m.invoke (null, new Object[] {dd, targetObject, script});
        }

        // invoke the method on the target object
        resp = rpcRouter.invoke (call, targetObject);

      } catch (SOAPException e) {

        Fault fault = new Fault ();
        String faultCode = e.getFaultCode ();
        String faultString = e.getMessage ();

        if (faultCode == null ||
  	  faultCode.startsWith (Constants.FAULT_CODE_SERVER)) {
  	res.setStatus (ServerConstants.SC_INTERNAL_SERVER_ERROR);
        }
        else if (faultCode.startsWith (Constants.FAULT_CODE_CLIENT)) {
  	res.setStatus (ServerConstants.SC_BAD_REQUEST);
        }

        fault.setFaultCode (faultCode);
        fault.setFaultString (faultString);
        fault.setFaultActorURI (req.getRequestURI ());

        resp = new Response (null, null, fault, null, null, null);

      } catch (Throwable t) {

        // some unknown error occurred .. let's send the stacktrace out
        // hoping it'll be useful to someone (can't do a SOAPFault though
        // because if it was a SOAP problem it'd have been caught above)
        t.printStackTrace ();
        t.printStackTrace (out);

      }

      // Send it out.
      if (resp != null) {
        try {
  	// Build an envelope containing the response.
  	Envelope respEnvelope = resp.buildEnvelope ();
  	SOAPMappingRegistry smr = (call != null
  				   ? call.getSOAPMappingRegistry ()
  				   : new SOAPMappingRegistry());

  	respEnvelope.marshall (out, smr);
        } catch (Exception e) {
  	throw new ServletException ("Error building response envelope", e);
        }
      }
    }
  }





RE: cvs commit: xml-soap/java/src/org/apache/soap/server/http RPCRouterServlet.java

Posted by "Steven J. McDowall" <sj...@uswest.net>.
Does something need to be added to build.xml to make this stuff
compile?

I tried to ant the newest tree and the Servlet stuff didn't happen..

-Steve

-----Original Message-----
From: sanjiva@locus.apache.org [mailto:sanjiva@locus.apache.org]
Sent: Tuesday, August 08, 2000 1:32 AM
To: xml-soap-cvs@apache.org
Subject: cvs commit: xml-soap/java/src/org/apache/soap/server/http
RPCRouterServlet.java


sanjiva     00/08/07 23:32:05

  Added:       java/src/org/apache/soap/server/http RPCRouterServlet.java
  Log:
  servlet version of RPC Router. A detailed note is being posted to
  the soap-dev list .. see there for more.
  Submitted by:	Steven J. McDowall, "Noor Zaman" <no...@instill.com>
  Reviewed by:	Sanjiva Weerawarana

  Revision  Changes    Path
  1.1
xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java

  Index: RPCRouterServlet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. 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.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "SOAP" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
   * ITS 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.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2000, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */

  package org.apache.soap.server.http;

  import java.io.*;
  import java.util.*;
  import java.lang.reflect.*;
  import javax.servlet.* ;
  import javax.servlet.http.* ;
  import org.w3c.dom.* ;
  import org.apache.soap.*;
  import org.apache.soap.rpc.*;
  import org.apache.soap.server.*;
  import org.apache.soap.encoding.*;
  import org.apache.soap.util.* ;
  import org.apache.soap.util.xml.* ;


  /**
   * @author Sanjiva Weerawarana <sa...@watson.ibm.com>
   * @author Mat
   * @author Steven McDowall <sj...@aptest.com>
   */

  public class RPCRouterServlet extends HttpServlet {
    private final static String RPC_ROUTER_ID = "rpcRouter";
    private final static String SERVICE_MANAGER_ID = "serviceManager";
    private static final String SCRIPT_CLASS = "com.ibm.bsf.BSFManager";
    private static final String SCRIPT_INVOKER =
      "org.apache.soap.server.InvokeBSF";

    public void init () throws ServletException {
      ServletConfig config = getServletConfig ();
      ServletContext context = config.getServletContext ();

      // create the service manager if necessary. NOTE: This approach
      // will not work if this servlet is put in a webapp that is
      // marked distributed .. the servlet context is unique only
      // per JVM. In that case we'll have to use an external database
      // to store the global stuff.
      synchronized (context) {
        Object o = context.getAttribute (RPC_ROUTER_ID);
        if (o == null) { // isn't this always true?? (is init() called
once?)
  	RPCRouter rpcRouter = new RPCRouter ();
  	ServiceManager serviceManager = new ServiceManager ();
  	rpcRouter.setServiceManager (serviceManager);
  	context.setAttribute (RPC_ROUTER_ID, rpcRouter);
  	context.setAttribute (SERVICE_MANAGER_ID, serviceManager);
        }
      }
    }

    public void doPost (HttpServletRequest req, HttpServletResponse res)
         throws ServletException, IOException {
      // locate the rpcrouter and service manager
      ServletConfig config = getServletConfig ();
      ServletContext context = config.getServletContext ();
      HttpSession session = req.getSession ();
      RPCRouter rpcRouter = (RPCRouter) context.getAttribute
(RPC_ROUTER_ID);
      ServiceManager serviceManager =
        (ServiceManager) context.getAttribute (SERVICE_MANAGER_ID);

      Response resp = null;
      String targetID = null;

      String contentType = req.getContentType ();
      int contentLength = req.getContentLength ();

      // set the outgoing content type and pick up the writer to write
      // to *after* that
      res.setContentType (Constants.HEADERVAL_CONTENT_TYPE_UTF8);
      PrintWriter out = res.getWriter ();

      Call call = null;

      if ((contentType == null) ||
  	!contentType.equals (Constants.HEADERVAL_CONTENT_TYPE)) {
        res.sendError (res.SC_BAD_REQUEST, "Content type must be: '" +
  		     Constants.HEADERVAL_CONTENT_TYPE + "'.");
        return;
      } else if (contentLength < 0) {
        res.sendError (res.SC_BAD_REQUEST, "Content length must be
specified.");
        return;
      }

      try {
        System.err.println (">>(" + new Date() + ") Processing SOAP
request...");

        Reader requestReader = req.getReader ();
        char[] payload       = new char[contentLength];
        int    offset        = 0;

        while (offset < contentLength) {
  	offset += requestReader.read (payload, offset, contentLength - offset);
        }

        // Parse the incoming request stream.
        org.apache.soap.util.xml.XMLParserLiaison xpl =
  	new XercesParserLiaison ();
        Document callDoc = xpl.read("- SOAP HTTP RPC Call Envelope -",
  				  new CharArrayReader (payload));
        Element payloadEl = null;
        if (callDoc == null) {
  	throw new SOAPException(Constants.FAULT_CODE_PROTOCOL,
  				"DOM parsing error: " + payload);
        }

        // extract the call
        try {
  	payloadEl = callDoc.getDocumentElement ();
  	Envelope callEnv = Envelope.unmarshall (payloadEl);
  	call = rpcRouter.extractCallFromEnvelope (callEnv);
  	targetID = call.getTargetObjectURI ();
        } catch (IllegalArgumentException e) {
  	String msg = e.getMessage ();
  	String faultCode =
  	  (msg != null && msg.equals (Constants.ERR_MSG_VERSION_MISMATCH))
  	  ? Constants.FAULT_CODE_VERSION_MISMATCH
  	  : Constants.FAULT_CODE_CLIENT;
  	throw new SOAPException (faultCode, msg, e);
        }

        // call on a valid method name?
        if (!rpcRouter.validCall (call)) {
  	throw new SOAPException (Constants.FAULT_CODE_SERVER,
  				 "Method '" + call.getMethodName () +
  				 "' is not supported.");
        }

        // lifecycle stuff of target object: what's the class to
instantiate?
        DeploymentDescriptor dd = serviceManager.query (targetID);
        int scope = dd.getScope ();
        byte providerType = dd.getProviderType ();
        String className;
        Object targetObject = null;
        if (providerType == DeploymentDescriptor.PROVIDER_JAVA) {
  	className = dd.getProviderClass ();
        } else {
  	// for scripts, we need a new BSF manager basically
  	className = SCRIPT_CLASS;
        }

        // determine the scope and lock object to use to manage the
lifecycle
        // of the service providing object
        Object scopeLock = null;
        if (scope == DeploymentDescriptor.SCOPE_REQUEST) {
  	scopeLock = this; // no need to register .. create, use and dink
        } else if (scope == DeploymentDescriptor.SCOPE_SESSION) {
  	scopeLock = session;
        } else if (scope == DeploymentDescriptor.SCOPE_APPLICATION) {
  	scopeLock = context;
        } else {
  	throw new SOAPException (Constants.FAULT_CODE_SERVER,
  				 "Service uses deprecated object scope " +
  				 "'page': inform provider of error");
        }

        // create the object if necessary
        boolean freshObject = false;

        // find the target object on which the requested method should
        // be invoked
        if (targetID.equals (ServerConstants.SERVICE_MANAGER_SERVICE_NAME))
{
  	targetObject = serviceManager;
        } else {
  	// locate (or create) the target object and invoke the method
  	synchronized (scopeLock) {
  	  if (scopeLock == session) {
  	    targetObject = session.getAttribute (targetID);
  	  } else if (scopeLock == context) {
  	    targetObject = context.getAttribute (targetID);
  	  } else {
  	    targetObject = null;
  	  }
  	  if (targetObject == null) {
  	    try {
  	      Class c = Class.forName (className);
  	      if (dd.getIsStatic ()) {
  		targetObject = c;
  	      } else {
  		targetObject = c.newInstance ();
  	      }
  	      freshObject = true;
  	    } catch (Exception e) {
  	      String msg;
  	      if (providerType == DeploymentDescriptor.PROVIDER_JAVA) {
  		msg = "Unable to resolve target object: " + e.getMessage ();
  	      } else {
  		msg = "Unable to load BSF: script services not available " +
  		  "without BSF: " + e.getMessage ();
  	      }
  	      throw new SOAPException
(RPCConstants.FAULT_CODE_SERVER_BAD_TARGET_OBJECT_URI,
  				       msg, e);
  	    }
  	  }
  	  // remember the created instance if the scope is not REQUEST;
  	  // in that case the object is to be thrown away after handling
  	  // the request
  	  if (scopeLock == session) {
  	    session.setAttribute (targetID, targetObject);
  	  } else if (scopeLock == context) {
  	    context.setAttribute (targetID, targetObject);
  	  }
  	}
        }

        // if script provider type and first time to it, then load and
        // exec the script
        if (providerType != DeploymentDescriptor.PROVIDER_JAVA &&
  	  freshObject) {
  	// find the class that provides the BSF services (done
  	// this way via reflection to avoid a static dependency on BSF)
  	Class bc = Class.forName (SCRIPT_INVOKER);

  	// get the script string to exec
  	String script = dd.getScriptFilenameOrString ();
  	if (providerType == DeploymentDescriptor.PROVIDER_SCRIPT_FILE) {
  	  String fileName = context.getRealPath (script);
  	  script = IOUtils.getStringFromReader (new FileReader (fileName));
  	}

  	// exec it
  	Class[] sig = {DeploymentDescriptor.class,
  		       Object.class,
  		       String.class};
  	Method m = MethodUtils.getMethod (bc, "init", sig, true);
  	m.invoke (null, new Object[] {dd, targetObject, script});
        }

        // invoke the method on the target object
        resp = rpcRouter.invoke (call, targetObject);

      } catch (SOAPException e) {

        Fault fault = new Fault ();
        String faultCode = e.getFaultCode ();
        String faultString = e.getMessage ();

        if (faultCode == null ||
  	  faultCode.startsWith (Constants.FAULT_CODE_SERVER)) {
  	res.setStatus (ServerConstants.SC_INTERNAL_SERVER_ERROR);
        }
        else if (faultCode.startsWith (Constants.FAULT_CODE_CLIENT)) {
  	res.setStatus (ServerConstants.SC_BAD_REQUEST);
        }

        fault.setFaultCode (faultCode);
        fault.setFaultString (faultString);
        fault.setFaultActorURI (req.getRequestURI ());

        resp = new Response (null, null, fault, null, null, null);

      } catch (Throwable t) {

        // some unknown error occurred .. let's send the stacktrace out
        // hoping it'll be useful to someone (can't do a SOAPFault though
        // because if it was a SOAP problem it'd have been caught above)
        t.printStackTrace ();
        t.printStackTrace (out);

      }

      // Send it out.
      if (resp != null) {
        try {
  	// Build an envelope containing the response.
  	Envelope respEnvelope = resp.buildEnvelope ();
  	SOAPMappingRegistry smr = (call != null
  				   ? call.getSOAPMappingRegistry ()
  				   : new SOAPMappingRegistry());

  	respEnvelope.marshall (out, smr);
        } catch (Exception e) {
  	throw new ServletException ("Error building response envelope", e);
        }
      }
    }
  }