diff --git a/src/zutil/net/http/HttpClient.java b/src/zutil/net/http/HttpClient.java index b0c69c3..76ab793 100755 --- a/src/zutil/net/http/HttpClient.java +++ b/src/zutil/net/http/HttpClient.java @@ -39,53 +39,56 @@ import java.util.HashMap; * * @author Ziver */ -public class HttpClient implements AutoCloseable{ - public enum HttpRequestType{ +public class HttpClient implements AutoCloseable { + public enum HttpRequestType { GET, POST } // Request variables private HttpURL url; private HttpRequestType type; - private HashMap headers; - private HashMap cookies; + private HashMap headers; + private HashMap cookies; private String data; // Response variables - private HttpHeaderParser rspHeader; + private HttpHeaderParser rspHeader; private InputStream rspStream; - - public HttpClient(HttpRequestType type){ + public HttpClient(HttpRequestType type) { this.type = type; headers = new HashMap<>(); cookies = new HashMap<>(); } - public void setURL( URL url){ - this.url = new HttpURL( url ); + public void setURL(URL url) { + setURL(new HttpURL(url)); + } + + public void setURL(HttpURL url) { + this.url = url; } /** * Adds a parameter to the request */ - public void setParameter( String key, String value ){ + public void setParameter(String key, String value) { url.setParameter(key, value); } /** * Adds a cookie to the request */ - public void setCookie( String key, String value ){ + public void setCookie(String key, String value) { cookies.put(key, value); } /** * Adds a header value to the request */ - public void setHeader( String key, String value ){ + public void setHeader(String key, String value) { headers.put(key, value); } @@ -93,7 +96,7 @@ public class HttpClient implements AutoCloseable{ * Sets the content data that will be included in the request. * NOTE: this will override the POST data parameter inclusion. */ - public void setData( String data ){ + public void setData(String data) { this.data = data; } @@ -101,32 +104,31 @@ public class HttpClient implements AutoCloseable{ * Will send a HTTP request to the target host. * NOTE: any previous request connections will be closed */ - public HttpHeaderParser send() throws IOException{ - Socket conn = new Socket( url.getHost(), url.getPort()); + public HttpHeaderParser send() throws IOException { + Socket conn = new Socket(url.getHost(), url.getPort()); // Request - HttpPrintStream request = new HttpPrintStream( conn.getOutputStream(), HttpMessageType.REQUEST ); - request.setRequestType( type.toString() ); - request.setRequestURL( url.getHttpURL() ); - request.setHeaders( headers ); - request.setCookies( cookies ); + HttpPrintStream request = new HttpPrintStream(conn.getOutputStream(), HttpMessageType.REQUEST); + request.setRequestType(type.toString()); + request.setRequestURL(url.getHttpURL()); + request.setHeaders(headers); + request.setCookies(cookies); - if( type == HttpRequestType.POST ){ + if (type == HttpRequestType.POST) { String postData; - if(data != null) + if (data != null) postData = data; else postData = url.getParameterString(); - request.setHeader("Content-Length", ""+postData.length()); + request.setHeader("Content-Length", "" + postData.length()); request.println(); - request.print( postData ); - } - else + request.print(postData); + } else request.println(); request.close(); // Response - if(rspHeader != null || rspStream != null) // Close previous request + if (rspHeader != null || rspStream != null) // Close previous request this.close(); rspStream = new BufferedInputStream(conn.getInputStream()); rspHeader = new HttpHeaderParser(rspStream); @@ -134,16 +136,17 @@ public class HttpClient implements AutoCloseable{ return rspHeader; } - public HttpHeaderParser getResponseHeader(){ + public HttpHeaderParser getResponseHeader() { return rspHeader; } - public InputStream getResponseInputStream(){ + + public InputStream getResponseInputStream() { return rspStream; } @Override public void close() throws IOException { - if(rspStream != null) + if (rspStream != null) rspStream.close(); rspStream = null; rspHeader = null; diff --git a/src/zutil/net/ws/rest/RESTClientFactory.java b/src/zutil/net/ws/rest/RESTClientFactory.java new file mode 100644 index 0000000..5904dfa --- /dev/null +++ b/src/zutil/net/ws/rest/RESTClientFactory.java @@ -0,0 +1,59 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 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.rest; + +import zutil.log.LogUtil; +import zutil.net.ws.WSClientFactory; +import zutil.net.ws.WSInterface; +import zutil.net.ws.WebServiceDef; +import zutil.net.ws.soap.SOAPClientInvocationHandler; + +import java.net.URL; +import java.util.logging.Logger; + +/** + * This is an factory that generates clients for web services + * + * @author Ziver + */ +public class RESTClientFactory { + private static Logger logger = LogUtil.getLogger(); + + + /** + * Generates a Client Object for the web service. + * + * @param is the class of the web service definition + * @param url is the target service serviceUrl + * @param intf is the class of the web service definition + * @return a client Object + */ + public static T createClient(URL url, Class intf){ + T obj = WSClientFactory.createClient( intf, + new RESTClientInvocationHandler(url, new WebServiceDef(intf))); + return obj; + } + +} diff --git a/src/zutil/net/ws/rest/RESTClientInvocationHandler.java b/src/zutil/net/ws/rest/RESTClientInvocationHandler.java new file mode 100644 index 0000000..6cdb557 --- /dev/null +++ b/src/zutil/net/ws/rest/RESTClientInvocationHandler.java @@ -0,0 +1,112 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 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.rest; + +import zutil.io.IOUtil; +import zutil.log.LogUtil; +import zutil.net.http.HttpClient; +import zutil.net.http.HttpHeaderParser; +import zutil.net.http.HttpURL; +import zutil.net.ws.WSInterface; +import zutil.net.ws.WSMethodDef; +import zutil.net.ws.WSParameterDef; +import zutil.net.ws.WebServiceDef; +import zutil.net.ws.soap.SOAPHttpPage; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This is an abstract client that will do generic requests to a + * REST Web service using JSON response. + */ +public class RESTClientInvocationHandler implements InvocationHandler { + private static Logger logger = LogUtil.getLogger(); + + private WebServiceDef wsDef; + /** + * Web address of the web service + */ + protected URL serviceUrl; + + public RESTClientInvocationHandler(URL url, WebServiceDef webServiceDef) { + this.serviceUrl = url; + this.wsDef = webServiceDef; + } + + + /** + * Makes a request to the target web service + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // Generate XML + HttpURL url = generateRESTRequest(method.getName(), args); + + // Send request + HttpClient request = new HttpClient(HttpClient.HttpRequestType.POST); + request.setURL(url); + HttpHeaderParser response = request.send(); + String rspJson = IOUtil.readContentAsString(request.getResponseInputStream()); + request.close(); + + // DEBUG + if (logger.isLoggable(Level.FINEST)) { + System.out.println("********** Request"); + System.out.println(url); + System.out.println("********** Response"); + System.out.println(rspJson); + } + + return parseRESTResponse(rspJson); + } + + + private HttpURL generateRESTRequest(String targetMethod, Object[] args) { + logger.fine("Sending request for " + targetMethod); + HttpURL url = new HttpURL(serviceUrl); + + WSMethodDef methodDef = wsDef.getMethod(targetMethod); + url.setPath(serviceUrl.getPath() + + (serviceUrl.getPath().endsWith("/") ? "" : "/") + + methodDef.getName()); + + for (int i = 0; i < methodDef.getOutputCount(); i++) { + WSParameterDef param = methodDef.getOutput(i); + url.setParameter(param.getName(), args[i].toString()); + } + + return url; + } + + private Object parseRESTResponse(String json) { + + return null; + } +} diff --git a/src/zutil/net/ws/soap/SOAPClientFactory.java b/src/zutil/net/ws/soap/SOAPClientFactory.java index da53f74..cca2382 100755 --- a/src/zutil/net/ws/soap/SOAPClientFactory.java +++ b/src/zutil/net/ws/soap/SOAPClientFactory.java @@ -45,7 +45,7 @@ public class SOAPClientFactory { * Generates a Client Object for the web service. * * @param is the class of the web service definition - * @param url is the target service url + * @param url is the target service serviceUrl * @param intf is the class of the web service definition * @return a client Object */ diff --git a/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java b/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java index 85b205a..d39a4a1 100755 --- a/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java +++ b/src/zutil/net/ws/soap/SOAPClientInvocationHandler.java @@ -44,20 +44,22 @@ import java.util.logging.Level; import java.util.logging.Logger; /** - * This is an abstract client that will do generic requests to a + * 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 */ + /** + * Web address of the web service + */ protected URL url; - public SOAPClientInvocationHandler(URL url, WebServiceDef wsDef){ + public SOAPClientInvocationHandler(URL url, WebServiceDef wsDef) { this.url = url; this.wsDef = wsDef; } @@ -69,10 +71,9 @@ public class SOAPClientInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Generate XML - Document document = genSOAPRequest((WSInterface)proxy, method.getName(), args); + Document document = genSOAPRequest((WSInterface) proxy, method.getName(), args); String reqXml = document.asXML(); - // Send request HttpClient request = new HttpClient(HttpClient.HttpRequestType.POST); request.setURL(url); @@ -82,7 +83,7 @@ public class SOAPClientInvocationHandler implements InvocationHandler { request.close(); // DEBUG - if( logger.isLoggable(Level.FINEST) ){ + if (logger.isLoggable(Level.FINEST)) { System.out.println("********** Request"); System.out.println(reqXml); System.out.println("********** Response"); @@ -93,23 +94,23 @@ public class SOAPClientInvocationHandler implements InvocationHandler { } - private Document genSOAPRequest(WSInterface obj, String targetMethod, Object[] args){ - logger.fine("Sending request for "+targetMethod); + private Document genSOAPRequest(WSInterface obj, String targetMethod, Object[] args) { + logger.fine("Sending request for " + targetMethod); Document document = DocumentHelper.createDocument(); Element envelope = document.addElement("soap:Envelope"); - WSMethodDef methodDef = wsDef.getMethod( targetMethod ); + 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 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