import java.io.IOException;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.InputStreamReader;
import java.net.UnknownHostException;
import java.util.Vector;
import org.kxml.Xml;
import org.kxml.parser.XmlParser;
import org.kxml.kdom.Document;
import org.kxml.kdom.Element;
public class WSDLClient {
// Flag for error checking.
public boolean Error = false;
// Holds error string.
public String ErrorString = null;
// Holds binding name.
private String bindingName;
// Holds portType name.
private String portTypeName;
// Holds SOAP address.
private String soapAddress;
// Holds service description.
private String description;
// Flag to check if hash is present within
//wsdl file url.
private boolean hashFlag;
// Vector holding Operation objects.
private Vector operationVector;
// Document holding xml structure.
private Document doc = null;
// Port for wsdl downloading.
// We will use 8080 if user does not set
//the port value.
private int wsdlDownladingPort=8080;
// Constructor takes wsdl file url,
// downloads it and populates the Operation and
// Parameter class objects after processing.
public WSDLClient (String wsdlFileUri)
throws UnknownHostException, _
NullPointerException, IOException
{
operationVector = new Vector();
String resource = wsdlFileUri;
if (wsdlFileUri.indexOf("#")!=-1)
{
// There is a bindingName present
//as fragment identifer.
hashFlag = true;
int hashpos = wsdlFileUri.indexOf("#");
bindingName = wsdlFileUri.substring
(hashpos+1);
resource = wsdlFileUri.substring
(0,hashpos);
}// if (wsdlFileUri.indexOf("#")!=-1)
String wsdlFile = httpDownloadWSDL (resource);
if (wsdlFile.indexOf("<?xml")==-1)
{
Error = true;
ErrorString = wsdlFile;
}//if (wsdlFile.indexOf("<?xml")==-1)
else
// Parse method will load complete XML
// as Operation objects.
parse(wsdlFile);
}//WSDLClient
// Takes a WSDL file URL, downloads it and
// Return the downloaded wsdl file as string.
private String httpDownloadWSDL (String uri)
throws UnknownHostException, IOException
{
String wsdlFile="";
HttpConnection connection = _
new HttpConnection(uri, wsdlDownladingPort);
String request = connection.getHeaders();
// Getting input and output from httpconnection
PrintWriter out = new _
PrintWriter(connection.getOutputStream());
BufferedReader in = new BufferedReader
(new InputStreamReader
(connection.getInputStream()));
// Sending request to output streams
out.println(request);
out.flush();
StringBuffer sc = new StringBuffer();
String line = null;
// Getting respone and appending to string buffer.
while((line=in.readLine())!=null)
{
sc.append(line);
sc.append("\r\n");
}//while((line=in.readLine())!=null)
wsdlFile = sc.toString();
in.close();
out.close();
return wsdlFile = _
wsdlFile.substring(wsdlFile.indexOf("<"));
}//getBinding
/******************************************
* The following private methods together implement
* the WSDL parsing strategy.
* 1. parse()
* 2. setSoapAddress()
* 3. isElementPresent()
* 4. findServiceElement()
* 5. findElement()
* 6. findSoapBinding()
* 7. parseBinding()
* 8. addParamter()
*********************************************/
// Method gets the wsdlfile.
// It checks wether hashFlag is set or not.
// Constructor sets HashFlag if there was
// fragment identifier present in wsdl file URL.
// If yes we can come straight to the
// binding element.
// Otherwise we will first find the soap binding.
// In any of the two cases the next step is to
// parse the binding.
private void
parse (String wsdl) throws NullPointerException
,IOException
{
// Set flag if binding found
// so that no more binding processing.
boolean bindingFlag=false;
XmlParser parser = new XmlParser
(new StringReader(wsdl));
doc = new Document();
doc.parse(parser);
Element rootElement = doc.getRootElement();
Element bindingElement = null;
// We have to handle four cases.
// 1. hashFlag was set
(i.e. fragment identifier for binding
// was specified with wsdl file URL)
and <service> element
// is not present in the wsdl file.
// In this case we will find binding
//element and parse it.
// User should supply SOAP server address.
// 2. hashFlag was set and <service>
// element
// is also present in the wsdl file.
// In this case we will find binding
//element and parse it.
// Then find the SOAP server address from
//the <service> element.
// 3. hashFlag was not set but <service>
//element was present.
// First find the <service> element
//then find the binding.
// 4. Both hashFlag and <service>
//element were absent.
// In this case user will supply the //
SOAP server address
// just like Point number 1. But
//unlike point number 1,
// now we have to find the binding //
as well.
if (!bindingFlag)
{
// Case:1 or 2
if (hashFlag)
{
bindingElement = findElement
(rootElement,
"binding", bindingName);
parseBinding (bindingElement);
// Case:2
if (isElementPresent("service"))
setSoapAddress(rootElement);
} else {
// Case:3 or 4
if (isElementPresent("service"))
{
// Case:3
findServiceElement(rootElement);
bindingElement = findElement
(rootElement,
"binding", bindingName);
}
else
// Case:4
bindingElement = findSoapBinding
(rootElement);
if (bindingElement!=null)
parseBinding (bindingElement);
}//else
bindingFlag = true;
}//if (!bindingFlag)
}//parse()
// Finds the SOAP Server address from the
//<service> element.
private void
setSoapAddress (Element rootElement)
{
Element serviceElement = findElement
(rootElement, "service", null);
if (serviceElement!=null)
{
Element portElement = findElement
(serviceElement,"port",null);
for (int i=0; _
i<portElement.getChildCount(); i++)
{
if (portElement.getType(i) == Xml.ELEMENT)
{
Element address =
(Element) portElement.getChild(i);
soapAddress =
resolveVal(address.getValue("location"));
return;
}
}
}//if (serviceElement!=null)
}//setSoapAddress()
// Checks for the presence of an element.
private boolean
isElementPresent (String elementName)
{
Element element = findElement
(doc.getRootElement(), elementName, null);
if (element!=null)
return true;
else
return false;
}//isElement()
// Takes rootElement, finds <service>
// element
// and sets description, soapAddress and
//bindingName values.
private void
findServiceElement(Element rootElement)
{
Element serviceElement = null;
Element element = null;
serviceElement = findElement
(rootElement, "service", null);
// Note the documentation, find the bindingName
// and soapAddress.
if (serviceElement!=null)
{
System.out.println("In Service.."+soapAddress);
// Note the documentation if present.
if ((element = findElement
(serviceElement,"documentation",null))!=null)
{
for
(int x=0; x<element.getChildCount(); x++)
{
if (element.getType(x) == Xml.TEXT)
description = (String)
element.getChild(x);
}
}//if ((element = findElement
(serviceElement,"documentation",null))!=null)
// Find the bindingName and soapAddress.
if ((element = findElement
(serviceElement,"port",null))!=null)
{
for (int i=0; i<element.getChildCount(); i++)
{
if (element.getType(i) == Xml.ELEMENT)
{
bindingName =
resolveVal(element.getValue("binding"));
element = (Element) element.getChild(i);
soapAddress =
resolveVal(element.getValue("location"));
return;
}
}
}//if ((element = findElement
(serviceElement,"port",null))!=null)
}// if (serviceElement!=null)
return;
}//findServiceElement()
// Takes an Element object "e" and tries to find
// its child "elementName" with "name"
// attribute matching "valueOfAttributeName".
// WSDL Schema relies on "name" attribute of
//many Elements.
// That's why we need this method.
private Element
findElement (Element e, String elementName,
String valueOfAttributeName)
{
if (e!=null)
{
Element element = null;
int count = e.getChildCount();
if (count>0) {
for (int i=0; i<count; i++)
{
if (e.getType(i) == Xml.ELEMENT)
{
element = (Element) e.getChild(i);
if (valueOfAttributeName==null)
{
if (element.getName().equals
(elementName))
return element;
}
else
{
if (element.getName().equals(elementName) &&
element.getValue("name").equals(valueOfAttributeName))
return element;
}//else attribute=null
}//if (e.getType(i) == Xml.ELEMENT)
}//for (int i=0; i<count; i++)
}//if (count>0)
}//if (e!=null)
return null;
}//findElement
// This method returns the particular Soap Binding element
// whose style attribute equals "RPC"
// and transport attribute value equals
//"http://schemas.xmlsoap.org/soap/http".
// We use this method when hashFlag is not set, which means
// there was no fragment identifer in wsdlFileURL.
public Element
findSoapBinding(Element rootElement)
{
Element bindingElement=null;
int count = rootElement.getChildCount();
if (count>0)
{
for (int i=0; i<count; i++)
{
if (rootElement.getType(i) == Xml.ELEMENT)
{
bindingElement = (Element)
rootElement.getChild(i);
if (bindingElement.getName().equals
("binding"))
{
int ccount = bindingElement.getChildCount();
for (int j=0; j<ccount; j++)
{
if (bindingElement.getType(j) ==
Xml.ELEMENT)
{
Element cbinding =
(Element)
bindingElement.getChild(j);
if (cbinding.getName().equalsIgnoreCase
("binding")
&& cbinding.getValue
("style").equalsIgnoreCase("rpc")
&& cbinding.getValue
("transport").equalsIgnoreCase
("http://schemas.xmlsoap.org/soap/http"))
return bindingElement;
else
break;
}
}//for (int j=0; j<ccount; j++)
}//if (bindingElement.getName().equals("binding"))
}//if (rootElement.getType(i) == Xml.ELEMENT)
}//for (int i=0; i<count; i++)
}//if (count>0)
return null;
}//findSoapBinding()
// Takes the bindingElement, parses it
// and populates operationVector.
private void parseBinding(Element bindingElement)
{
bindingName = bindingElement.getValue("name");
// We are intreseted in name of the portType.
// The "type" attribute of binding gives
// name of the portType.
portTypeName = resolveVal(bindingElement.getValue
("type"));
// Getting portType element.
// Later we will find all corresponding
// operation elements.
Element portTypeElement = _
findElement(doc.getRootElement(), "portType" ,
portTypeName /*value for name
attribute*/);
int binChildCount = bindingElement.getChildCount();
Element operationElement = null;
// Loop to get binding's child elements.
// We are intreseted in three elements:
// 1. portType (we already have found this element).
// 2. operation (we will search for operation within
//portType).
// 3. message (both input and output are children
//of operation).
// We will search for multiple operation elements
// within the single portType element.
for ( int j = 0; j<binChildCount; j++ )
{
if (bindingElement.getType(j) == Xml.ELEMENT)
{
operationElement = _
(Element) bindingElement.getChild(j);
if (operationElement != null &&
operationElement.getName().equals("operation"))
{
int operChildCount = _
operationElement.getChildCount();
// Initializing Operation instance.
Operation operation = new Operation
(operationElement);
String operationName = resolveVal
(operationElement.getValue("name"));
if (portTypeElement!= null)
{
// Find <operation>
//in <portType>
// with operation name
//that we stored in operationName..
Element element = findElement
(portTypeElement,
"operation" , operationName);
int count = element.getChildCount();
//holds operation element childs
Element operationChild = null;
//holds message element
Element message = null;
for (int i=0; i<count; i++)
{
if (element.getType(i) ==
Xml.ELEMENT)
{
operationChild =(Element)
element.getChild(i);
if (operationChild != null &&
operationChild.getName().equals("input"))
{
String messagename = resolveVal
(operationChild.getValue("message"));
message = findElement
(doc.getRootElement(), "message",messagename);
addParameters (operation, message, true);
}
else if (operationChild != null &&
operationChild.getName().equals("output"))
{
String messagename = resolveVal
(operationChild.getValue("message"));
message = findElement (doc.getRootElement(),
"message",messagename);
addParameters (operation, message, false);
}
}//if(element.getType(i) ==
Xml.ELEMENT)
}//for (int i=0; i<count; i++)
}//if (portTypeElement!= null)
// Adding Operation object to vector.
operationVector.addElement(operation);
}//if (operationElement != null &&
operationElement.getName().equals
("operation"))
}//if (bindingElement.getType(j) == Xml.ELEMENT)
}//for j
}//parseBinding
// Takes a message element
// and adds it to the operation.
private void
addParameters (Operation operation, Element message,
boolean isInput)
{
Element part = null;
int parts = message.getChildCount();
if (parts>0)
{
for (int i=0; i<parts; i++)
{
if (message!=null && message.getType(i) ==
Xml.ELEMENT)
{
part =(Element) message.getChild(i);
if (isInput)
operation.addInputParameter
( new Parameter (part.getValue("name"),
resolveVal
(part.getValue("type"))));
else
operation.addOutputParameter
( new Parameter (part.getValue("name"),
resolveVal
(part.getValue("type"))));
}
}//for (int i=0; i<parts; i++)
}//if (parts>0)
}//addParameters
// Resolve values with namespace prefix e.g. "wax:WaxP".
// This method will return value without prefix e.g. "WaxP".
// This means we will igonre the namespace.
// Our client is only capable of working with data types
// defined by SOAP and WSDL.
// We will ignore user defined namespaces for data types.
private String resolveVal (String val)
{
if (val==null)
return null;
String value="";
if (val.indexOf(":")!=-1)
{
int colonpos = val.indexOf(":");
return value = val.substring
(colonpos+1);
}
return val;
}//resolveVal
/************************************************
* These are the public methods of this WSDL Client class.
* 1. setSoapAddress()
* 2. setWSDLDownloadingPort()
* 3. getOperationsCount()
* 4. getOperations()
* 5. getSoapAddress()
***************************************************/
// Sets soap server address.
public void setSoapAddress(String soapAddress)
{
this.soapAddress = soapAddress;
}//setSoapAddress()
// Sets the downloading WSDL file port.
public void setWSDLDownlodingPort(int port)
{
wsdlDownladingPort = port;
}//setWSDLDownlodingPort()
// Returns number of operations in Vector.
public int getOperationsCount ()
{
return operationVector.size();
}//getOperationsCount()
// Returns vector of Operation objects.
public Vector getOperations()
{
return operationVector;
}//getOperations
// Returns SOAP server address.
public String getSoapAddress()
{
return this.soapAddress;
}//setSoap()
}//class
|