diff --git a/Zutil.jar b/Zutil.jar index 152064d..710b214 100755 Binary files a/Zutil.jar and b/Zutil.jar differ diff --git a/libs/javassist.jar b/libs/javassist.jar deleted file mode 100644 index 29079c4..0000000 Binary files a/libs/javassist.jar and /dev/null differ diff --git a/src/zutil/net/ws/WSClientFactory.java b/src/zutil/net/ws/WSClientFactory.java new file mode 100755 index 0000000..ba6afcf --- /dev/null +++ b/src/zutil/net/ws/WSClientFactory.java @@ -0,0 +1,73 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.net.ws; + +import zutil.log.LogUtil; +import zutil.net.ws.soap.SOAPClientInvocationHandler; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This is an factory that generates clients for an unspecified web services + * + * @author Ziver + */ +public class WSClientFactory { + private static Logger logger = LogUtil.getLogger(); + + /** + * 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 + */ + public static T createClient(Class intf, InvocationHandler handler){ + if( !WSInterface.class.isAssignableFrom( intf )){ + throw new ClassCastException("The Web Service class is not a subclass of WSInterface!"); + } + + try { + Class proxyClass = Proxy.getProxyClass( + WSClientFactory.class.getClassLoader(), + new Class[]{intf}); + Constructor constructor = proxyClass.getConstructor( + new Class[]{InvocationHandler.class}); + T obj = constructor.newInstance( + new Object[]{handler}); + + return obj; + } catch (Exception e){ + logger.log(Level.SEVERE, null, e); + } + + return null; + } + +} diff --git a/src/zutil/net/ws/rest/RestHttpPage.java b/src/zutil/net/ws/rest/RestHttpPage.java old mode 100644 new mode 100755 index 98bf1cd..db0c676 --- a/src/zutil/net/ws/rest/RestHttpPage.java +++ b/src/zutil/net/ws/rest/RestHttpPage.java @@ -25,14 +25,15 @@ package zutil.net.ws.rest; import zutil.converters.Converter; +import zutil.io.StringOutputStream; import zutil.net.http.HttpHeaderParser; import zutil.net.http.HttpPage; import zutil.net.http.HttpPrintStream; -import zutil.net.ws.WSInterface; -import zutil.net.ws.WSMethodDef; -import zutil.net.ws.WSParameterDef; -import zutil.net.ws.WebServiceDef; +import zutil.net.ws.*; +import zutil.parser.json.JSONObjectOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; import java.util.Map; /** @@ -57,13 +58,33 @@ public class RestHttpPage implements HttpPage { HttpHeaderParser client_info, Map session, Map cookie, - Map request) { - execute(request); + Map request) throws IOException { + try { + out.println( + execute(client_info.getRequestURL(), request)); + } catch (Throwable throwable) { + throw new IOException(throwable); + } } - private void execute(Map input){ + private String execute(String targetMethod, Map input) throws Throwable { + if( wsDef.hasMethod(targetMethod) ){ + // Parse request + WSMethodDef m = wsDef.getMethod(targetMethod); + Object[] params = prepareInputParams(m, input); + // Invoke + Object ret = m.invoke(ws, params); + + // Generate Response + StringOutputStream dummyOut = new StringOutputStream(); + JSONObjectOutputStream out = new JSONObjectOutputStream(dummyOut); + out.writeObject(ret); + out.close(); + return dummyOut.toString(); + } + return "{error: \"Unknown target: "+targetMethod+"\"}"; } private Object[] prepareInputParams(WSMethodDef method, Map input){ diff --git a/src/zutil/net/ws/soap/SOAPAbstractClient.java b/src/zutil/net/ws/soap/SOAPAbstractClient.java deleted file mode 100644 index f6299f1..0000000 --- a/src/zutil/net/ws/soap/SOAPAbstractClient.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 Ziver Koc - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package zutil.net.ws.soap; - -import java.util.HashMap; - -/** - * This is an abstract client that will do generic requests to a - * SOAP Web service - * - * @author Ziver - */ -public class SOAPAbstractClient { - /** Web address of the web service */ - protected String url; - - /** - * Makes a request to the target web service - * @return - */ - public static Object request(String methodName, HashMap input){ - return null; - } - -} diff --git a/src/zutil/net/ws/soap/SOAPClientFactory.java b/src/zutil/net/ws/soap/SOAPClientFactory.java old mode 100644 new mode 100755 index fc6ac88..32dd556 --- a/src/zutil/net/ws/soap/SOAPClientFactory.java +++ b/src/zutil/net/ws/soap/SOAPClientFactory.java @@ -24,144 +24,48 @@ package zutil.net.ws.soap; -import javassist.*; import zutil.log.LogUtil; +import zutil.net.ws.WSClientFactory; import zutil.net.ws.WSInterface; -import zutil.net.ws.WSMethodDef; -import zutil.net.ws.WSParameterDef; import zutil.net.ws.WebServiceDef; -import java.util.HashMap; -import java.util.List; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.logging.Level; import java.util.logging.Logger; /** * This is an factory that generates clients for web services - * + * * @author Ziver */ public class SOAPClientFactory { - private static Logger logger = LogUtil.getLogger(); - - /** - * 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{ - 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 - */ - 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 intfClass = pool.get( intf.getName() ); - CtClass cc = pool.makeClass(intf.getName()+"Impl_"+ (int)(Math.random()*10000)); - - // Is intf an interface - if( intf.isInterface() ){ - cc.addInterface( intfClass ); - } - // or a class - else{ - cc.setSuperclass( intfClass ); - } - - // Add the logger class - CtField logger = CtField.make( - "private static "+Logger.class.getName()+" logger = "+LogUtil.class.getName()+".getLogger();", - cc); - cc.addField(logger); - - // Generate the methods - for(WSMethodDef methodDef : wsDef.getMethods()){ - // Create method - CtMethod method = CtNewMethod.make( - getOutputClass(methodDef.getOutputs()), // Return type - methodDef.getName(), // Method name - getParameterClasses(methodDef.getInputs()), // Parameters - new CtClass[]{pool.get( SOAPException.class.getName() )}, // Exceptions - generateCodeBody(methodDef), // Code Body - cc); // Class - cc.addMethod(method); - } - - // Initiate the class - @SuppressWarnings("unchecked") - Class c = cc.toClass(); - T obj = c.newInstance(); - - return obj; - } - - /** - * Generates a generic method code body that calls the SOAPAbstractClient class - */ - private static String generateCodeBody(WSMethodDef m) { - logger.finer("Generating method "+m.getName()+"(...)"); - - StringBuilder body = new StringBuilder("{\n"); - // Logging - body.append( "logger.fine(\"Executing method: "+m.getName()+"(...)\");\n" ); - - // Generate parameter list - body.append( HashMap.class.getName()+" params = new "+HashMap.class.getName()+"();\n" ); - for(WSParameterDef param : m.getInputs()){ - body.append( "params.put(\""+param.getName()+"\", "+param.getName()+");\n"); - } - - // Call SOAPAbstractClient class - if(m.getOutputCount() > 0) // non void function - body.append( "return " ); - body.append( SOAPAbstractClient.class.getName()+".request(\""+m.getName()+"\", params);\n" ); - - body.append("}"); - logger.finest("###################### BODY #########################"); - logger.finest(body.toString()); - logger.finest("#######################################################"); - return body.toString(); - } + private static Logger logger = LogUtil.getLogger(); + + /** + * 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 createClient(Class intf){ + return createClient( 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 + */ + public static T createClient(Class intf, WebServiceDef wsDef){ + T obj = WSClientFactory.createClient(intf, new SOAPClientInvocationHandler()); + return obj; + } - private static CtClass getParameterClass(WSParameterDef param) throws NotFoundException{ - return ClassPool.getDefault().get( param.getClass().getName() ); - } - - private static CtClass[] getParameterClasses(List params) throws NotFoundException{ - CtClass[] c = new CtClass[params.size()]; - - int i = 0; - for(WSParameterDef param : params){ - c[i++] = getParameterClass(param); - } - - return c; - } - - private static CtClass getOutputClass(List params) throws NotFoundException{ - if(params.isEmpty()){ - return CtClass.voidType; - } - else if(params.size() == 1){ - return ClassPool.getDefault().get( params.get(0).getClass().getName() ); - } - throw new IllegalArgumentException("Unknown return type"); - } } diff --git a/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java b/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java new file mode 100755 index 0000000..a951876 --- /dev/null +++ b/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java @@ -0,0 +1,105 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Ziver Koc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package zutil.net.ws.soap; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.xml.sax.SAXException; +import zutil.log.LogUtil; +import zutil.net.http.HttpClient; +import zutil.net.http.HttpHeaderParser; +import zutil.net.ws.WSInterface; +import zutil.net.ws.WSMethodDef; +import zutil.net.ws.WSParameterDef; +import zutil.net.ws.WebServiceDef; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This is an abstract client that will do generic requests to a + * SOAP Web service + * + * @author Ziver + */ +public class SOAPClientInvocationHandler implements InvocationHandler { + private static Logger logger = LogUtil.getLogger(); + + private WebServiceDef wsDef; + /** Web address of the web service */ + protected String url; + + /** + * Makes a request to the target web service + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + HttpClient request = HttpClient.POST(); + + HttpHeaderParser response = request.send(); + + return null; + } + + + private Document genSOAPRequest(WSInterface obj, String targetMethod, Object[] args){ + Document document = DocumentHelper.createDocument(); + Element envelope = document.addElement("soap:Envelope"); + WSMethodDef methodDef = wsDef.getMethod( targetMethod ); + try { + envelope.addNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/"); + envelope.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + envelope.addNamespace("xsd", "http://www.w3.org/2001/XMLSchema"); + + Element body = envelope.addElement( "soap:Body" ); + Element method = body.addElement(""); + method.addNamespace("m", methodDef.getNamespace() ); + method.setName("m:"+methodDef.getName()+"Request"); + for(int i=0; i c){ + protected static String getSOAPClassName(Class c){ Class cTmp = getClass(c); if(byte[].class.isAssignableFrom(c)){ return "base64Binary"; @@ -359,7 +363,7 @@ public class SOAPHttpPage implements HttpPage{ } } - public static Class getClass(Class c){ + protected static Class getClass(Class c){ if(c!=null && c.isArray()){ return getClass(c.getComponentType()); } diff --git a/test/zutil/test/SOAPClientTest.java b/test/zutil/test/SOAPClientTest.java old mode 100644 new mode 100755 index bd025c0..f0831fb --- a/test/zutil/test/SOAPClientTest.java +++ b/test/zutil/test/SOAPClientTest.java @@ -23,8 +23,6 @@ */ package zutil.test; -import javassist.CannotCompileException; -import javassist.NotFoundException; import zutil.log.CompactLogFormatter; import zutil.log.LogUtil; import zutil.net.ws.WSInterface; @@ -34,11 +32,11 @@ import java.util.logging.Level; public class SOAPClientTest { - public static void main(String[] args) throws InstantiationException, IllegalAccessException, CannotCompileException, NotFoundException{ + public static void main(String[] args) throws InstantiationException, IllegalAccessException{ LogUtil.setGlobalLevel(Level.ALL); LogUtil.setFormatter("", new CompactLogFormatter()); - TestClient intf = SOAPClientFactory.getClient(TestClient.class); + TestClient intf = SOAPClientFactory.createClient(TestClient.class); intf.m(); intf.c(); } diff --git a/test/zutil/test/SOAPTest.java b/test/zutil/test/SOAPTest.java old mode 100644 new mode 100755 index e9ae3cb..e03a6a7 --- a/test/zutil/test/SOAPTest.java +++ b/test/zutil/test/SOAPTest.java @@ -26,6 +26,7 @@ package zutil.test; import org.dom4j.Document; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; +import zutil.net.nio.message.type.SystemMessage; import zutil.net.ws.WSInterface; import zutil.net.ws.WSInterface.WSNamespace; import zutil.net.ws.WSReturnObject; @@ -43,30 +44,30 @@ public class SOAPTest { public SOAPTest(){ WebServiceDef wsDef = new WebServiceDef( MainSOAPClass.class ); SOAPHttpPage soap = new SOAPHttpPage( wsDef ); - + + System.out.println( "****************** WSDL *********************" ); WSDLWriter wsdl = new WSDLWriter( wsDef ); wsdl.write(System.out); - System.out.println( "****************** new *********************" ); - WSDLWriter wsdl2 = new WSDLWriter( wsDef ); - wsdl2.write(System.out); // Response try { - System.out.println( "****************** LOG *********************" ); - Document document = soap.genSOAPResponse( - "" + + System.out.println( "\n****************** REQUEST *********************" ); + String request = "\n" + "\n" + " \n" + " \n" + " IBM\n" + " \n" + - + " \n" + " IBM\n" + " \n" + " \n" + - ""); - System.out.println( "****************** RESPONSE *********************" ); + ""; + System.out.println(request); + System.out.println( "\n****************** EXECUTION *********************" ); + Document document = soap.genSOAPResponse(request); + System.out.println( "\n****************** RESPONSE *********************" ); OutputFormat format = OutputFormat.createPrettyPrint(); XMLWriter writer = new XMLWriter( System.out, format ); @@ -112,7 +113,7 @@ public class SOAPTest { public void exceptionMethod( @WSParamName(value="otherParam1", optional=true) int param1, @WSParamName(value="otherParam2", optional=true) int param2) throws Exception{ - System.out.println("Executing method: exceptionMethod()"); + System.out.println("Executing method: exceptionMethod(int param1="+param1+", int param2="+param2+",)"); throw new Exception("This is an Exception"); } @@ -120,7 +121,7 @@ public class SOAPTest { @WSParamDocumentation("Documentation of stringArrayMethod()") public String[][] stringArrayMethod ( @WSParamName("StringName") String str) throws Exception{ - System.out.println("Executing method: stringArrayMethod()"); + System.out.println("Executing method: stringArrayMethod(String str='"+str+"')"); return new String[][]{{"test","test2"},{"test3","test4"}}; } @@ -128,7 +129,7 @@ public class SOAPTest { @WSParamDocumentation("Documentation of specialReturnMethod()") public SpecialReturnClass[] specialReturnMethod ( @WSParamName("StringName2") String str) throws Exception{ - System.out.println("Executing method: specialReturnMethod()"); + System.out.println("Executing method: specialReturnMethod(String str='"+str+"')"); return new SpecialReturnClass[]{new SpecialReturnClass(), new SpecialReturnClass()}; }