From 91cadbb3011a02b8997b3c42b8c4eb67212a817c Mon Sep 17 00:00:00 2001 From: Ziver Koc Date: Mon, 23 Mar 2015 21:05:51 +0000 Subject: [PATCH] --- src/zutil/converters/Converter.java | 27 ++++++- src/zutil/io/IOUtil.java | 23 +++++- src/zutil/io/file/FileSearch.java | 32 ++++---- src/zutil/io/file/FileUtil.java | 6 +- src/zutil/net/http/HttpPrintStream.java | 10 +-- src/zutil/net/http/HttpServer.java | 14 ++-- src/zutil/net/ssdp/SSDPClient.java | 40 +++++++--- src/zutil/net/ssdp/SSDPServer.java | 30 ++++--- src/zutil/net/ssdp/SSDPServiceInfo.java | 2 + src/zutil/net/ssdp/StandardSSDPInfo.java | 40 +++++++++- src/zutil/net/torrent/TorrentMetainfo.java | 2 +- src/zutil/osal/OSAbstractionLayer.java | 29 ++++--- src/zutil/parser/DataNode.java | 10 +-- src/zutil/parser/json/JSONParser.java | 9 ++- src/zutil/plugin/PluginData.java | 69 ++++++++++++---- src/zutil/plugin/PluginManager.java | 92 +++++++++++++++++----- src/zutil/test/ConverterTest.java | 31 +++++--- src/zutil/test/HTTPGuessTheNumber.java | 2 +- src/zutil/test/HTTPUploaderTest.java | 2 +- src/zutil/test/UPnPServerTest.java | 2 +- 20 files changed, 342 insertions(+), 130 deletions(-) diff --git a/src/zutil/converters/Converter.java b/src/zutil/converters/Converter.java index 69afe43..ec8d0ec 100644 --- a/src/zutil/converters/Converter.java +++ b/src/zutil/converters/Converter.java @@ -71,7 +71,28 @@ public class Converter { public static byte toByte(int num){ return (byte)(num & 0xff); } - + + /** + * Converts hex string to a byte array + * + * @param hex a String containing data coded in hex + * @return a byte array + */ + public static byte[] hexToByte(String hex){ + if(hex == null) + return null; + if(hex.startsWith("0x")) + hex = hex.substring(2); + byte[] b = new byte[(int)Math.ceil(hex.length()/2.0)]; + for(int i=hex.length()-1; i>=0; i-=2){ + if(i-1 < 0) + b[(hex.length()-i-1)/2] = hexToByte(hex.charAt(i)); + else + b[(hex.length()-i-1)/2] = hexToByte(hex.charAt(i-1), hex.charAt(i)); + } + return b; + } + /** * Converts hex chars to a byte * @@ -79,10 +100,10 @@ public class Converter { * @param quad2 is the second hex value * @return a byte that corresponds to the hex */ - public static int hexToByte( char quad1, char quad2){ + public static byte hexToByte( char quad1, char quad2){ byte b = hexToByte( quad2 ); b |= hexToByte( quad1 ) << 4; - return toInt(b); + return b; } /** diff --git a/src/zutil/io/IOUtil.java b/src/zutil/io/IOUtil.java index f0ad345..65ddf16 100644 --- a/src/zutil/io/IOUtil.java +++ b/src/zutil/io/IOUtil.java @@ -33,7 +33,8 @@ import java.io.*; public class IOUtil { /** - * Reads and returns all the contents of a stream. + * Reads and returns all the content of a stream. + * This function will close the inout stream at the end. * * @param stream * @return the stream contents @@ -45,10 +46,30 @@ public class IOUtil { while((len = stream.read(buff)) != -1){ dyn_buff.append(buff, 0, len); } + stream.close(); return dyn_buff.getBytes(); } + /** + * Reads and returns all the content of a stream as a String. + * This function will close the inout stream at the end. + * + * @param stream + * @return a String with the content of the stream + */ + public static String getContentString(InputStream stream) throws IOException{ + StringBuilder str = new StringBuilder(); + String line; + BufferedReader in = new BufferedReader(new InputStreamReader(stream)); + while((line = in.readLine()) != null){ + str.append(line).append("\n"); + } + in.close(); + + return str.toString(); + } + /** * Copies all data from the input stream to the output stream */ diff --git a/src/zutil/io/file/FileSearch.java b/src/zutil/io/file/FileSearch.java index 785f767..e797899 100644 --- a/src/zutil/io/file/FileSearch.java +++ b/src/zutil/io/file/FileSearch.java @@ -113,18 +113,19 @@ public class FileSearch implements Iterable{ protected class FileSearchIterator implements Iterator{ private ArrayList fileList; private int currentIndex; + private FileSearchItem nextItem; public FileSearchIterator(){ fileList = new ArrayList(); currentIndex = 0; - addFiles(root.list()); + addFiles(new FileSearchFileItem(root), root.list()); next(); } @Override public boolean hasNext() { - return currentIndex != fileList.size(); + return currentIndex < fileList.size(); } @Override @@ -134,28 +135,28 @@ public class FileSearch implements Iterable{ @Override public FileSearchItem next() { - if(currentIndex < 0) + if(currentIndex < 0 || currentIndex >= fileList.size()) return null; // Temporarily save the current file FileSearchItem ret = fileList.get(currentIndex); + currentIndex++; // Find the next file for(; currentIndex e = zipFile.entries(); while(e.hasMoreElements()){ ZipEntry entry = e.nextElement(); - fileList.add(new FileSearchZipItem(url, entry)); + fileList.add(new FileSearchZipItem(file.getPath(), entry)); } zipFile.close(); } catch (IOException e) { @@ -173,9 +174,12 @@ public class FileSearch implements Iterable{ return ret; } - private void addFiles(String[] list){ - for(String file : list){ - fileList.add(new FileSearchFileItem(new File(file))); + private void addFiles(FileSearchItem root, String[] list){ + if(root instanceof FileSearchFileItem) { + for (String file : list) { + fileList.add(new FileSearchFileItem( + new File(((FileSearchFileItem)root).file, file))); + } } } @@ -186,8 +190,8 @@ public class FileSearch implements Iterable{ public interface FileSearchItem{ /** @return a file or folder name **/ public String getName(); - /** @return a URL to the file or folder, in case of a compressed file the URL to the package will be returned **/ - public URL getUrl() throws MalformedURLException ; + /** @return a path to the file or folder, in case of a compressed file the path to the package will be returned **/ + public String getPath(); public boolean isCompressed(); public boolean isFile(); @@ -208,7 +212,7 @@ public class FileSearch implements Iterable{ } public String getName() { return file.getName(); } - public URL getUrl() throws MalformedURLException { return new URL(file.getAbsolutePath()); } + public String getPath() { return file.getAbsolutePath(); } public boolean isCompressed() { return false; } public boolean isFile() { return file.isFile(); } @@ -229,7 +233,7 @@ public class FileSearch implements Iterable{ } public String getName() { return entry.getName(); } - public URL getUrl() throws MalformedURLException { return new URL(file); } + public String getPath() { return file; } public boolean isCompressed() { return true; } public boolean isFile() { return !entry.isDirectory(); } diff --git a/src/zutil/io/file/FileUtil.java b/src/zutil/io/file/FileUtil.java index e0bcb36..9373957 100644 --- a/src/zutil/io/file/FileUtil.java +++ b/src/zutil/io/file/FileUtil.java @@ -129,7 +129,7 @@ public class FileUtil { * @param file * @return the file content */ - public static String getFileContent(File file) throws IOException{ + public static String getContent(File file) throws IOException{ InputStream in = new FileInputStream(file); String data = new String(IOUtil.getContent( in )); in.close(); @@ -302,8 +302,8 @@ public class FileUtil { /** * Replaces the current extension on the file withe the given one. * - * @param filename is the name of the file - * @param string is the new extension, without the dot + * @param file is the name of the file + * @param ext is the new extension, without the dot * @return */ public static String changeExtension(String file, String ext) { diff --git a/src/zutil/net/http/HttpPrintStream.java b/src/zutil/net/http/HttpPrintStream.java index bb7eaf9..4ed5b0b 100644 --- a/src/zutil/net/http/HttpPrintStream.java +++ b/src/zutil/net/http/HttpPrintStream.java @@ -199,7 +199,7 @@ public class HttpPrintStream extends PrintStream{ super.print(req_type+" "+req_url+" HTTP/1.0"); else super.print("HTTP/1.0 "+res_status_code+" "+getStatusString(res_status_code)); - super.println(); + super.print(System.lineSeparator()); res_status_code = null; req_type = null; req_url = null; @@ -207,7 +207,7 @@ public class HttpPrintStream extends PrintStream{ if(headers != null){ for(String key : headers.keySet()){ super.print(key+": "+headers.get(key)); - super.println(); + super.print(System.lineSeparator()); } headers = null; } @@ -218,16 +218,16 @@ public class HttpPrintStream extends PrintStream{ for(String key : cookies.keySet()){ super.print(key+"="+cookies.get(key)+"; "); } - super.println(); + super.print(System.lineSeparator()); } else{ for(String key : cookies.keySet()){ super.print("Set-Cookie: "+key+"="+cookies.get(key)+";"); - super.println(); + super.print(System.lineSeparator()); } } } - super.println(); + super.print(System.lineSeparator()); cookies = null; } super.print(s); diff --git a/src/zutil/net/http/HttpServer.java b/src/zutil/net/http/HttpServer.java index 1e322a7..2667598 100644 --- a/src/zutil/net/http/HttpServer.java +++ b/src/zutil/net/http/HttpServer.java @@ -53,7 +53,6 @@ public class HttpServer extends ThreadedTCPNetworkServer{ public static final int COOKIE_TTL = 200; public static final int SESSION_TTL = 10*60*1000; // in milliseconds - public final String server_url; public final int server_port; private Map pages; @@ -63,26 +62,23 @@ public class HttpServer extends ThreadedTCPNetworkServer{ /** * Creates a new instance of the sever - * - * @param url The address to the server + * * @param port The port that the server should listen to */ - public HttpServer(String url, int port){ - this(url, port, null, null); + public HttpServer(int port){ + this(port, null, null); } /** * Creates a new instance of the sever - * - * @param url The address to the server + * * @param port The port that the server should listen to * @param keyStore If this is not null then the server will use SSL connection with this keyStore file path * @param keyStorePass If this is not null then the server will use a SSL connection with the given certificate */ - public HttpServer(String url, int port, File keyStore, String keyStorePass){ + public HttpServer(int port, File keyStore, String keyStorePass){ super( port, keyStore, keyStorePass ); - this.server_url = url; this.server_port = port; pages = new ConcurrentHashMap(); diff --git a/src/zutil/net/ssdp/SSDPClient.java b/src/zutil/net/ssdp/SSDPClient.java index 6668ec0..3dcb9dc 100644 --- a/src/zutil/net/ssdp/SSDPClient.java +++ b/src/zutil/net/ssdp/SSDPClient.java @@ -56,7 +56,8 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork System.out.println(LogUtil.getCalingClass()); LogUtil.setGlobalLevel(Level.FINEST); SSDPClient ssdp = new SSDPClient(); - ssdp.requestService("upnp:rootdevice"); + //ssdp.requestService("upnp:rootdevice"); + ssdp.requestService("zap:discover"); ssdp.start(); for(int i=0; true ;++i){ @@ -73,13 +74,13 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork * @throws IOException */ public SSDPClient() throws IOException{ - super( null ); - super.setThread( this ); + super(null); + super.setThread(this); services_st = new HashMap>(); services_usn = new HashMap(); } - + /** * Sends an request for an service * @@ -94,6 +95,9 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork * */ public void requestService(String st){ + requestService(st, null); + } + public void requestService(String st, HashMap headers){ try { services_st.put( st, new LinkedList() ); @@ -106,9 +110,14 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork http.setHeader("ST", st ); http.setHeader("Man", "\"ssdp:discover\"" ); http.setHeader("MX", "3" ); + if(headers != null) { + for (String key : headers.keySet()) { + http.setHeader(key, headers.get(key)); + } + } http.flush(); - logger.log(Level.FINEST, "***** REQUEST: \n"+msg); + logger.log(Level.FINEST, "Sending Multicast: \n"+msg); byte[] data = msg.toString().getBytes(); DatagramPacket packet = new DatagramPacket( data, data.length, @@ -120,7 +129,14 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork e.printStackTrace(); } } - + + /** + * Set a listener that will be notified when new services are detected + */ + public void setListener(SSDPServiceListener listener){ + this.listener = listener; + } + /** * Returns a list of received services by * the given search target. @@ -176,7 +192,7 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork */ public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) { HttpHeaderParser header = new HttpHeaderParser( new String( packet.getData() ) ); - logger.log(Level.FINEST, "Recived: \n"+header); + logger.log(Level.FINEST, "Recived(from: "+packet.getAddress()+"): \n" + header); String usn = header.getHeader("USN"); String st = header.getHeader("ST"); @@ -199,11 +215,13 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork service.setLocation( header.getHeader("LOCATION") ); service.setST( st ); service.setUSN( usn ); - service.setExpirationTime( - System.currentTimeMillis() + - 1000 * getCacheTime(header.getHeader("Cache-Control")) ); + service.setInetAddress(packet.getAddress()); + if(header.getHeader("Cache-Control") != null) { + service.setExpirationTime( + System.currentTimeMillis() + 1000 * getCacheTime(header.getHeader("Cache-Control"))); + } + service.setHeaders(header.getHeaders()); - logger.log(Level.FINEST, "Recived:\n"+service); if(listener != null && newService) listener.newService(service); } diff --git a/src/zutil/net/ssdp/SSDPServer.java b/src/zutil/net/ssdp/SSDPServer.java index ffb5732..20d5802 100644 --- a/src/zutil/net/ssdp/SSDPServer.java +++ b/src/zutil/net/ssdp/SSDPServer.java @@ -25,6 +25,7 @@ package zutil.net.ssdp; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; +import java.net.MulticastSocket; import java.util.HashMap; import java.util.Timer; import java.util.TimerTask; @@ -80,10 +81,14 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork public static void main(String[] args) throws IOException{ LogUtil.setGlobalLevel(Level.FINEST); - SSDPServer ssdp = new SSDPServer(); StandardSSDPInfo service = new StandardSSDPInfo(); service.setLocation("nowhere"); - service.setST("upnp:rootdevice"); + service.setST("zep:discover"); + HashMap headers = new HashMap(); + headers.put("Alias", "Desktop"); + headers.put("PublicKey", "SuperDesktopKey"); + service.setHeaders(headers); + SSDPServer ssdp = new SSDPServer(); ssdp.addService(service); ssdp.start(); MultiPrintStream.out.println("SSDP Server running"); @@ -178,31 +183,36 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork String msg = new String( packet.getData() ); HttpHeaderParser header = new HttpHeaderParser( msg ); - logger.log(Level.FINEST, "#### Received:\n"+header); // ******* Respond // Check that the message is an ssdp discovery message if( header.getRequestType() != null && header.getRequestType().equalsIgnoreCase("M-SEARCH") ){ - String man = header.getHeader("Man").replace("\"", ""); + String man = header.getHeader("Man"); + if(man != null) + man = man.replace("\"", ""); String st = header.getHeader("ST"); // Check that its the correct URL and that its an ssdp:discover message - if( header.getRequestURL().equals("*") && man.equalsIgnoreCase("ssdp:discover") ){ + if( header.getRequestURL().equals("*") && "ssdp:discover".equalsIgnoreCase(man) ){ // Check if the requested service exists if( services.containsKey( st ) ){ + logger.log(Level.FINEST, "Received Multicast(from: "+packet.getAddress()+"):\n"+header); + // Generate the SSDP response StringOutputStream response = new StringOutputStream(); HttpPrintStream http = new HttpPrintStream( response ); http.setStatusCode(200); + http.setHeader("Location", services.get(st).getLocation() ); + http.setHeader("USN", services.get(st).getUSN() ); http.setHeader("Server", SERVER_INFO ); http.setHeader("ST", st ); - http.setHeader("Location", services.get(st).getLocation() ); http.setHeader("EXT", "" ); http.setHeader("Cache-Control", "max-age = "+cache_time ); - http.setHeader("USN", services.get(st).getUSN() ); + if(services.get(st) instanceof SSDPCustomInfo) + ((SSDPCustomInfo)services.get(st)).setHeaders(http); http.flush(); String strData = response.toString(); - logger.log(Level.FINEST, "#### Response:\n"+strData); + logger.log(Level.FINEST, "Response:\n"+strData); byte[] data = strData.getBytes(); packet = new DatagramPacket( data, data.length, @@ -269,7 +279,7 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork http.setHeader("USN", services.get(searchTarget).getUSN() ); http.close(); - logger.log(Level.FINEST, "#### Notification:\n"+msg); + logger.log(Level.FINEST, "Notification:\n" + msg); byte[] data = msg.toString().getBytes(); DatagramPacket packet = new DatagramPacket( data, data.length, @@ -318,7 +328,7 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork http.setHeader("USN", services.get(searchTarget).getUSN() ); http.close(); - logger.log(Level.FINEST, "******** ByeBye:\n"+msg); + logger.log(Level.FINEST, "ByeBye:\n" + msg); byte[] data = msg.toString().getBytes(); DatagramPacket packet = new DatagramPacket( data, data.length, diff --git a/src/zutil/net/ssdp/SSDPServiceInfo.java b/src/zutil/net/ssdp/SSDPServiceInfo.java index ec917d3..6150919 100644 --- a/src/zutil/net/ssdp/SSDPServiceInfo.java +++ b/src/zutil/net/ssdp/SSDPServiceInfo.java @@ -22,6 +22,8 @@ package zutil.net.ssdp; +import zutil.net.http.HttpPrintStream; + /** * This class contains information about a service from * or through the SSDP protocol diff --git a/src/zutil/net/ssdp/StandardSSDPInfo.java b/src/zutil/net/ssdp/StandardSSDPInfo.java index adbdbc1..abf00cd 100644 --- a/src/zutil/net/ssdp/StandardSSDPInfo.java +++ b/src/zutil/net/ssdp/StandardSSDPInfo.java @@ -22,7 +22,11 @@ package zutil.net.ssdp; +import zutil.net.http.HttpPrintStream; + +import java.net.InetAddress; import java.util.Date; +import java.util.HashMap; import java.util.UUID; /** @@ -31,12 +35,15 @@ import java.util.UUID; * * @author Ziver */ -public class StandardSSDPInfo implements SSDPServiceInfo{ +public class StandardSSDPInfo implements SSDPServiceInfo, SSDPCustomInfo{ private String location; private String st; private String usn; private long expiration_time; - + // All header parameters + private HashMap headers; + private InetAddress inetAddress; + /** * @param l is the value to set the Location variable */ @@ -103,11 +110,10 @@ public class StandardSSDPInfo implements SSDPServiceInfo{ usn = genUSN(); return usn; } - + /** * Generates an unique USN for the service * - * @param searchTarget is the service ST name * @return an unique string that corresponds to the service */ private String genUSN(){ @@ -117,4 +123,30 @@ public class StandardSSDPInfo implements SSDPServiceInfo{ public String toString(){ return "USN: "+usn+"\nLocation: "+location+"\nST: "+st+"\nExpiration-Time: "+new Date(expiration_time); } + + public void setHeaders(HashMap headers) { + this.headers = headers; + } + + public String getHeader(String header){ + return headers.get(header.toUpperCase()); + } + + + @Override + public void setHeaders(HttpPrintStream http) { + if(headers != null) { + for (String key : headers.keySet()) { + http.setHeader(key, headers.get(key)); + } + } + } + + public InetAddress getInetAddress(){ + return inetAddress; + } + + public void setInetAddress(InetAddress inetAddress) { + this.inetAddress = inetAddress; + } } diff --git a/src/zutil/net/torrent/TorrentMetainfo.java b/src/zutil/net/torrent/TorrentMetainfo.java index e7b31c8..aa48a53 100644 --- a/src/zutil/net/torrent/TorrentMetainfo.java +++ b/src/zutil/net/torrent/TorrentMetainfo.java @@ -62,7 +62,7 @@ public class TorrentMetainfo { public TorrentMetainfo(File torrent) throws IOException{ - this(FileUtil.getFileContent( torrent )); + this(FileUtil.getContent(torrent)); } public TorrentMetainfo(String data){ diff --git a/src/zutil/osal/OSAbstractionLayer.java b/src/zutil/osal/OSAbstractionLayer.java index b0fa4fe..91331c5 100644 --- a/src/zutil/osal/OSAbstractionLayer.java +++ b/src/zutil/osal/OSAbstractionLayer.java @@ -58,7 +58,7 @@ public abstract class OSAbstractionLayer { * @param cmd the command to run * @return first line of the command */ - protected String getFirstLineFromCommand(String cmd) throws InterruptedException, IOException { + protected String getFirstLineFromCommand(String cmd) { String[] tmp = runCommand(cmd); if(tmp.length > 1) return tmp[0]; @@ -71,18 +71,25 @@ public abstract class OSAbstractionLayer { * @param cmd the command to run * @return a String list of the output of the command */ - public String[] runCommand(String cmd) throws InterruptedException, IOException { - Runtime runtime = Runtime.getRuntime(); - Process proc = runtime.exec(cmd); - proc.waitFor(); - BufferedReader output = new BufferedReader(new InputStreamReader(proc.getInputStream())); - + public String[] runCommand(String cmd) { ArrayList ret = new ArrayList(); - String line; - while((line = output.readLine()) != null){ - ret.add(line); + try { + Runtime runtime = Runtime.getRuntime(); + Process proc = runtime.exec(cmd); + proc.waitFor(); + BufferedReader output = new BufferedReader(new InputStreamReader(proc.getInputStream())); + + + String line; + while ((line = output.readLine()) != null) { + ret.add(line); + } + output.close(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); } - output.close(); return ret.toArray(new String[1]); } diff --git a/src/zutil/parser/DataNode.java b/src/zutil/parser/DataNode.java index 02d23be..efbeb34 100644 --- a/src/zutil/parser/DataNode.java +++ b/src/zutil/parser/DataNode.java @@ -99,11 +99,11 @@ public class DataNode implements Iterable{ * @return an JSONNode that contains the next level of the List or Map */ public DataNode get(int index){ - if(map != null) - return map.get(""+index); - else if(list != null) - return list.get(index); - return null; + if(map != null) + return map.get(""+index); + else if(list != null) + return list.get(index); + return null; } /** * @param index is the key in the Map diff --git a/src/zutil/parser/json/JSONParser.java b/src/zutil/parser/json/JSONParser.java index a95bf76..e232cf2 100644 --- a/src/zutil/parser/json/JSONParser.java +++ b/src/zutil/parser/json/JSONParser.java @@ -111,15 +111,14 @@ public class JSONParser{ case '\"': root = new DataNode(DataType.String); StringBuilder str = new StringBuilder(); - while((c=(char)in.read()) != (char)-1 && c != '\"') + while((c=(char)in.read()) >= 0 && c != '\"') str.append(c); root.set(str.toString()); break; // Parse unknown type default: StringBuilder tmp = new StringBuilder().append(c); - while((c=(char)in.read()) != (char)-1 && !Character.isWhitespace(c) && - c != ',' && c != '='){ + while((c=(char)in.read()) >= 0 && c != ',' && c != '='){ if(c == ']' || c == '}'){ end.i = 1; break; @@ -127,7 +126,7 @@ public class JSONParser{ tmp.append(c); } // Check what type of type the data is - String data = tmp.toString(); + String data = tmp.toString().trim(); if( BOOLEAN_PATTERN.matcher(data).matches() ) root = new DataNode(DataType.Boolean); else if( NUMBER_PATTERN.matcher(data).matches() ) @@ -140,4 +139,6 @@ public class JSONParser{ return root; } + + } diff --git a/src/zutil/plugin/PluginData.java b/src/zutil/plugin/PluginData.java index aa6989d..6bb9fd8 100644 --- a/src/zutil/plugin/PluginData.java +++ b/src/zutil/plugin/PluginData.java @@ -22,9 +22,18 @@ package zutil.plugin; +import zutil.ClassUtil; +import zutil.log.LogUtil; import zutil.parser.DataNode; +import javax.xml.crypto.Data; +import java.net.MalformedURLException; +import java.net.URL; import java.net.URLClassLoader; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.logging.Logger; /** * This class contains information about a plugin @@ -32,18 +41,36 @@ import java.net.URLClassLoader; * * @author Ziver */ -public class PluginData { +public class PluginData { + private static Logger log = LogUtil.getLogger(); + private double pluginVersion; - private String pluginName; - private String pluginClass; + private String pluginName; + private HashMap classMap; + private HashMap objectMap; + - private T obj; - - - protected PluginData(String intf, DataNode data){ + protected PluginData(DataNode data) throws ClassNotFoundException, MalformedURLException { + classMap = new HashMap(); + objectMap = new HashMap(); + pluginVersion = data.getDouble("version"); - pluginName = data.getString("name"); - pluginClass = data.get("interfaces").getString(intf); + pluginName = data.getString("name"); + log.fine("Found plugin: "+pluginName); + + DataNode node = data.get("interfaces"); + Iterator intfIt = node.keyIterator(); + while (intfIt.hasNext()) { + String intf = intfIt.next(); + log.finer("Plugin interface: "+ intf+"-->"+node.get(intf).getString()); + classMap.put( + getClassByName(intf), + getClassByName(node.get(intf).getString())); + } + } + + private static Class getClassByName(String name) throws ClassNotFoundException, MalformedURLException { + return Class.forName(name); } public double getVersion(){ @@ -52,13 +79,23 @@ public class PluginData { public String getName(){ return pluginName; } - - @SuppressWarnings("unchecked") - public T getObject() throws InstantiationException, IllegalAccessException, ClassNotFoundException{ - //if(obj == null) - // new URLClassLoader(pluginClass); - // //obj = (T) Class.forName(pluginClass).newInstance(); - return obj; + + public T getObject(Class intf) { + if(classMap.containsKey(intf)) { + try { + Class subClass = classMap.get(intf); + if (objectMap.containsKey(subClass)) + objectMap.put(intf, subClass.newInstance()); + return (T) objectMap.get(subClass); + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; } + + public boolean contains(Class intf){ + return classMap.containsKey(intf); + } } diff --git a/src/zutil/plugin/PluginManager.java b/src/zutil/plugin/PluginManager.java index 820cfb9..38cbdcc 100644 --- a/src/zutil/plugin/PluginManager.java +++ b/src/zutil/plugin/PluginManager.java @@ -24,11 +24,17 @@ package zutil.plugin; import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; import java.util.HashMap; import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.logging.Logger; +import com.sun.xml.internal.stream.util.ReadOnlyIterator; +import zutil.io.IOUtil; import zutil.io.file.FileSearch; import zutil.io.file.FileUtil; +import zutil.log.LogUtil; import zutil.parser.DataNode; import zutil.parser.json.JSONParser; @@ -40,39 +46,85 @@ import zutil.parser.json.JSONParser; * * @author Ziver */ -public class PluginManager implements Iterable>{ - private HashMap> plugins; - - public static PluginManager load(Class intfClass) throws IOException{ - return new PluginManager(intfClass); +public class PluginManager implements Iterable{ + private static Logger log = LogUtil.getLogger(); + + private HashMap plugins; + + + public static PluginManager load(String path){ + return new PluginManager(path); } - - private PluginManager(Class intfClass) throws IOException{ - FileSearch search = new FileSearch(new File(".")); + public PluginManager(){ + this("./"); + } + public PluginManager(String path){ + plugins = new HashMap(); + + FileSearch search = new FileSearch(new File(path)); search.setRecursive(true); search.searchFolders(false); search.setFileName("plugin.json"); - + + log.fine("Searching for plugins..."); for(FileSearch.FileSearchItem file : search){ - DataNode node = JSONParser.read(FileUtil.getContent(file.getUrl())); - PluginData plugin = new PluginData(intfClass.getName(), node); - - if(node.get("interfaces").getString(intfClass.getName()) != null){ - if(plugins.containsKey(plugin.getName())){ - if(plugins.get(plugin.getName()).getVersion() < plugin.getVersion()) - plugins.put(plugin.getName(), plugin); - } - else{ + try { + DataNode node = JSONParser.read(IOUtil.getContentString(file.getInputStream())); + PluginData plugin = new PluginData(node); + + if (!plugins.containsKey(plugin.getName()) || + plugins.get(plugin.getName()).getVersion() < plugin.getVersion()){ plugins.put(plugin.getName(), plugin); } + } catch (Exception e) { + e.printStackTrace(); } } } @Override - public Iterator> iterator() { + public Iterator iterator() { return plugins.values().iterator(); } - + + public Iterator iterator(Class intf) { + return new PluginInterfaceIterator(plugins.values().iterator(), intf); + } + + public class PluginInterfaceIterator implements Iterator { + private Class intf; + private Iterator it; + private PluginData next; + + PluginInterfaceIterator(Iterator it, Class intf){ + this.intf = intf; + this.it = it; + } + + @Override + public boolean hasNext() { + if(next != null) + return true; + while(it.hasNext()) { + next = it.next(); + if(next.contains(intf)) + return true; + } + next = null; + return false; + } + + @Override + public T next() { + if(!hasNext()) + throw new NoSuchElementException(); + return next.getObject(intf); + } + + @Override + public void remove() { + throw new RuntimeException("Iterator is ReadOnly"); + } + } } \ No newline at end of file diff --git a/src/zutil/test/ConverterTest.java b/src/zutil/test/ConverterTest.java index aeacbe8..f4707fc 100644 --- a/src/zutil/test/ConverterTest.java +++ b/src/zutil/test/ConverterTest.java @@ -43,17 +43,28 @@ public class ConverterTest { assertEquals( 0x00, Converter.hexToByte('0','0') ); assertEquals( 0x11, Converter.hexToByte('1','1') ); assertEquals( 0x75, Converter.hexToByte('7','5') ); - assertEquals( 0xDA, Converter.hexToByte('D','A') ); - assertEquals( 0xFA, Converter.hexToByte('F','a') ); - assertEquals( 0xFF, Converter.hexToByte('f','f') ); + assertEquals( 0xDA, Converter.hexToByte('D','A') & 0xFF ); + assertEquals( 0xFA, Converter.hexToByte('F','a') & 0xFF ); + assertEquals( 0xFF, Converter.hexToByte('f','f') & 0xFF ); } - + + @Test + public void testHexStringToByte() { + assertArrayEquals( null, Converter.hexToByte(null) ); + assertArrayEquals( new byte[]{}, Converter.hexToByte("") ); + assertArrayEquals( new byte[]{0x00}, Converter.hexToByte("0x00") ); + assertArrayEquals( new byte[]{0x00}, Converter.hexToByte("00") ); + assertArrayEquals(new byte[]{0x07,0x06,0x05,0x04,0x03,0x02,0x01}, + Converter.hexToByte("01020304050607") ); + assertArrayEquals( new byte[]{0x11,0x0F}, Converter.hexToByte("F11") ); + } + @Test public void testUrlEncode() { - assertEquals( "fas8dg7%20a0d1%2313f9g8d7%200h9a%a4%25h0", - Converter.urlEncode("fas8dg7 a0d1#13f9g8d7 0h9a�%h0") ); - assertEquals( "9i34%e5%202y92%a452%25%2623%20463765%a4(%2f%26(", - Converter.urlEncode("9i34� 2y92�52%&23 463765�(/&(") ); + assertEquals( "fas8dg7%20a0d1%2313f9g8d7%200h9a%25h0", + Converter.urlEncode("fas8dg7 a0d1#13f9g8d7 0h9a%h0") ); + assertEquals( "9i34%202y9252%25%2623%20463765(%2f%26(", + Converter.urlEncode("9i34 2y9252%&23 463765(/&(") ); } @@ -61,8 +72,8 @@ public class ConverterTest { public void testUrlDecode() { assertEquals( "fas8dg7 a0d1#13f9g8d7 0h9a%h0", Converter.urlDecode("fas8dg7%20a0d1%2313f9g8d7%200h9a%25h0") ); - assertEquals( "9i34� 2y9252%&23 463765(/&(", - Converter.urlDecode("9i34%e5%202y9252%25%2623%20463765(%2f%26(") ); + assertEquals( "9i34 2y9252%&23 463765(/&(", + Converter.urlDecode("9i34%202y9252%25%2623%20463765(%2f%26(") ); } } diff --git a/src/zutil/test/HTTPGuessTheNumber.java b/src/zutil/test/HTTPGuessTheNumber.java index abd2e85..73e8b11 100644 --- a/src/zutil/test/HTTPGuessTheNumber.java +++ b/src/zutil/test/HTTPGuessTheNumber.java @@ -35,7 +35,7 @@ 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", 8080); + HttpServer server = new HttpServer(8080); server.setDefaultPage(new HTTPGuessTheNumber()); server.run(); } diff --git a/src/zutil/test/HTTPUploaderTest.java b/src/zutil/test/HTTPUploaderTest.java index ed0f718..b7a71f0 100644 --- a/src/zutil/test/HTTPUploaderTest.java +++ b/src/zutil/test/HTTPUploaderTest.java @@ -35,7 +35,7 @@ import zutil.net.http.HttpServer; public class HTTPUploaderTest implements HttpPage{ public static void main(String[] args) throws IOException{ - HttpServer server = new HttpServer("localhost", 80); + HttpServer server = new HttpServer(80); server.setDefaultPage(new HTTPUploaderTest()); server.run(); } diff --git a/src/zutil/test/UPnPServerTest.java b/src/zutil/test/UPnPServerTest.java index 6461baf..663af64 100644 --- a/src/zutil/test/UPnPServerTest.java +++ b/src/zutil/test/UPnPServerTest.java @@ -42,7 +42,7 @@ public class UPnPServerTest { UPnPContentDirectory cds = new UPnPContentDirectory(new File("C:\\Users\\Ziver\\Desktop\\lan")); WebServiceDef ws = new WebServiceDef( UPnPContentDirectory.class ); - HttpServer http = new HttpServer("http://192.168.0.60/", 8080); + HttpServer http = new HttpServer(8080); //http.setDefaultPage(upnp); http.setPage("/RootDesc", upnp ); http.setPage("/SCP/ContentDir", cds );