diff --git a/src/zutil/Hasher.java b/src/zutil/Hasher.java index bfd98eb..7e7a067 100644 --- a/src/zutil/Hasher.java +++ b/src/zutil/Hasher.java @@ -9,6 +9,8 @@ import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import zutil.converters.Converter; + public class Hasher { /** diff --git a/src/zutil/Converter.java b/src/zutil/converters/Converter.java similarity index 95% rename from src/zutil/Converter.java rename to src/zutil/converters/Converter.java index 5199535..b43d152 100644 --- a/src/zutil/Converter.java +++ b/src/zutil/converters/Converter.java @@ -1,4 +1,4 @@ -package zutil; +package zutil.converters; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; diff --git a/src/zutil/converters/WGS84Converter.java b/src/zutil/converters/WGS84Converter.java new file mode 100644 index 0000000..011802a --- /dev/null +++ b/src/zutil/converters/WGS84Converter.java @@ -0,0 +1,48 @@ +package zutil.converters; + +public class WGS84Converter { + public static void main(String[] args){ + System.out.println(toWGS84Decimal("N 59° 47' 43\"")+" "+toWGS84Decimal(" E 17° 42' 55\"")); + System.out.println(toWGS84Decimal("55° 0' 0\"")+" "+toWGS84Decimal("68° 59' 59,999\"")); + System.out.println(toWGS84Decimal("55° 0.001'")+" "+toWGS84Decimal("68° 59.999'")); + System.out.println(toWGS84Decimal("3444.0000S")+" "+toWGS84Decimal("13521.0000E")); + System.out.println(toWGS84Decimal("-44.0001")+" "+toWGS84Decimal("521.0001")); + } + + /** + * Converts an WGS84 coordinate to an WGS84 decimal coordinate + * + * @param coordinate is the coordinate to convert + * @return the new coordinate in decimal degrees, returns 0 if conversions fails + */ + public static float toWGS84Decimal(String coordinate){ + float deg=0, min=0, sec=0, neg=1; + coordinate = coordinate.trim().replaceAll(",", ".").toUpperCase(); + if(coordinate.contains("S") || coordinate.contains("W")) + neg = -1; + + // 55° 0' 68° 59,999 or 55° 0' 0" 68° 59' 59,999" + if(coordinate.matches("[NSWE ]? ?[0-9]{1,3}° [0-9]{1,2}.?[0-9]*'[ 0-9.\\\"]*")){ + coordinate = coordinate.replaceAll("[NSEW°'\\\"]", "").trim(); + String[] tmp = coordinate.split(" "); + deg = Float.parseFloat(tmp[0]); + min = Float.parseFloat(tmp[1]); + if(tmp.length > 2){ + sec = Float.parseFloat(tmp[2]); + } + } + // 3444.0000S 13521.0000E + else if(coordinate.matches("[0-9]{4,5}.[0-9]*[NSEW]{1}")){ + coordinate = coordinate.replaceAll("[NS EW]", ""); + float tmpf = Float.parseFloat(coordinate); + deg = (int)(tmpf/100); + min = tmpf-(deg*100); + } + // 55.0 68.99999 + else if(coordinate.matches("\\-?[0-9]{2,3}.[0-9]*")){ + return Float.parseFloat(coordinate); + } + + return neg*(deg + min/60 + sec/3600); + } +} diff --git a/src/zutil/db/MySQLQueue.java b/src/zutil/db/MySQLQueue.java index bf47812..15d50e0 100644 --- a/src/zutil/db/MySQLQueue.java +++ b/src/zutil/db/MySQLQueue.java @@ -7,8 +7,8 @@ import java.util.Collection; import java.util.Iterator; import java.util.Queue; -import zutil.Converter; import zutil.MultiPrintStream; +import zutil.converters.Converter; /** * This class creates a queue that stors the diff --git a/src/zutil/network/http/HttpPage.java b/src/zutil/network/http/HttpPage.java index 4cf6854..174f13b 100644 --- a/src/zutil/network/http/HttpPage.java +++ b/src/zutil/network/http/HttpPage.java @@ -22,7 +22,7 @@ public interface HttpPage{ */ public abstract void respond(HttpPrintStream out, HashMap client_info, - HashMap session, + HashMap session, HashMap cookie, HashMap request); } \ No newline at end of file diff --git a/src/zutil/network/http/HttpPrintStream.java b/src/zutil/network/http/HttpPrintStream.java index fff1ffc..8d934d6 100644 --- a/src/zutil/network/http/HttpPrintStream.java +++ b/src/zutil/network/http/HttpPrintStream.java @@ -11,7 +11,9 @@ import java.util.HashMap; * @author Ziver * */ -public class HttpPrintStream extends PrintStream{ +public class HttpPrintStream extends PrintStream{ + private Integer status_code; + private HashMap header; private HashMap cookie; private StringBuffer buffer; private boolean buffer_enabled; @@ -19,6 +21,8 @@ public class HttpPrintStream extends PrintStream{ public HttpPrintStream(OutputStream out) { super(out); + status_code = 0; + header = new HashMap(); cookie = new HashMap(); buffer = new StringBuffer(); buffer_enabled = false; @@ -27,12 +31,15 @@ public class HttpPrintStream extends PrintStream{ /** * Enable the buffering capability of the PrintStream. * Nothing will be sent to the client when buffering - * is enabled until you close or flush the stream. + * is enabled until you close or flush the stream. + * This function will flush the stream if buffering is + * disabled. * * @param b */ public void enableBuffering(boolean b){ buffer_enabled = b; + if(!buffer_enabled) flush(); } /** @@ -49,16 +56,28 @@ public class HttpPrintStream extends PrintStream{ } /** - * Sends the given header directly to the client. - * No buffering involved. + * Adds an header value * - * @param header is the header to send + * @param key is the header name + * @param value is the value of the header * @throws Exception Throws exception if the header has already been sent */ - public void sendHeader(String header) throws Exception{ - if(cookie == null) + public void setHeader(String key, String value) throws Exception{ + if(header == null) throw new Exception("Header already sent!!!"); - super.print(header+"\n"); + header.put(key, value); + } + + /** + * Sets the return status code + * + * @param code the code from 100 up to 599 + * @throws Exception Throws exception if the header has already been sent + */ + public void setStatusCode(int code) throws Exception{ + if(status_code == null) + throw new Exception("Header already sent!!!"); + status_code = code; } /** @@ -74,7 +93,7 @@ public class HttpPrintStream extends PrintStream{ public void print(String s){ printOrBuffer(s); } - + /** * prints to all */ @@ -83,11 +102,24 @@ public class HttpPrintStream extends PrintStream{ buffer.append(s); } else{ + if(status_code != null){ + super.print("HTTP/1.0 "+status_code+" "+getStatusString(status_code)); + super.println(); + status_code = null; + } + if(header != null){ + for(String key : header.keySet()){ + super.print(key+": "+header.get(key)); + super.println(); + } + header = null; + } if(cookie != null){ for(String key : cookie.keySet()){ - super.print("Set-Cookie: "+key+"="+cookie.get(key)+"; \n"); + super.print("Set-Cookie: "+key+"="+cookie.get(key)+";"); + super.println(); } - super.print(" \n"); + super.println(); cookie = null; } super.print(s); @@ -103,15 +135,18 @@ public class HttpPrintStream extends PrintStream{ printOrBuffer(buffer.toString()); buffer.delete(0, buffer.length()); buffer_enabled = true; - } + } + else if(status_code != null || header != null || cookie != null){ + printOrBuffer(""); + } super.flush(); } - + public void close(){ flush(); super.close(); } - + public void println(){ println("");} public void println(boolean x){ println(String.valueOf(x));} public void println(char x){ println(String.valueOf(x));} @@ -121,7 +156,7 @@ public class HttpPrintStream extends PrintStream{ public void println(int x){ println(String.valueOf(x));} public void println(long x){ println(String.valueOf(x));} public void println(Object x){ println(String.valueOf(x));} - + public void print(boolean x){ printOrBuffer(String.valueOf(x));} public void print(char x){ printOrBuffer(String.valueOf(x));} public void print(char[] x){ printOrBuffer(new String(x));} @@ -130,4 +165,25 @@ public class HttpPrintStream extends PrintStream{ public void print(int x){ printOrBuffer(String.valueOf(x));} public void print(long x){ printOrBuffer(String.valueOf(x));} public void print(Object x){ printOrBuffer(String.valueOf(x));} + + /* + public void write(int b) { print((char)b);} + public void write(byte buf[], int off, int len){ + print(new String(buf, off, len));} + */ + private String getStatusString(int type){ + switch(type){ + case 100: return "Continue"; + case 200: return "OK"; + case 301: return "Moved Permanently"; + case 307: return "Temporary Redirect"; + case 400: return "Bad Request"; + case 401: return "Unauthorized"; + case 403: return "Forbidden"; + case 404: return "Not Found"; + case 500: return "Internal Server Error"; + case 501: return "Not Implemented"; + default: return ""; + } + } } diff --git a/src/zutil/network/http/HttpServer.java b/src/zutil/network/http/HttpServer.java index f3c6463..f86d79c 100644 --- a/src/zutil/network/http/HttpServer.java +++ b/src/zutil/network/http/HttpServer.java @@ -11,12 +11,14 @@ import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.cert.CertificateException; import java.util.HashMap; +import java.util.Timer; +import java.util.TimerTask; +import java.util.regex.Pattern; import javax.net.ssl.SSLServerSocketFactory; import zutil.MultiPrintStream; - /** * A simple web server that handles both cookies and * sessions for all the clients @@ -27,7 +29,7 @@ public class HttpServer extends Thread{ public static final boolean DEBUG = false; public static final String SERVER_VERSION = "StaticInt HttpServer 1.0"; public static final int COOKIE_TTL = 200; - public static final int SESSION_TTL = 3600*3*1000; // in ms + public static final int SESSION_TTL = 10*60*1000; // in milliseconds public final String server_url; public final int server_port; @@ -36,7 +38,7 @@ public class HttpServer extends Thread{ private HashMap pages; private HttpPage defaultPage; - private HashMap> sessions; + private HashMap> sessions; private int nextSessionId; /** @@ -65,8 +67,33 @@ public class HttpServer extends Thread{ this.keyStore = keyStore; pages = new HashMap(); - sessions = new HashMap>(); + sessions = new HashMap>(); nextSessionId = 0; + + Timer timer = new Timer(); + timer.schedule(new GarbageCollector(), 0, SESSION_TTL / 2); + } + + /** + * This class acts as an garbage collector that + * removes old sessions from the session HashMap + * + * @author Ziver + */ + private class GarbageCollector extends TimerTask { + public void run(){ + synchronized(sessions) { + for(String key : sessions.keySet()){ + HashMap client_session = sessions.get(key); + + // Check if session is still valid + if((Long)client_session.get("ttl") < System.currentTimeMillis()){ + sessions.remove(key); + if(DEBUG) MultiPrintStream.out.println("Removing Session: "+key); + } + } + } + } } /** @@ -155,7 +182,10 @@ public class HttpServer extends Thread{ public void run(){ String tmp = null; - int tmpi; + String[] tmpArray, tmpArray2; + Pattern colonPattern = Pattern.compile(":"); + Pattern semiColonPattern = Pattern.compile(";"); + Pattern equalPattern = Pattern.compile("="); String page_url = ""; HashMap client_info = new HashMap(); @@ -165,7 +195,7 @@ public class HttpServer extends Thread{ //**************************** REQUEST ********************************* try { if(DEBUG)MultiPrintStream.out.println("Reciving Http Request!!!"); - while(!(tmp=in.readLine()).isEmpty()){ + while((tmp=in.readLine()) != null && !tmp.isEmpty()){ //System.err.println(tmp); //*********** Handling Get variables if(tmp.startsWith("GET")){ @@ -181,28 +211,21 @@ public class HttpServer extends Thread{ } //********* Handling Cookies else if(tmp.startsWith("Cookie")){ - tmp = tmp.substring(tmp.indexOf(':')+1, tmp.length()); - while(!tmp.isEmpty()){ - tmpi = ( (tmpi = tmp.indexOf(';')) == -1 ? tmp.length() : tmpi); + tmp = colonPattern.split(tmp)[1]; + tmpArray = semiColonPattern.split(tmp); + for(String e : tmpArray){ + tmpArray2 = equalPattern.split(e); cookie.put( - (tmp.substring(0, tmp.indexOf('=')).trim() ), // Key - (tmp.substring(tmp.indexOf('=')+1, tmpi)).trim() ); //Value - if(tmp.indexOf(';') > 0) - tmp = tmp.substring(tmp.indexOf(';')+1, tmp.length()); - else - break; + tmpArray2[0].trim(), // Key + (tmpArray2.length>1 ? tmpArray2[1] : "").trim()); //Value } } //********* Handling Client info else{ - if(tmp.indexOf(':') > -1){ - client_info.put( - (tmp.substring(0, tmp.indexOf(':')).trim() ), // Key - (tmp.substring(tmp.indexOf(':')+1, tmp.length())).trim() ); //Value - } - else{ - MultiPrintStream.out.println("Faild to parsse header: "+tmp); - } + tmpArray = colonPattern.split(tmp); + client_info.put( + tmpArray[0].trim(), // Key + (tmpArray.length>1 ? tmpArray[1] : "").trim()); //Value } } @@ -210,8 +233,7 @@ public class HttpServer extends Thread{ if(client_info.containsKey("Content-Length")){ // Reads the post data size tmp = client_info.get("Content-Length"); - int post_data_length = Integer.parseInt( - tmp.substring(tmp.indexOf(':')+1, tmp.length()).trim() ); + int post_data_length = Integer.parseInt( tmp ); // read the data StringBuffer tmpb = new StringBuffer(); // read the data @@ -230,44 +252,31 @@ public class HttpServer extends Thread{ request.put("" , tmpb.toString()); } else if(client_info.get("Content-Type").contains("multipart/form-data")){ - // TODO: File upload + // TODO: File upload throw new Exception("\"multipart-form-data\" Not implemented!!!"); } } - //***************** - } catch (Exception e) { - e.printStackTrace(); - try { - out.sendHeader("HTTP/1.0 500 ERROR"); - } catch (Exception e1) {} - if(e.getMessage() != null) - out.println("500 Internal Error(Header: "+tmp+"): "+e.getMessage()); - else{ - out.println("500 Internal Error(Header: "+tmp+"): "+e.getCause().getMessage()); - } - } - try { + //**************************** HANDLE REQUEST ********************************* // Get the client session or create one - HashMap client_session; + HashMap client_session; long ttl_time = System.currentTimeMillis()+SESSION_TTL; if(cookie.containsKey("session_id") && sessions.containsKey(cookie.get("session_id"))){ client_session = sessions.get(cookie.get("session_id")); // Check if session is still valid - if(Long.parseLong(client_session.get("ttl")) < System.currentTimeMillis()){ - int session_id = Integer.parseInt(client_session.get("session_id")); - client_session = new HashMap(); - client_session.put("session_id", ""+session_id); + if((Long)client_session.get("ttl") < System.currentTimeMillis()){ + int session_id = (Integer)client_session.get("session_id"); + client_session = new HashMap(); + client_session.put("session_id", session_id); sessions.put(""+session_id, client_session); } // renew the session TTL - - client_session.put("ttl", ""+ttl_time); + client_session.put("ttl", ttl_time); } else{ - client_session = new HashMap(); - client_session.put("session_id", ""+nextSessionId); - client_session.put("ttl", ""+ttl_time); + client_session = new HashMap(); + client_session.put("session_id", nextSessionId); + client_session.put("ttl", ttl_time); sessions.put(""+nextSessionId, client_session); nextSessionId++; } @@ -281,10 +290,10 @@ public class HttpServer extends Thread{ } //**************************** RESPONSE ************************************ if(DEBUG)MultiPrintStream.out.println("Sending Http Response!!!"); - out.sendHeader("HTTP/1.0 200 OK"); - out.sendHeader("Server: "+SERVER_VERSION); - out.sendHeader("Content-Type: text/html"); - out.setCookie("session_id", client_session.get("session_id")); + out.setStatusCode(200); + out.setHeader("Server", SERVER_VERSION); + out.setHeader("Content-Type", "text/html"); + out.setCookie("session_id", ""+client_session.get("session_id")); if(!page_url.isEmpty() && pages.containsKey(page_url)){ pages.get(page_url).respond(out, client_info, client_session, cookie, request); @@ -293,13 +302,21 @@ public class HttpServer extends Thread{ defaultPage.respond(out, client_info, client_session, cookie, request); } else{ - out.println("404 ERROR"); + out.setStatusCode(404); + out.println("404 Page Not Found"); } //******************************************************************************** } catch (Exception e) { - e.printStackTrace(); - out.println("500 Internal Error: "+e.getMessage()); + e.printStackTrace(MultiPrintStream.out); + try { + out.setStatusCode(500); + } catch (Exception e1) {} + if(e.getMessage() != null) + out.println("500 Internal Server Error(Header: "+tmp+"): "+e.getMessage()); + else{ + out.println("500 Internal Server Error(Header: "+tmp+"): "+e.getCause().getMessage()); + } } try{ @@ -308,7 +325,7 @@ public class HttpServer extends Thread{ in.close(); socket.close(); } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(MultiPrintStream.out); } } } @@ -351,8 +368,8 @@ public class HttpServer extends Thread{ tmp = element.indexOf('='); if(tmp > 0){ map.put( - element.substring(0, tmp ).trim(), // Key - element.substring(tmp+1, element.length() ).trim() ); //Value + element.substring(0, tmp ).trim(), // Key + element.substring(tmp+1, element.length() ).trim() ); //Value } else{ map.put(element, ""); diff --git a/src/zutil/network/http/soap/SOAPHttpPage.java b/src/zutil/network/http/soap/SOAPHttpPage.java index 1335f2c..1fe526a 100644 --- a/src/zutil/network/http/soap/SOAPHttpPage.java +++ b/src/zutil/network/http/soap/SOAPHttpPage.java @@ -1,5 +1,6 @@ package zutil.network.http.soap; +import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.Field; @@ -16,6 +17,7 @@ import javax.wsdl.BindingOperation; import javax.wsdl.BindingOutput; import javax.wsdl.Definition; import javax.wsdl.Fault; +import javax.wsdl.Import; import javax.wsdl.Input; import javax.wsdl.Message; import javax.wsdl.Operation; @@ -34,6 +36,13 @@ import javax.wsdl.factory.WSDLFactory; import javax.wsdl.xml.WSDLWriter; import javax.xml.namespace.QName; +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.MultiPrintStream; + import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; @@ -43,18 +52,40 @@ import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.xml.sax.SAXException; -import zutil.MultiPrintStream; -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 com.ibm.wsdl.extensions.PopulatedExtensionRegistry; import com.ibm.wsdl.extensions.soap.SOAPConstants; import com.sun.org.apache.xerces.internal.dom.DocumentImpl; - +/** + * This is an HTTPPage for the HTTPServer that + * handles soap messages. + * + * TODO: Read SOAPObjects as input parameter + * TODO: Ability to have multiple arrays of same SOAPObject + * + * Features: + * Input: + *
-int + *
-double + *
-float + *
-char + *
-String + *
-byte[] + *
-And the Wrappers except byte + * + * Output: + *
-SOAPObjects + *
-byte[] + *
-int + *
-double + *
-float + *
-char + *
-String + *
-Arrays of Output + *
-And the Wrappers except byte + * + * @author Ziver + */ public class SOAPHttpPage implements HttpPage{ // valid methods for this soap page private HashMap methods; @@ -81,17 +112,20 @@ public class SOAPHttpPage implements HttpPage{ private Document wsdlType; // the URL to this soap page private String url; + // Session enabled + private boolean session_enabled; public SOAPHttpPage(String url, SOAPInterface interf) throws WSDLException{ //if(!SOAPInterface.class.isAssignableFrom(interf) ) // throw new ClassCastException("Class does not implement SOAPInterface!"); this.url = url; this.interf = interf; + this.session_enabled = false; methods = new HashMap(); for(Method m : interf.getClass().getDeclaredMethods()){ // check for public methods - if(m.getModifiers() == Modifier.PUBLIC && + if((m.getModifiers() & Modifier.PUBLIC) > 0 && !m.isAnnotationPresent(SOAPInterface.SOAPDisabled.class)){ MethodChasch chasch = new MethodChasch(m); StringBuffer tmp = new StringBuffer(m.getName()+"("); @@ -150,18 +184,21 @@ public class SOAPHttpPage implements HttpPage{ } } - + public void enableSession(boolean enabled){ + this.session_enabled = enabled; + } + + public void respond(HttpPrintStream out, HashMap client_info, - HashMap session, HashMap cookie, + HashMap session, HashMap cookie, HashMap request) { try { - out.sendHeader("Content-Type: text/xml"); + out.setHeader("Content-Type", "text/xml"); + out.flush(); if(request.containsKey("wsdl")){ - out.println(""); - out.flush(); WSDLWriter writer = WSDLFactory.newInstance().newWSDLWriter(); writer.writeWSDL(wsdl, out); } @@ -171,33 +208,52 @@ public class SOAPHttpPage implements HttpPage{ writer.write( wsdlType ); } else{ - Document document = soap( request.get("") ); + SOAPInterface obj = null; + if(session_enabled && session.containsKey("SOAPInterface")) + obj = (SOAPInterface)session.get("SOAPInterface"); + else{ + obj = interf.getClass().newInstance(); + if(session_enabled) session.put("SOAPInterface", obj); + } + + Document document = soapResponse( request.get(""), obj); OutputFormat format = OutputFormat.createPrettyPrint(); XMLWriter writer = new XMLWriter( out, format ); writer.write( document ); } } catch (Exception e) { - e.printStackTrace(MultiPrintStream.out); + e.printStackTrace(MultiPrintStream.out); } - + } + + /** + * Generates a soap response for the given + * @param xml is the XML request + * @return a Document with the response + */ + public Document soapResponse(String xml){ + try { + return soapResponse(xml, interf.getClass().newInstance()); + } catch (Exception e) { + e.printStackTrace(); + } + return null; } - public Document soap(String xml){ + protected Document soapResponse(String xml, SOAPInterface obj){ try { Document document = DocumentHelper.createDocument(); Element envelope = document.addElement("soap:Envelope"); envelope.add(new Namespace("soap", "http://www.w3.org/2001/12/soap-envelope")); envelope.addAttribute("soap:encodingStyle", "http://www.w3.org/2001/12/soap-encoding"); - + Element header = envelope.addElement( "soap:Header" ); Element body = envelope.addElement( "soap:Body" ); try{ Element request = getXMLRoot(xml); - Object obj = interf.getClass().newInstance(); // Header if( request.element("Header") != null){ - Element header = envelope.addElement( "soap:Header" ); prepareInvoke( obj, request.element("Header"), header ); } @@ -280,10 +336,18 @@ public class SOAPHttpPage implements HttpPage{ * @param m is the method that returned the ret */ private void createReturnXML(Element root, Object ret, String ename, MethodChasch m) throws IllegalArgumentException, IllegalAccessException{ + if(ret == null) return; + if(byte[].class.isAssignableFrom(ret.getClass())){ + Element valueE = root.addElement( ename ); + valueE.addAttribute("type", "xsd:"+getClassSOAPName(ret.getClass())); + String tmp = new sun.misc.BASE64Encoder().encode((byte[])ret); + tmp = tmp.replaceAll("\\s", ""); + valueE.setText(tmp); + } // return an array - if(ret.getClass().isArray()){ + else if(ret.getClass().isArray()){ Element array = root.addElement( (ename.equals("element") ? "Array" : ename) ); - String arrayType = "xsd:"+ret.getClass().getSimpleName().toLowerCase(); + String arrayType = "xsd:"+getClassSOAPName(ret.getClass()); arrayType = arrayType.replaceFirst("\\[\\]", "["+Array.getLength(ret)+"]"); array.addAttribute("type", "soap:Array"); @@ -296,7 +360,7 @@ public class SOAPHttpPage implements HttpPage{ if(ret instanceof Element) root.add( (Element)ret ); if(ret instanceof SOAPObject){ - Element objectE = root.addElement( ret.getClass().getSimpleName().toLowerCase() ); + Element objectE = root.addElement( getClassSOAPName(ret.getClass()) ); Field[] fields = ret.getClass().getFields(); for(int i=0; i c){ + protected Object convertToClass(String data, Class 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); @@ -334,6 +398,8 @@ public class SOAPHttpPage implements HttpPage{ 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; } @@ -344,7 +410,7 @@ public class SOAPHttpPage implements HttpPage{ * @param params a vector with arguments * @throws Throwable */ - public Object invoke(Object obj, Method m, Object[] params) throws Throwable{ + protected Object invoke(Object obj, Method m, Object[] params) throws Throwable{ try { return m.invoke(obj, params ); } catch (IllegalArgumentException e) { @@ -362,13 +428,31 @@ public class SOAPHttpPage implements HttpPage{ * @param msg is the string XML * @return the XML root Element */ - public Element getXMLRoot(String xml) throws Exception { + private Element getXMLRoot(String xml) throws Exception { if(xml != null && !xml.isEmpty()){ Document document = DocumentHelper.parseText(xml); return document.getRootElement(); } return null; } + + private String getClassSOAPName(Class c){ + Class cTmp = getClass(c); + if(byte[].class.isAssignableFrom(c)){ + return "base64Binary"; + } + else if( SOAPObject.class.isAssignableFrom(cTmp) ){ + return c.getSimpleName(); + } + else{ + String ret = c.getSimpleName().toLowerCase(); + + if(cTmp == Integer.class) ret = ret.replaceAll("integer", "int"); + else if(cTmp == Character.class)ret = ret.replaceAll("character", "char"); + + return ret; + } + } /** * Generates an WSDL document for the class @@ -377,14 +461,15 @@ public class SOAPHttpPage implements HttpPage{ */ private void generateWSDL() throws WSDLException{ ArrayList> types = new ArrayList>(); - - PopulatedExtensionRegistry extReg = new PopulatedExtensionRegistry(); - WSDLFactory factory = WSDLFactory.newInstance(); + String tns = url+"?wsdl"; String xsd = "http://www.w3.org/2001/XMLSchema"; String soap = "http://schemas.xmlsoap.org/wsdl/soap/"; String wsdln = "http://schemas.xmlsoap.org/wsdl/"; String td = url+"?type"; + + PopulatedExtensionRegistry extReg = new PopulatedExtensionRegistry(); + WSDLFactory factory = WSDLFactory.newInstance(); String portTypeName = this.interf.getClass().getSimpleName()+"PortType"; wsdl = factory.newDefinition(); @@ -406,12 +491,11 @@ public class SOAPHttpPage implements HttpPage{ wsdl.addMessage(exception); // Types import - /* Import imp = wsdl.createImport(); imp.setNamespaceURI(td); imp.setLocationURI(td); wsdl.addImport(imp); - */ + // PrtType PortType portType = wsdl.createPortType(); portType.setQName(new QName(tns, portTypeName)); @@ -438,8 +522,8 @@ public class SOAPHttpPage implements HttpPage{ // Parts Part part = wsdl.createPart(); part.setName(m.paramName[i]); - part.setTypeName(new QName(xsd, - m.method.getParameterTypes()[i].getSimpleName().toLowerCase())); + part.setTypeName(new QName( xsd, + getClassSOAPName(m.method.getParameterTypes()[i]))); if(m.paramOptional[i]) part.getExtensionAttribute(new QName("minOccurs", "0")); msgIn.addPart(part); @@ -462,34 +546,26 @@ public class SOAPHttpPage implements HttpPage{ // Generate new type if the object is an SOAPObject Class cTmp = getClass(m.method.getReturnType()); - if(( SOAPObject.class.isAssignableFrom(cTmp) )){ - // is is an array? - if(m.method.getReturnType().isArray()){ - part.setTypeName(new QName(soap, "Array")); - part.setExtensionAttribute( - new QName(soap, "arrayType"), - new QName(td, m.method.getReturnType().getSimpleName().toLowerCase())); - } - else{ // its an Object - part.setTypeName(new QName(td, - m.method.getReturnType().getSimpleName().toLowerCase())); - } + if(byte[].class.isAssignableFrom(m.method.getReturnType())){ + part.setTypeName(new QName(xsd, "base64Binary")); + } + // is an array? + else if(m.method.getReturnType().isArray()){ + part.setTypeName(new QName(td, + "ArrayOf"+getClassSOAPName(m.method.getReturnType()).replaceAll("[\\[\\]]", ""))); + // add to type generation list + if(!types.contains(m.method.getReturnType())) + types.add(m.method.getReturnType()); + } + else if( SOAPObject.class.isAssignableFrom(cTmp) ){ + // its an SOAPObject + part.setTypeName(new QName(td, getClassSOAPName(m.method.getReturnType()))); // add to type generation list if(!types.contains(cTmp)) types.add(cTmp); } - else{ - // is is an array? - if(m.method.getReturnType().isArray()){ - part.setTypeName(new QName(soap, "Array")); - part.setExtensionAttribute( - new QName(soap, "arrayType"), - new QName(xsd, m.method.getReturnType().getSimpleName().toLowerCase())); - } - else{ // its an Object - part.setTypeName(new QName(xsd, - m.method.getReturnType().getSimpleName().toLowerCase())); - } + else{// its an Object + part.setTypeName(new QName(xsd, getClassSOAPName(m.method.getReturnType()))); } wsdl.addMessage(msgOut); @@ -529,7 +605,7 @@ public class SOAPHttpPage implements HttpPage{ SOAPBinding soapBinding = (SOAPBinding)extReg.createExtension(Binding.class, SOAPConstants.Q_ELEM_SOAP_BINDING); soapBinding.setStyle("rpc"); - soapBinding.setRequired(true); + //soapBinding.setRequired(true); soapBinding.setTransportURI("http://schemas.xmlsoap.org/soap/http"); binding.addExtensibilityElement(soapBinding); @@ -588,6 +664,7 @@ public class SOAPHttpPage implements HttpPage{ port.addExtensibilityElement(addr); Service ser = wsdl.createService(); + ser.setQName(new QName(tns, interf.getClass().getSimpleName()+"Service")); ser.addPort(port); wsdl.addService(ser); @@ -603,42 +680,66 @@ public class SOAPHttpPage implements HttpPage{ private void generateWSDLType(ArrayList> types){ wsdlType = DocumentHelper.createDocument(); Element definitions = wsdlType.addElement( "wsdl:definitions" ); - definitions.addNamespace("targetNamespace", url+"?type"); + definitions.addAttribute("targetNamespace", url+"?type"); definitions.addNamespace("xsd", "http://www.w3.org/2001/XMLSchema"); - definitions.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/"); + definitions.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/"); + definitions.addNamespace("SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"); Element typeE = definitions.addElement("wsdl:types"); Element schema = typeE.addElement("xsd:schema"); for(int n=0; n c = types.get(n); - Element type = schema.addElement("xsd:complexType"); - type.addAttribute("name", c.getSimpleName().toLowerCase()); + // Generate Array type + if(c.isArray()){ + Class ctmp = getClass(c); + + Element type = schema.addElement("xsd:complexType"); + type.addAttribute("name", + "ArrayOf"+getClassSOAPName(c).replaceAll("[\\[\\]]", "")); + Element complexContent = type.addElement("complexContent"); + + Element restriction = complexContent.addElement("restriction"); + restriction.addAttribute("base", "SOAP-ENC:Array"); + + Element attribute = restriction.addElement("attribute"); + attribute.addAttribute("ref", "SOAP-ENC:arrayType"); + attribute.addAttribute("wsdl:arrayType", "tns:"+getClassSOAPName(c)); + + if(!types.contains(ctmp)) + types.add(ctmp); + } + // Generate SOAPObject type + else if(SOAPObject.class.isAssignableFrom(c)){ + Element type = schema.addElement("xsd:complexType"); + type.addAttribute("name", getClassSOAPName(c)); - Element sequence = type.addElement("xsd:sequence"); + Element sequence = type.addElement("xsd:sequence"); - Field[] fields = c.getFields(); - for(int i=0; i cTmp = getClass(fields[i].getType()); - if(SOAPObject.class.isAssignableFrom(cTmp)){ - element.addAttribute("type", "tns:"+cTmp.getSimpleName().toLowerCase()); - if(!types.contains(cTmp)) - types.add(cTmp); + // Check if the object is an SOAPObject + Class cTmp = getClass(fields[i].getType()); + if(SOAPObject.class.isAssignableFrom(cTmp)){ + element.addAttribute("type", "tns:"+getClassSOAPName(cTmp)); + if(!types.contains(cTmp)) + types.add(cTmp); + } + else{ + element.addAttribute("type", "xsd:"+getClassSOAPName(fields[i].getType())); + } + // Is the Field optional + if(tmp != null && tmp.optional()) + element.addAttribute("minOccurs", "0"); } - else - element.addAttribute("type", "xsd:"+cTmp.getSimpleName().toLowerCase()); - // Is the Field optional - if(tmp != null && tmp.optional()) - element.addAttribute("minOccurs", "0"); } } } @@ -650,88 +751,4 @@ public class SOAPHttpPage implements HttpPage{ return c; } - //******************************************************************************************* - //**************************** TEST ********************************************************* - - public static void main(String[] args){ - try { - new SOAPHttpPage("http://test.se:8080/", new Test()).test(); - } catch (WSDLException e) { - e.printStackTrace(); - } - } - - private static class TestObject2 implements SOAPObject{ - public String lol = "lol11"; - public String lol2 = "lol22"; - } - - private static class TestObject implements SOAPObject{ - @SOAPFieldName(value="lolz", optional=true) - public String lol = "lol1"; - @SOAPFieldName("lolx") - public String lol2 = "lol2"; - public TestObject2 l = new TestObject2(); - } - - private static class Test implements SOAPInterface{ - public Test(){} - - @SOAPHeader() - @WSDLDocumentation("hello") - public void pubZ( - @SOAPParamName(value="olle", optional=true) int lol) 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 TestObject[] pubX ( - @SOAPParamName("Ztring") String lol) throws Exception{ - return new TestObject[]{new TestObject(), new TestObject()}; - } - - @SOAPDisabled() - public void privaZ(){ } - protected void protZ(){ } - } - - public void test(){ - // Response - try { - Document document = soap( - "" + - "\n" + - " \n" + - //" \n" + - //" IBM\n" + - //" \n" + - //" \n" + - //" 66\n" + - //" \n" + - " \n" + - " IBM\n" + - " \n" + - " \n" + - ""); - System.out.println(); - - OutputFormat format = OutputFormat.createPrettyPrint(); - XMLWriter writer = new XMLWriter( System.out, format ); - writer.write( document ); - - System.out.println(); - } catch (Exception e) { - e.printStackTrace(); - } - } } diff --git a/src/zutil/network/http/soap/SOAPObject.java b/src/zutil/network/http/soap/SOAPObject.java index e2ef5a1..7e5906a 100644 --- a/src/zutil/network/http/soap/SOAPObject.java +++ b/src/zutil/network/http/soap/SOAPObject.java @@ -40,4 +40,17 @@ public interface SOAPObject{ String value(); boolean optional() default false; } + + /** + * This generates an documentation tag in the + * WSDL for the object type + * + * @author Ziver + */ + /* + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface WSDLDocumentation { + String value(); + }*/ } \ No newline at end of file diff --git a/src/zutil/network/nio/NioNetwork.java b/src/zutil/network/nio/NioNetwork.java index ea8f442..2a29e68 100644 --- a/src/zutil/network/nio/NioNetwork.java +++ b/src/zutil/network/nio/NioNetwork.java @@ -15,9 +15,9 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import zutil.Converter; import zutil.Encrypter; import zutil.MultiPrintStream; +import zutil.converters.Converter; import zutil.network.nio.message.type.ResponseRequestMessage; import zutil.network.nio.message.type.SystemMessage; import zutil.network.nio.response.ResponseEvent; diff --git a/src/zutil/test/HTTPGuessTheNumber.java b/src/zutil/test/HTTPGuessTheNumber.java index ad94f26..7671cab 100644 --- a/src/zutil/test/HTTPGuessTheNumber.java +++ b/src/zutil/test/HTTPGuessTheNumber.java @@ -7,18 +7,19 @@ import zutil.network.http.HttpPage; import zutil.network.http.HttpPrintStream; import zutil.network.http.HttpServer; + public class HTTPGuessTheNumber implements HttpPage{ public static void main(String[] args) throws IOException{ //HttpServer server = new HttpServer("localhost", 443, FileFinder.find("keySSL"), "rootroot");//SSL - HttpServer server = new HttpServer("localhost", 80); + HttpServer server = new HttpServer("localhost", 8080); server.setDefaultPage(new HTTPGuessTheNumber()); server.run(); } public void respond(HttpPrintStream out, HashMap client_info, - HashMap session, HashMap cookie, + HashMap session, HashMap cookie, HashMap request) { out.enableBuffering(true); @@ -27,7 +28,7 @@ public class HTTPGuessTheNumber implements HttpPage{ if(session.containsKey("random_nummber") && request.containsKey("guess")){ int guess = Integer.parseInt(request.get("guess")); - int nummber = Integer.parseInt(session.get("random_nummber")); + int nummber = (Integer)session.get("random_nummber"); try { if(guess == nummber){ session.remove("random_nummber"); @@ -54,7 +55,7 @@ public class HTTPGuessTheNumber implements HttpPage{ } } else{ - session.put("random_nummber", ""+(int)(Math.random()*99+1)); + session.put("random_nummber", (int)(Math.random()*99+1)); try { out.setCookie("low", "0"); out.setCookie("high", "100"); @@ -73,7 +74,7 @@ public class HTTPGuessTheNumber implements HttpPage{ out.println(""); out.println(""); out.println(""); - //out.println("DEBUG: nummber="+session.get("random_nummber")+"
"); + out.println("DEBUG: nummber="+session.get("random_nummber")+"
"); out.println(""); } diff --git a/src/zutil/test/HTTPUploaderTest.java b/src/zutil/test/HTTPUploaderTest.java new file mode 100644 index 0000000..04ebc68 --- /dev/null +++ b/src/zutil/test/HTTPUploaderTest.java @@ -0,0 +1,37 @@ +package zutil.test; + +import java.io.IOException; +import java.util.HashMap; + +import zutil.network.http.HttpPage; +import zutil.network.http.HttpPrintStream; +import zutil.network.http.HttpServer; + + + +public class HTTPUploaderTest implements HttpPage{ + + public static void main(String[] args) throws IOException{ + HttpServer server = new HttpServer("localhost", 80); + server.setDefaultPage(new HTTPUploaderTest()); + server.run(); + } + + public void respond(HttpPrintStream out, + HashMap client_info, + HashMap session, HashMap cookie, + HashMap request) { + + if(!session.containsKey("file1")){ + out.println("" + + "
" + + "

Please specify a file, or a set of files:
" + + " " + + "

" + + " " + + "
" + + ""); + } + } + +} diff --git a/src/zutil/test/SOAPTest.java b/src/zutil/test/SOAPTest.java new file mode 100644 index 0000000..3d65aba --- /dev/null +++ b/src/zutil/test/SOAPTest.java @@ -0,0 +1,104 @@ +package zutil.test; + +import javax.wsdl.WSDLException; + +import org.dom4j.Document; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; + +import zutil.network.http.soap.SOAPHttpPage; +import zutil.network.http.soap.SOAPInterface; +import zutil.network.http.soap.SOAPObject; + +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.soapResponse( + "" + + "\n" + + " \n" + + //" \n" + + //" IBM\n" + + //" \n" + + //" \n" + + //" 66\n" + + //" \n" + + " \n" + + " IBM\n" + + " \n" + + " \n" + + ""); + System.out.println(); + + 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 SOAPTestClass implements SOAPInterface{ + public SOAPTestClass(){} + + @SOAPHeader() + @WSDLDocumentation("hello") + public void pubZ( + @SOAPParamName(value="olle", optional=true) int lol) 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 byte[] pubB ( + @SOAPParamName("byte") String lol) throws Exception{ + return new byte[]{0x12, 0x23}; + } + + @SOAPDisabled() + public void privaZ(){ } + protected void protZ(){ } +}