diff --git a/src/zutil/network/http/soap/SOAPClientFactory.java b/src/zutil/network/http/soap/SOAPClientFactory.java new file mode 100644 index 0000000..e34f842 --- /dev/null +++ b/src/zutil/network/http/soap/SOAPClientFactory.java @@ -0,0 +1,78 @@ +package zutil.network.http.soap; + +import javax.wsdl.WSDLException; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.CtNewMethod; +import javassist.NotFoundException; +import zutil.network.ws.WSInterface; +import zutil.network.ws.WSMethodDef; +import zutil.network.ws.WebServiceDef; + +/** + * This is an factory that generates clients for web services + * + * @author Ziver + */ +public class SOAPClientFactory { + + /** + * Generates a Client Object for the web service. + * + * @param is the class of the web service definition + * @param intf is the class of the web service definition + * @return a client Object + */ + @SuppressWarnings("unchecked") + public static T getClient(Class intf) throws InstantiationException, IllegalAccessException, CannotCompileException, NotFoundException, WSDLException{ + if( !WSInterface.class.isAssignableFrom( intf )){ + throw new ClassCastException("The Web Service class is not a subclass of WSInterface!"); + } + return getClient( intf, new WebServiceDef((Class)intf) ); + } + + /** + * Generates a Client Object for the web service. + * + * @param is the class of the web service definition + * @param intf is the class of the web service definition + * @param wsDef is the web service definition of the intf parameter + * @return a client Object + */ + @SuppressWarnings("unchecked") + public static T getClient(Class intf, WebServiceDef wsDef) throws InstantiationException, IllegalAccessException, CannotCompileException, NotFoundException{ + if( !WSInterface.class.isAssignableFrom( intf )){ + throw new ClassCastException("The Web Service class is not a subclass of WSInterface!"); + } + + // Generate the class + ClassPool pool = ClassPool.getDefault(); + CtClass cc = pool.makeClass(intf.getName()+"Impl_"+Math.random()); + + CtClass intfClass = pool.get( intf.getName() ); + + // Is intf an interface + if( intf.isInterface() ){ + cc.addInterface( intfClass ); + } + // or a class + else{ + cc.setSuperclass( intfClass ); + } + + // Generate the methods + for(WSMethodDef methodDef : wsDef.getMethods()){ + CtMethod method = CtNewMethod.make("public int m(int i){}", cc); + method.insertBefore("System.out.println(\"Hello.say():\");"); + } + + // Initiate the class + Class c = cc.toClass(); + T obj = c.newInstance(); + + return obj; + } +} diff --git a/src/zutil/network/http/soap/SOAPClientException.java b/src/zutil/network/http/soap/SOAPException.java similarity index 65% rename from src/zutil/network/http/soap/SOAPClientException.java rename to src/zutil/network/http/soap/SOAPException.java index 9002090..af5f597 100644 --- a/src/zutil/network/http/soap/SOAPClientException.java +++ b/src/zutil/network/http/soap/SOAPException.java @@ -6,10 +6,10 @@ package zutil.network.http.soap; * * @author Ziver */ -public class SOAPClientException extends Exception{ +public class SOAPException extends Exception{ private static final long serialVersionUID = 1L; - public SOAPClientException(String string) { + public SOAPException(String string) { super(string); } } diff --git a/src/zutil/network/http/soap/SOAPHttpPage.java b/src/zutil/network/http/soap/SOAPHttpPage.java index a52d7c3..17178d5 100644 --- a/src/zutil/network/http/soap/SOAPHttpPage.java +++ b/src/zutil/network/http/soap/SOAPHttpPage.java @@ -1,6 +1,5 @@ package zutil.network.http.soap; -import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.Field; @@ -11,6 +10,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.wsdl.Binding; import javax.wsdl.BindingInput; @@ -45,12 +46,17 @@ import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.xml.sax.SAXException; -import zutil.MultiPrintStream; +import zutil.converters.Converter; +import zutil.io.StringOutputStream; +import zutil.log.LogUtil; import zutil.network.http.HttpPage; import zutil.network.http.HttpPrintStream; -import zutil.network.http.soap.SOAPInterface.WSDLDocumentation; -import zutil.network.http.soap.SOAPInterface.WSDLParamDocumentation; -import zutil.network.http.soap.SOAPObject.SOAPFieldName; +import zutil.network.ws.WSInterface; +import zutil.network.ws.WSObject; +import zutil.network.ws.WSReturnValueList; +import zutil.network.ws.WSInterface.WSDocumentation; +import zutil.network.ws.WSInterface.WSParamDocumentation; +import zutil.network.ws.WSObject.WSFieldName; import com.ibm.wsdl.extensions.PopulatedExtensionRegistry; import com.ibm.wsdl.extensions.soap.SOAPConstants; @@ -89,6 +95,8 @@ import com.sun.org.apache.xerces.internal.dom.DocumentImpl; * @author Ziver */ public class SOAPHttpPage implements HttpPage{ + public static final Logger logger = LogUtil.getLogger(); + // valid methods for this soap page private HashMap methods; // contains an method and the names for the parameters @@ -107,7 +115,7 @@ public class SOAPHttpPage implements HttpPage{ header = false; Class tmp = m.getReturnType(); - if( SOAPReturnValueList.class.isAssignableFrom( tmp )){ + if( WSReturnValueList.class.isAssignableFrom( tmp )){ returnName = new String[ tmp.getFields().length ]; returnClass = new Class[ tmp.getFields().length ]; } @@ -122,7 +130,7 @@ public class SOAPHttpPage implements HttpPage{ } } // The object that the functions will be invoked from - private SOAPInterface interf; + private WSInterface interf; // The WSDL document private Definition wsdl; // The WSDL Type part @@ -132,7 +140,7 @@ public class SOAPHttpPage implements HttpPage{ // Session enabled private boolean session_enabled; - public SOAPHttpPage(String url, SOAPInterface interf) throws WSDLException{ + public SOAPHttpPage(String url, WSInterface interf) throws WSDLException{ //if(!SOAPInterface.class.isAssignableFrom(interf) ) // throw new ClassCastException("Class does not implement SOAPInterface!"); this.url = url; @@ -143,7 +151,7 @@ public class SOAPHttpPage implements HttpPage{ for(Method m : interf.getClass().getDeclaredMethods()){ // check for public methods if((m.getModifiers() & Modifier.PUBLIC) > 0 && - !m.isAnnotationPresent(SOAPInterface.SOAPDisabled.class)){ + !m.isAnnotationPresent(WSInterface.WSDisabled.class)){ MethodCache chasch = new MethodCache(m); StringBuffer tmp = new StringBuffer(m.getName()+"("); @@ -152,8 +160,8 @@ public class SOAPHttpPage implements HttpPage{ for(int i=0; i "); // the return parameter name - SOAPInterface.SOAPReturnName returnName = m.getAnnotation(SOAPInterface.SOAPReturnName.class); - if( SOAPReturnValueList.class.isAssignableFrom( m.getReturnType() ) ){ + WSInterface.WSReturnName returnName = m.getAnnotation(WSInterface.WSReturnName.class); + if( WSReturnValueList.class.isAssignableFrom( m.getReturnType() ) ){ Class retClass = m.getReturnType(); for(int i=0; i it = requestRoot.elementIterator(); while( it.hasNext() ){ Element e = it.next(); @@ -379,7 +390,7 @@ public class SOAPHttpPage implements HttpPage{ // Get the parameter values for(int i=0; i0 ){ - SOAPInterface.SOAPNameSpace namespace = m.method.getAnnotation(SOAPInterface.SOAPNameSpace.class); + WSInterface.WSNamespace namespace = m.method.getAnnotation(WSInterface.WSNamespace.class); Element response = responseRoot.addElement(""); if( namespace != null ) response.addNamespace("m", namespace.value()); else response.addNamespace("m", url+""+m.method.getName()); response.setName("m:"+m.method.getName()+"Response"); - if( ret instanceof SOAPReturnValueList ){ + if( ret instanceof WSReturnValueList ){ Field[] f = ret.getClass().getFields(); for(int i=0; i c) throws IOException{ - if(data == null || data.isEmpty()) - return null; - - if( c == String.class) return data; - else if(c == Integer.class) return Integer.parseInt(data); - else if(c == int.class) return Integer.parseInt(data); - else if(c == Long.class) return Long.parseLong(data); - else if(c == long.class) return Long.parseLong(data); - else if(c == Float.class) return Float.parseFloat(data); - else if(c == float.class) return Float.parseFloat(data); - else if(c == Double.class) return Double.parseDouble(data); - else if(c == double.class) return Double.parseDouble(data); - else if(c == Boolean.class) return Boolean.parseBoolean(data); - else if(c == boolean.class) return Boolean.parseBoolean(data); - else if(c == Byte.class) return Byte.parseByte(data); - else if(c == byte.class) return Byte.parseByte(data); - else if(byte[].class.isAssignableFrom(c)) - return new sun.misc.BASE64Decoder().decodeBuffer(data); - return null; - } /** * Invokes a specified method @@ -449,7 +435,7 @@ public class SOAPHttpPage implements HttpPage{ try { return m.invoke(obj, params ); } catch (IllegalArgumentException e) { - throw new SOAPClientException("Arguments missing for "+m.getName()+"!"); + throw new SOAPException("Arguments missing for "+m.getName()+"!"); } catch (IllegalAccessException e) { throw e; } catch (InvocationTargetException e) { @@ -492,10 +478,10 @@ public class SOAPHttpPage implements HttpPage{ Element objectE = root.addElement( ename ); //getClassSOAPName(ret.getClass()) if(ret instanceof Element) objectE.add( (Element)ret ); - else if(ret instanceof SOAPObject){ + else if(ret instanceof WSObject){ Field[] fields = ret.getClass().getFields(); for(int i=0; i org.w3c.dom.Document xmldoc= new DocumentImpl(); @@ -821,7 +807,7 @@ public class SOAPHttpPage implements HttpPage{ element.addAttribute("maxOccurs", "unbounded"); element.addAttribute("name", "element"); element.addAttribute("nillable", "true"); - if(SOAPObject.class.isAssignableFrom(ctmp)) + if(WSObject.class.isAssignableFrom(ctmp)) element.addAttribute("type", "tns:"+getClassSOAPName(c).replace("[]", "")); else element.addAttribute("type", "xsd:"+getClassSOAPName(c).replace("[]", "")); @@ -830,7 +816,7 @@ public class SOAPHttpPage implements HttpPage{ types.add(ctmp); } // Generate SOAPObject type - else if(SOAPObject.class.isAssignableFrom(c)){ + else if(WSObject.class.isAssignableFrom(c)){ Element type = schema.addElement("xsd:complexType"); type.addAttribute("name", getClassSOAPName(c)); @@ -838,7 +824,7 @@ public class SOAPHttpPage implements HttpPage{ Field[] fields = c.getFields(); for(int i=0; i cTmp = getClass(fields[i].getType()); - if(SOAPObject.class.isAssignableFrom(cTmp)){ + if(WSObject.class.isAssignableFrom(cTmp)){ element.addAttribute("type", "tns:"+getClassSOAPName(cTmp)); if(!types.contains(cTmp)) types.add(cTmp); diff --git a/src/zutil/network/http/soap/SOAPReturnObjectList.java b/src/zutil/network/http/soap/SOAPReturnObjectList.java deleted file mode 100644 index 84b0335..0000000 --- a/src/zutil/network/http/soap/SOAPReturnObjectList.java +++ /dev/null @@ -1,51 +0,0 @@ -package zutil.network.http.soap; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * This interface is for returning multiple object. - * All the public fields in the class that implements - * this class will be set as return values. And the - * implementing class will be transparent. - * - * @author Ziver - * - */ -public interface SOAPReturnObjectList { - - /** - * Method comments for the WSDL. - * These comments are put in the operation part of the WSDL - * - * @author Ziver - */ - @Retention(RetentionPolicy.RUNTIME) - public @interface WSDLDocumentation{ - String value(); - } - - /** - * Disables SOAP publication of the given field. - * - * @author Ziver - */ - /*@Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.METHOD) - public @interface SOAPDisabledValue { }*/ - - /** - * Annotation that assigns a name to the return value - * to the field. - * - * @author Ziver - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) - public @interface SOAPValueName { - String value(); - } -} - diff --git a/src/zutil/network/http/soap/SOAPTest.java b/src/zutil/network/http/soap/SOAPTest.java deleted file mode 100644 index 9f48a1a..0000000 --- a/src/zutil/network/http/soap/SOAPTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package zutil.network.http.soap; - -import javax.wsdl.WSDLException; - -import org.dom4j.Document; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.XMLWriter; - - -public class SOAPTest { - //******************************************************************************************* - //**************************** TEST ********************************************************* - - public static void main(String[] args){ - try { - SOAPHttpPage soap = new SOAPHttpPage("http://test.se:8080/", new SOAPTestClass()); - - // Response - try { - Document document = soap.genSOAPResponse( - "" + - "\n" + - " \n" + - //" \n" + - //" IBM\n" + - //" \n" + - //" \n" + - //" 66\n" + - //" \n" + - " \n" + - " IBM\n" + - " \n" + - " \n" + - ""); - System.out.println( "****************** RESPONSE *********************" ); - - OutputFormat format = OutputFormat.createPrettyPrint(); - XMLWriter writer = new XMLWriter( System.out, format ); - writer.write( document ); - - System.out.println(); - } catch (Exception e) { - e.printStackTrace(); - } - } catch (WSDLException e) { - e.printStackTrace(); - } - } -} - -class SOAPTestClass3 implements SOAPObject{ - public String lol = "lol11"; - public String lol2 = "lol22"; -} - -class SOAPTestClass2 implements SOAPObject{ - @SOAPFieldName(value="lolz", optional=true) - public String lol = "lol1"; - @SOAPFieldName("lolx") - public String lol2 = "lol2"; - public byte[] b = new byte[]{0x12, 0x23}; - public SOAPTestClass3 l = new SOAPTestClass3(); -} - -class SOAPTestRetClass implements SOAPReturnObjectList{ - @SOAPValueName("retTest") - public String lol = "lol1"; - public String lol2 = "lol2"; -} - -class SOAPTestClass implements SOAPInterface{ - public SOAPTestClass(){} - - @SOAPHeader() - @WSDLDocumentation("hello") - public void pubZ( - @SOAPParamName(value="olle", optional=true) int lol, - @SOAPParamName(value="olle2", optional=true) int lol2) throws Exception{ - //System.out.println("Param: "+lol); - throw new Exception("Ziver is the fizle"); - } - - @SOAPReturnName("param") - @WSDLParamDocumentation("null is the shizzle") - public String[][] pubA ( - @SOAPParamName("Ztring") String lol) throws Exception{ - //System.out.println("ParamZ: "+lol); - return new String[][]{{"test","test2"},{"test3","test4"}}; - } - - @SOAPReturnName("zivarray") - @WSDLParamDocumentation("null is the shizzle") - public SOAPTestClass2[] pubX ( - @SOAPParamName("Ztring") String lol) throws Exception{ - return new SOAPTestClass2[]{new SOAPTestClass2(), new SOAPTestClass2()}; - } - - @SOAPReturnName("zivarray") - @WSDLParamDocumentation("null is the shizzle") - public SOAPTestRetClass pubB ( - @SOAPParamName("byte") String lol) throws Exception{ - SOAPTestRetClass tmp = new SOAPTestRetClass(); - tmp.lol = "test"; - tmp.lol2 = "test2"; - return tmp; - } - - @SOAPDisabled() - public void privaZ(){ } - protected void protZ(){ } -} diff --git a/src/zutil/network/http/soap/SOAPInterface.java b/src/zutil/network/ws/WSInterface.java similarity index 58% rename from src/zutil/network/http/soap/SOAPInterface.java rename to src/zutil/network/ws/WSInterface.java index 56974e8..420987a 100644 --- a/src/zutil/network/http/soap/SOAPInterface.java +++ b/src/zutil/network/ws/WSInterface.java @@ -1,31 +1,30 @@ -package zutil.network.http.soap; +package zutil.network.ws; import java.lang.annotation.*; /** * - * Specifies SOAP parameters names an other things. + * Specifies web service parameter names and other things. * Example: *
- *	private static class Test implements SOAPInterface{
+ *	private static class Test implements WSInterface{
  *		public Test(){}
  *	
- *		@SOAPHeader()
- *		@WSDLDocumentation("blabla")
+ *		@WSDocumentation("blabla")
  *		@WSDLParamDocumentation("olle = an variable?")
  *		public void pubZ( 
- *				@SOAPParamName("olle") int lol) 
+ *				@WSParamName("olle") int lol) 
  *				throws Exception{ 
  *			....
  *		}
  *	
- *		@SOAPReturnName("param")
+ *		@WSReturnName("param")
  *		public String pubA( 
- *				@SOAPParamName(value="lol", optional=true) String lol) 
+ *				@WSParamName(value="lol", optional=true) String lol) 
  *				throws Exception{ 
  *			....
  *		}
  *	
- *		@SOAPDisabled()
+ *		@WSDisabled()
  *		public void privaZ(....){ 
  *			...
  *		}		
@@ -34,7 +33,7 @@ import java.lang.annotation.*;
  * 
* @author Ziver */ -public interface SOAPInterface { +public interface WSInterface { /** * Annotation that assigns a name to an parameters * in an method. @@ -43,7 +42,7 @@ public interface SOAPInterface { */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) - public @interface SOAPParamName { + public @interface WSParamName { String value(); boolean optional() default false; } @@ -56,29 +55,30 @@ public interface SOAPInterface { */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) - public @interface SOAPReturnName { + public @interface WSReturnName { String value(); } /** - * Disables SOAP publication of the given method + * Disables publication of the given method * * @author Ziver */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) - public @interface SOAPDisabled { } + public @interface WSDisabled { } /** - * Method comments for the WSDL. - * These comments are put in the operation part of the WSDL + * Method or Parameter comments for the WSDL. + * These comments are put in the message part of the WSDL * * @author Ziver */ @Retention(RetentionPolicy.RUNTIME) - public @interface WSDLDocumentation{ + public @interface WSDocumentation{ String value(); } + /** * Parameter comments for the WSDL. * These comments are put in the message part of the WSDL @@ -86,27 +86,27 @@ public interface SOAPInterface { * @author Ziver */ @Retention(RetentionPolicy.RUNTIME) - public @interface WSDLParamDocumentation{ + public @interface WSParamDocumentation{ String value(); } /** - * This method will be used in the header of the soap. + * This method will be used in the header. * * @author Ziver */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) - public @interface SOAPHeader { } + public @interface WSHeader { } /** - * Specifies the namespace for the method. + * Specifies the name space for the method. * * @author Ziver */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) - public @interface SOAPNameSpace { + public @interface WSNamespace { String value(); } } diff --git a/src/zutil/network/ws/WSMethodDef.java b/src/zutil/network/ws/WSMethodDef.java new file mode 100644 index 0000000..856a37b --- /dev/null +++ b/src/zutil/network/ws/WSMethodDef.java @@ -0,0 +1,175 @@ +package zutil.network.ws; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import zutil.network.ws.WSInterface.WSDocumentation; + +// TODO: Header parameters +public class WSMethodDef { + /** A list of input parameters **/ + private ArrayList inputs; + /** A List of return parameters of the method **/ + private ArrayList outputs; + /** A List of exceptions that this method throws **/ + private ArrayList> exceptions; + /** The real method that this class represent, can be null if its a remote method **/ + private Method method; + /** Documentation of the method **/ + private String doc; + /** The published name of the method **/ + private String name; + + + /** + * + * @param me is a method in a class that implements WSInterface + */ + public WSMethodDef(Method me) { + if(!WSInterface.class.isAssignableFrom(me.getDeclaringClass()) ) + throw new ClassCastException("Declaring class does not implement WSInterface!"); + method = me; + inputs = new ArrayList(); + outputs = new ArrayList(); + exceptions = new ArrayList>(); + name = method.getName(); + + //***** Documentation + WSDocumentation tmpDoc = method.getAnnotation(WSInterface.WSDocumentation.class); + if(tmpDoc != null){ + doc = tmpDoc.value(); + } + //***** Exceptions + for( Class exc : method.getExceptionTypes() ){ + exceptions.add( exc ); + } + //********* Get the input parameter names ********** + Annotation[][] paramAnnotation = method.getParameterAnnotations(); + + for(int i=0; i retClass = method.getReturnType(); + Field[] fields = retClass.getFields(); + for(int i=0; i> getExceptions(){ + return exceptions; + } + + /** + * @return the number of parameters for this method + */ + public int inputCount(){ + return inputs.size(); + } + + /** + * @return a list of input parameters + */ + public List getInputs(){ + return inputs; + } + + /** + * @return the number of parameters for this method + */ + public int outputCount(){ + return outputs.size(); + } + + /** + * @return a list of input parameters + */ + public List getOutputs(){ + return outputs; + } + + /** + * @return Documentation of the method if one exists or else null + */ + public String getDocumentation(){ + return doc; + } + + + public String toString(){ + StringBuilder tmp = new StringBuilder(); + boolean first = true; + tmp.append(name).append("("); + for(WSParameterDef param : inputs){ + if(first) + first = false; + else + tmp.append(" ,"); + tmp.append(param.paramClass.getSimpleName()); + tmp.append(" "); + tmp.append(param.name); + } + tmp.append(") => "); + first = true; + for(WSParameterDef param : outputs){ + if(first) + first = false; + else + tmp.append(" ,"); + tmp.append(param.paramClass.getSimpleName()); + tmp.append(" "); + tmp.append(param.name); + } + return tmp.toString(); + } +} diff --git a/src/zutil/network/http/soap/SOAPObject.java b/src/zutil/network/ws/WSObject.java similarity index 72% rename from src/zutil/network/http/soap/SOAPObject.java rename to src/zutil/network/ws/WSObject.java index 7e5906a..1ea7c06 100644 --- a/src/zutil/network/http/soap/SOAPObject.java +++ b/src/zutil/network/ws/WSObject.java @@ -1,4 +1,4 @@ -package zutil.network.http.soap; +package zutil.network.ws; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -6,11 +6,11 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * This class is used as an return Object for SOAP. + * This class is used as an return Object for a web service. * If an class implements this interface then it can return * multiple values through the SOAPInterface. Example: *
- * 	private static class TestObject implements SOAPObject{
+ * 	private static class TestObject implements WSObject{
  *		@SOAPFieldName("name")
  *		public String name;
  *		@SOAPFieldName("lastname")
@@ -26,17 +26,17 @@ import java.lang.annotation.Target;
  * @author Ziver
  *
  */
-public interface SOAPObject{
+public interface WSObject{
 	/**
-	 * Specifies the SOAP name of an field.
-	 * The fields that are available for SOAP should
+	 * Specifies the name of a field.
+	 * The fields that are available in the service should
 	 * be declared public.
 	 * 
 	 * @author Ziver
 	 */
 	@Retention(RetentionPolicy.RUNTIME)
 	@Target(ElementType.FIELD)
-	public @interface SOAPFieldName {
+	public @interface WSFieldName {
 		String value();
 		boolean optional() default false;
 	}
diff --git a/src/zutil/network/ws/WSParameterDef.java b/src/zutil/network/ws/WSParameterDef.java
new file mode 100644
index 0000000..0051e8b
--- /dev/null
+++ b/src/zutil/network/ws/WSParameterDef.java
@@ -0,0 +1,42 @@
+package zutil.network.ws;
+public class WSParameterDef{
+	/** The class type of the parameter **/
+	protected Class paramClass;
+	/** The web service name of the parameter **/
+	protected String name;
+	/** Developer documentation **/
+	protected String doc;
+	/** If this parameter is optional **/
+	protected boolean optional;
+	/** Is it an header parameter **/
+	//boolean header;
+	
+	
+	public Class getParamClass() {
+		return paramClass;
+	}
+	protected void setParamClass(Class paramClass) {
+		this.paramClass = paramClass;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	protected void setName(String name) {
+		this.name = name;
+	}
+	
+	public String getDoc() {
+		return doc;
+	}
+	protected void setDoc(String doc) {
+		this.doc = doc;
+	}
+	
+	public boolean isOptional() {
+		return optional;
+	}
+	protected void setOptional(boolean optional) {
+		this.optional = optional;
+	}
+}
\ No newline at end of file
diff --git a/src/zutil/network/http/soap/SOAPReturnValueList.java b/src/zutil/network/ws/WSReturnValueList.java
similarity index 77%
rename from src/zutil/network/http/soap/SOAPReturnValueList.java
rename to src/zutil/network/ws/WSReturnValueList.java
index 83abb1b..5741461 100644
--- a/src/zutil/network/http/soap/SOAPReturnValueList.java
+++ b/src/zutil/network/ws/WSReturnValueList.java
@@ -1,4 +1,4 @@
-package zutil.network.http.soap;
+package zutil.network.ws;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
@@ -15,7 +15,7 @@ import java.lang.reflect.Field;
  * @author Ziver
  *
  */
-public class SOAPReturnValueList {
+public class WSReturnValueList {
 	
 	/**
 	 * Method comments for the WSDL. 
@@ -29,7 +29,7 @@ public class SOAPReturnValueList {
 	}
 	
 	/**
-	 * Disables SOAP publication of the given field.
+	 * Disables publication of the given field.
 	 * 
 	 * @author Ziver
 	 */
@@ -45,12 +45,12 @@ public class SOAPReturnValueList {
 	 */
 	@Retention(RetentionPolicy.RUNTIME)
 	@Target(ElementType.FIELD)
-	public @interface SOAPValueName {
+	public @interface WSValueName {
 	    String value();
 	}
 	
 	
-	protected Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException{
+	public Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException{
 		return field.get(this);
 	}
 }
diff --git a/src/zutil/network/ws/WebServiceDef.java b/src/zutil/network/ws/WebServiceDef.java
new file mode 100644
index 0000000..48aacb3
--- /dev/null
+++ b/src/zutil/network/ws/WebServiceDef.java
@@ -0,0 +1,66 @@
+package zutil.network.ws;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Set;
+
+import javax.wsdl.WSDLException;
+
+public class WebServiceDef {
+	/** A map of methods in this Service **/
+	private HashMap methods;
+	/** URL of the Service **/
+	//private String url;
+	/** Namespace of the service **/
+	//private String namespace;
+	/** Name of the web service **/
+	private String name;
+	/** This is the WSInterface class **/
+	private Class intf;
+	
+	
+	public WebServiceDef(Class intf) throws WSDLException{
+		this.intf = intf;
+		methods = new HashMap();
+		name = intf.getSimpleName();
+
+		for(Method m : intf.getDeclaredMethods()){
+			// check for public methods
+			if((m.getModifiers() & Modifier.PUBLIC) > 0 && 
+					!m.isAnnotationPresent(WSInterface.WSDisabled.class)){
+				WSMethodDef method = new WSMethodDef(m);
+				methods.put(method.getName(), method);
+			}
+		}
+	}
+	
+	/**
+	 * @return the class that defines this web service
+	 */
+	public Class getWSClass(){
+		return intf;
+	}
+	
+	/**
+	 * @return the name of the Service (usually the class name of the WSInterface)
+	 */
+	public String getName(){
+		return name;
+	}
+	
+	/**
+	 * @return a Set of all the method names
+	 */
+	public Set getMethodNames(){
+		return methods.keySet();
+	}
+	
+	/**
+	 * @return all the methods
+	 */
+	public Collection getMethods(){
+		return methods.values();
+	}
+}