Package org.vnetcon.xml.ws.servlet.request

Source Code of org.vnetcon.xml.ws.servlet.request.RequestHandler

/*
*    This file is part of WebServiceServlet (WSS).
*
*    WSS is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    WSS 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 General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with WSS.  If not, see <http://www.gnu.org/licenses/>.
*   
*    Copyright(c) 2010 Michael Kankkonen
*    http://www.vnetcon.org
*/


package org.vnetcon.xml.ws.servlet.request;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.transform.stream.StreamSource;

import org.vnetcon.xml.ws.servlet.WebServiceServlet;
import org.vnetcon.xml.ws.servlet.dao.MethodParameter;
import org.vnetcon.xml.ws.servlet.dao.SoapMethodCall;
import org.vnetcon.xml.ws.servlet.dao.WebMethod;
import org.xmlsoap.schemas.soap.envelope.Body;
import org.xmlsoap.schemas.soap.envelope.Envelope;

/**
* This class is responsible for handling received SOAP calls.
* doPost method in WebServiceServlet will only read the soap message
* from requests input stream and pass this request as a string
* to this class.
*
* @author Michael Kankkonen 17.9.2010
*         http://www.vnetcon.org
*
*/
public class RequestHandler {
 
 
  String wsUrl = null;
  String soapRequest = null;
  String nameSpace = null;
  HashMap<String, WebMethod> hashWebMethods = null;
 
  Class<?> wsClass = null;
 
  /**
   * Constructor for RequestHandler
   *
   * @param soapRequest       this is the actual request received from WebService client.
   * @param wsClass           the users class which public methods are treated as WebService methods
   * @param hashWebMethods    HashMap containing information of WebSerivce's public methods
   * @param wsUrl             WebService url this WebService is served
   * @throws Exception
   */
  public RequestHandler(String soapRequest, Class<?> wsClass, HashMap<String, WebMethod> hashWebMethods, String wsUrl) throws Exception {
    String parts[] = null;
    String delim = "";
    int i = 0;
    this.soapRequest = soapRequest.replaceAll("</", "\n</").replaceAll("\n\n", "\n");
    this.soapRequest = this.soapRequest.replaceAll(">", ">\n").replaceAll("\n\n", "\n");
//    System.out.println("SOAP request: " + this.soapRequest);
    this.wsClass = wsClass;
    this.hashWebMethods = hashWebMethods;
    this.wsUrl = wsUrl;
   
    this.nameSpace = this.wsClass.getName();
    parts = this.nameSpace.split("\\.");
    i = parts.length - 2;
    this.nameSpace = "";
    while(i >= 0){
      this.nameSpace += delim + parts[i];
      delim = ".";
      i--;
    }
  }

  /**
   * All received requests are transformed to native java objects using
   * JAXB Unmarshaller. To get this work properly without namespace "problems"
   * all the namspace "tags" (e.g. ns2:) are removed using this method.
   *
   * @param xml
   * @return
   * @throws Exception
   */
  private String cleanNamespaces(String xml) throws Exception {
    String strBuf = xml;
    strBuf = strBuf.replaceAll("\n</.?.*(0-10).:", "\n</");
    strBuf = strBuf.replaceAll("\n<.?.*(0-10).:", "\n<");
    return strBuf;
  }

 
 
  /**
   * This is called by RequestHandler creator and calling this
   * will start the actual "job to be done".
   *
   * @return
   * @throws Exception
   */
  public String execute() throws Exception {
    String strRet = null;
    Envelope env = this.xmlToEnvelope(this.soapRequest);
    Body body = env.getBody();
    String bodyXml = this.bodyToXML(body);
    SoapMethodCall smc = this.parseSoapBody(bodyXml);
    String methodRequest = smc.getMethodName();
    WebMethod webMethod = this.hashWebMethods.get(methodRequest);
    strRet = this.doNativeMethodCall(webMethod, smc);
    env = null;
    smc = null;
    Runtime.getRuntime().gc();
    return strRet;
  }
 
  /**
   * This method is called after all the information is prepared for actual
   * native WebService method call (= Users WebService class's public method call)
   * Method call is done using reflection classes.
   *
   * @param webMethod
   * @param smc
   * @return
   * @throws Exception
   */
  private String doNativeMethodCall(WebMethod webMethod, SoapMethodCall smc) throws Exception {
    String strRet = "";
    List<MethodParameter> params = webMethod.getParameters();
    Class<?> partytypes[] = new Class[params.size()];
    Method callMethod = null;
    Object wsObject = this.wsClass.newInstance();
    Object oParams[] = new Object[params.size()];
    Object retObject = null;
    int i = 0;

   
    while(i < params.size()){
      MethodParameter param = params.get(i);
      String parameterClass = param.getParameterClassAsString();
      String parameterClassForXmlRetrieve = "arg" + i + "_" + parameterClass.replaceAll("\\.", "_");
      Object nativeObject = null;
      String paramClassAsString = param.getParameterClassAsString();

      // get class for name if class not java class and not native (= contains . in class as package separator)
      if(!paramClassAsString.startsWith("java.") && !paramClassAsString.startsWith("javax.") && paramClassAsString.indexOf(".") > -1){
        partytypes[i] = Class.forName(paramClassAsString);
      }

      // now we are dealing with native types like int, long, float etc.
      if(paramClassAsString.indexOf(".") == -1){
       
        if(paramClassAsString.equals("int")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = Integer.parseInt(xml);
          partytypes[i] = Integer.TYPE;
        }

        if(paramClassAsString.equals("long")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = Long.parseLong(xml);
          partytypes[i] = Long.TYPE;
        }

        if(paramClassAsString.equals("short")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = Short.parseShort(xml);
          partytypes[i] = Short.TYPE;
        }

        if(paramClassAsString.equals("float")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = Float.parseFloat(xml);
          partytypes[i] = Float.TYPE;
        }
       
        if(paramClassAsString.equals("double")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = Double.parseDouble(xml);
          partytypes[i] = Double.TYPE;
        }

        if(paramClassAsString.equals("boolean")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = Boolean.parseBoolean(xml);
          partytypes[i] = Boolean.TYPE;
        }
       
        if(paramClassAsString.equals("byte")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = Byte.parseByte(xml);
          partytypes[i] = Byte.TYPE;
        }
       
        if(paramClassAsString.equals("long")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = Long.parseLong(xml);
          partytypes[i] = Long.TYPE;
        }
       
      }

      // now we are dealing with java types like String, BigInteger, GregorianCalendar etc.
      if(paramClassAsString.indexOf(".") > -1 && (paramClassAsString.startsWith("java.") || paramClassAsString.startsWith("javax."))){

        if(paramClassAsString.equals("java.lang.String")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = new String(xml);
          partytypes[i] = String.class;
        }

        if(paramClassAsString.equals("java.math.BigInteger")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = new java.math.BigInteger(xml);
          partytypes[i] = java.math.BigInteger.class;
        }

        if(paramClassAsString.equals("java.math.BigDecimal")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = new java.math.BigDecimal(xml);
          partytypes[i] = java.math.BigDecimal.class;
        }

        if(paramClassAsString.equals("javax.xml.datatype.XMLGregorianCalendar")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          javax.xml.datatype.XMLGregorianCalendar gcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(xml);
          nativeObject = gcal;
          partytypes[i] = javax.xml.datatype.XMLGregorianCalendar.class;
        }

        if(paramClassAsString.equals("javax.xml.namespace.QName")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          nativeObject = new javax.xml.namespace.QName(xml);
          partytypes[i] = javax.xml.namespace.QName.class;
        }

        if(paramClassAsString.equals("javax.xml.datatype.Duration")){
          String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
          javax.xml.datatype.Duration dur = DatatypeFactory.newInstance().newDuration(xml);
          nativeObject = dur;
          partytypes[i] = javax.xml.datatype.Duration.class;
        }
       
       
      }
     
     
      if(nativeObject == null){
        String parts[] = parameterClass.split("\\.");
        String parameterPlainClassName = parts[parts.length - 1];
        parameterPlainClassName = parameterPlainClassName.substring(0, 1).toLowerCase() + parameterPlainClassName.substring(1);
        String xml = smc.getParameterXml(parameterClassForXmlRetrieve);
        xml = this.cleanNamespaces(xml);
        xml = "<" + parameterPlainClassName + ">" + xml + "</" + parameterPlainClassName + ">";
        oParams[i] = this.unmarshall(parameterClass, xml);
      }else{
        oParams[i] = nativeObject;
      }
      i++;
    }

    callMethod = this.wsClass.getMethod(webMethod.getMethodName(), partytypes);
    retObject = callMethod.invoke(wsObject, oParams);
    String retObjectClass = retObject.getClass().getName();

    if(retObjectClass.indexOf(".") > -1 && !retObjectClass.startsWith("java.") && !retObjectClass.startsWith("javax.")){
//      retObject = this.marshal(retObject);
      String str = this.marshal(retObject);
//      str = str.replaceAll("retMessage", "RetMessage");
//      str = str.replaceAll("<wsResultSet>", "<type=\"WSResultSet\" wsResultSet>");
     
      strRet += "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n";
      strRet += " <soap:Body>\n";
      strRet += "      <tns:" + smc.getMethodName() + "Response xmlns:tns=\"" + this.nameSpace + "\" targetNamespace=\"" + this.nameSpace + "\" >\n";
//      strRet += "               <return>" + retObject + "</return>\n";
//      strRet += "               <return>" + str + "</return>\n";
      strRet += "              <return>" + str + "</return>\n";
      strRet += "      </tns:" + smc.getMethodName() + "Response>\n";
      strRet += " </soap:Body>\n";
      strRet += "</soap:Envelope>\n";   
     
//      System.out.println("objectRet: " + strRet);
      return strRet;
    }   
   
   
    strRet += "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n";
    strRet += " <soap:Body>\n";
    strRet += "      <tns:" + smc.getMethodName() + "Response xmlns:tns=\"" + this.nameSpace + "\" targetNamespace=\"" + this.nameSpace + "\">\n";
    strRet += "               <return>" + retObject + "</return>\n";
    strRet += "      </tns:" + smc.getMethodName() + "Response>\n";
    strRet += " </soap:Body>\n";
    strRet += "</soap:Envelope>\n";   
   
//    System.out.println(strRet);


    retObject = null;
    Runtime.getRuntime().gc();
    return strRet;
  }

  /**
   * This method unmarshall xml element retrieved from SOAP call to java object.
   * Usually this is a method parameter used in WebService method calls.
   *
   * @param className
   * @param xml
   * @return
   * @throws Exception
   */
  private Object unmarshall(String className, String xml) throws Exception {
    Object o = null;
    JAXBContext jc = JAXBContext.newInstance(Class.forName(className));
    Unmarshaller unmarshaller = jc.createUnmarshaller();
    ByteArrayInputStream bIn = new ByteArrayInputStream(xml.getBytes());
    unmarshaller.setSchema(null);
//    o = ((JAXBElement)unmarshaller.unmarshal(bIn)).getValue();
    o = unmarshaller.unmarshal(bIn);
    unmarshaller = null;
    Runtime.getRuntime().gc();
    return o;
  }

  /**
   * This method will marshal methods return object for SOAP reply
   *
   * @param xmlObject  methods return object
   * @return           return marshaled and little modified xml for SOAP reply
   * @throws Exception
   */
  private String marshal(Object xmlObject) throws Exception {
    String strRet = null;
    String strClassName = xmlObject.getClass().getName();
    String parts[] = strClassName.split("\\.");
    strClassName = parts[parts.length - 1];
    strClassName = strClassName.substring(0, 1).toLowerCase() + strClassName.substring(1);
    JAXBContext jc = JAXBContext.newInstance(xmlObject.getClass());
    Marshaller marshaller = jc.createMarshaller();
    ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    marshaller.setSchema(null);
    // o = ((JAXBElement)unmarshaller.unmarshal(bIn)).getValue();
    marshaller.marshal(xmlObject, bOut);
    strRet = new String(bOut.toByteArray());
    strRet = strRet.replaceAll("<\\?.*.\\?>", "");
    strRet = strRet.replaceAll("<" + strClassName + ">", "");
    strRet = strRet.replaceAll("</" + strClassName + ">", "");
    marshaller = null;
    Runtime.getRuntime().gc();
    return strRet;
  }
 
 
  /**
   * Helper method for parsing method call information from SOAP message.
   * This information will be stored into SoapMethodCall object.
   *
   * @param xml
   * @return
   * @throws Exception
   */
  private SoapMethodCall parseSoapBody(String xml) throws Exception {
    SoapMethodCall smc = null;
    String lines[] = xml.split("\n");
    boolean inBody = false;
    int i = 0;
    int iArgCounter = 0;
    while(i < lines.length){
      String line = lines[i].trim();
     
      if(line.toLowerCase().indexOf("body ") > -1){
        i++;
        line = lines[i].trim();
        smc = new SoapMethodCall(this.getSoapMethodName(line));
        inBody = true;
        continue;
      }
     
      if(line.toLowerCase().indexOf("body>") > -1){
        inBody = false;
      }

      if(inBody){
        if(line.toLowerCase().indexOf("arg" + iArgCounter + "_") > -1){
          String argName = this.getSoapArgumentName(line);
          String argXml = "";
         
          // empty argument including ending slash in tag
          if(argName.endsWith("/")){
            argName = argName.substring(0, argName.length() - 1).trim();
            smc.addParameterXml(argName, argXml);
            i++;
            continue;
          }
         
          // starting and ending tags both in same line
          if(line.substring(line.indexOf(argName) + argName.length()).indexOf(argName) > -1){
            argXml = this.getOneLineValue(line);
            smc.addParameterXml(argName, argXml);
            i++;
            continue;
          }
         
          i++;
          while(lines[i].indexOf(argName) == -1){
            argXml += lines[i].trim();
            i++;
          }
         
          smc.addParameterXml(argName, argXml);
          iArgCounter++;
        }
      }
     
      i++;
    }
    return smc;
  }

  /**
   * Helper method for parsing information from "one line contains both
   * starting and ending tags".
   *
   * @param line
   * @return
   * @throws Exception
   */
  private String getOneLineValue(String line) throws Exception {
    String strRet = "";
    if(line.indexOf("><") > -1){
      return strRet;
    }else{
      strRet = line.substring(line.indexOf(">"));
      strRet = line.substring(0, line.indexOf("<"));
    }
    return strRet;
  }

  /**
   * Helper method for parsing argument name from received SOAP message.
   *
   * @param line
   * @return
   * @throws Exception
   */
  private String getSoapArgumentName(String line) throws Exception {
    String strRet = line;
    String parts[] = strRet.split(" ");
    strRet = parts[0];
    if(strRet.indexOf(":") > -1){
      strRet = strRet.substring(strRet.indexOf(":") + 1).trim();
    }else{
      strRet = strRet.substring(1).trim();
    }
   
    if(strRet.endsWith(">")){
      strRet = strRet.substring(0, strRet.length() - 1).trim();
    }
   
   
    return strRet;
  }

  /**
   * Helper method for retrieving method name to be called from
   * SOAP message.
   *
   * @param line
   * @return
   * @throws Exception
   */
  private String getSoapMethodName(String line) throws Exception {
    String strRet = line;
    String parts[] = strRet.split(" ");
    strRet = parts[0];
    if(strRet.indexOf(":") > -1){
      strRet = strRet.substring(strRet.indexOf(":") + 1).trim();
    }else{
      strRet = strRet.substring(1).trim();
    }
    return strRet;
  }

  /**
   * This will marshall SOAP body element to xma.
   *
   * @param body
   * @return
   * @throws Exception
   */
  private String bodyToXML(Body body) throws Exception {
    String strRet = null;
    Marshaller marshaller = WebServiceServlet.jcBody.createMarshaller();
    ByteArrayOutputStream bOut = new ByteArrayOutputStream();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    marshaller.marshal(body, bOut);
    strRet = new String(bOut.toByteArray());
    marshaller = null;
    Runtime.getRuntime().gc();
    return strRet;
  }

  /**
   * This the first method called in execute. Received SOAP method
   * is first unmarshalled as Envelope object.
   *
   * @param xml
   * @return
   * @throws Exception
   */
  private Envelope xmlToEnvelope(String xml) throws Exception {
    Envelope env = null;
    Unmarshaller unmarshaller = WebServiceServlet.jcEnvelope.createUnmarshaller();
    ByteArrayInputStream bIn = new ByteArrayInputStream(xml.getBytes());
    //marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    unmarshaller.setSchema(null);
    env = (Envelope)((JAXBElement)unmarshaller.unmarshal(bIn)).getValue();
//    JAXBElement<Envelope> element = unmarshaller.unmarshal(new StreamSource(bIn),Envelope.class);
//      env = element.getValue();
    unmarshaller = null;
    Runtime.getRuntime().gc();
      return env;
  }
 
 
}
TOP

Related Classes of org.vnetcon.xml.ws.servlet.request.RequestHandler

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.