Listing 2: The WSDLClient class reads and processes the WSDL File.
 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