This commit is contained in:
Ziver Koc 2015-03-23 21:05:51 +00:00
parent e822a4b35c
commit 91cadbb301
20 changed files with 342 additions and 130 deletions

View file

@ -71,7 +71,28 @@ public class Converter {
public static byte toByte(int num){ public static byte toByte(int num){
return (byte)(num & 0xff); 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 * Converts hex chars to a byte
* *
@ -79,10 +100,10 @@ public class Converter {
* @param quad2 is the second hex value * @param quad2 is the second hex value
* @return a byte that corresponds to the hex * @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 ); byte b = hexToByte( quad2 );
b |= hexToByte( quad1 ) << 4; b |= hexToByte( quad1 ) << 4;
return toInt(b); return b;
} }
/** /**

View file

@ -33,7 +33,8 @@ import java.io.*;
public class IOUtil { 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 * @param stream
* @return the stream contents * @return the stream contents
@ -45,10 +46,30 @@ public class IOUtil {
while((len = stream.read(buff)) != -1){ while((len = stream.read(buff)) != -1){
dyn_buff.append(buff, 0, len); dyn_buff.append(buff, 0, len);
} }
stream.close();
return dyn_buff.getBytes(); 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 * Copies all data from the input stream to the output stream
*/ */

View file

@ -113,18 +113,19 @@ public class FileSearch implements Iterable<FileSearch.FileSearchItem>{
protected class FileSearchIterator implements Iterator<FileSearchItem>{ protected class FileSearchIterator implements Iterator<FileSearchItem>{
private ArrayList<FileSearchItem> fileList; private ArrayList<FileSearchItem> fileList;
private int currentIndex; private int currentIndex;
private FileSearchItem nextItem;
public FileSearchIterator(){ public FileSearchIterator(){
fileList = new ArrayList<FileSearchItem>(); fileList = new ArrayList<FileSearchItem>();
currentIndex = 0; currentIndex = 0;
addFiles(root.list()); addFiles(new FileSearchFileItem(root), root.list());
next(); next();
} }
@Override @Override
public boolean hasNext() { public boolean hasNext() {
return currentIndex != fileList.size(); return currentIndex < fileList.size();
} }
@Override @Override
@ -134,28 +135,28 @@ public class FileSearch implements Iterable<FileSearch.FileSearchItem>{
@Override @Override
public FileSearchItem next() { public FileSearchItem next() {
if(currentIndex < 0) if(currentIndex < 0 || currentIndex >= fileList.size())
return null; return null;
// Temporarily save the current file // Temporarily save the current file
FileSearchItem ret = fileList.get(currentIndex); FileSearchItem ret = fileList.get(currentIndex);
currentIndex++;
// Find the next file // Find the next file
for(; currentIndex<fileList.size(); currentIndex++){ for(; currentIndex<fileList.size(); currentIndex++){
FileSearchItem file = fileList.get(currentIndex); FileSearchItem file = fileList.get(currentIndex);
if(recursive && file.isDirectory()){ if(recursive && file.isDirectory()){
addFiles(file.listFiles()); addFiles(file, file.listFiles());
if(searchFolders && file.getName().equalsIgnoreCase(fileName)) if(searchFolders && file.getName().equalsIgnoreCase(fileName))
break; break;
} }
else if(searchCompressedFiles && file.isFile() && else if(searchCompressedFiles && file.isFile() &&
compressedFileExtensions.contains(FileUtil.getFileExtension(file.getName()).toLowerCase())){ compressedFileExtensions.contains(FileUtil.getFileExtension(file.getName()).toLowerCase())){
try { try {
String url = file.getUrl().getFile(); ZipFile zipFile = new ZipFile(file.getPath());
ZipFile zipFile = new ZipFile(url);
Enumeration<? extends ZipEntry> e = zipFile.entries(); Enumeration<? extends ZipEntry> e = zipFile.entries();
while(e.hasMoreElements()){ while(e.hasMoreElements()){
ZipEntry entry = e.nextElement(); ZipEntry entry = e.nextElement();
fileList.add(new FileSearchZipItem(url, entry)); fileList.add(new FileSearchZipItem(file.getPath(), entry));
} }
zipFile.close(); zipFile.close();
} catch (IOException e) { } catch (IOException e) {
@ -173,9 +174,12 @@ public class FileSearch implements Iterable<FileSearch.FileSearchItem>{
return ret; return ret;
} }
private void addFiles(String[] list){ private void addFiles(FileSearchItem root, String[] list){
for(String file : list){ if(root instanceof FileSearchFileItem) {
fileList.add(new FileSearchFileItem(new File(file))); for (String file : list) {
fileList.add(new FileSearchFileItem(
new File(((FileSearchFileItem)root).file, file)));
}
} }
} }
@ -186,8 +190,8 @@ public class FileSearch implements Iterable<FileSearch.FileSearchItem>{
public interface FileSearchItem{ public interface FileSearchItem{
/** @return a file or folder name **/ /** @return a file or folder name **/
public String getName(); 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 **/ /** @return a path to the file or folder, in case of a compressed file the path to the package will be returned **/
public URL getUrl() throws MalformedURLException ; public String getPath();
public boolean isCompressed(); public boolean isCompressed();
public boolean isFile(); public boolean isFile();
@ -208,7 +212,7 @@ public class FileSearch implements Iterable<FileSearch.FileSearchItem>{
} }
public String getName() { return file.getName(); } 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 isCompressed() { return false; }
public boolean isFile() { return file.isFile(); } public boolean isFile() { return file.isFile(); }
@ -229,7 +233,7 @@ public class FileSearch implements Iterable<FileSearch.FileSearchItem>{
} }
public String getName() { return entry.getName(); } 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 isCompressed() { return true; }
public boolean isFile() { return !entry.isDirectory(); } public boolean isFile() { return !entry.isDirectory(); }

View file

@ -129,7 +129,7 @@ public class FileUtil {
* @param file * @param file
* @return the file content * @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); InputStream in = new FileInputStream(file);
String data = new String(IOUtil.getContent( in )); String data = new String(IOUtil.getContent( in ));
in.close(); in.close();
@ -302,8 +302,8 @@ public class FileUtil {
/** /**
* Replaces the current extension on the file withe the given one. * Replaces the current extension on the file withe the given one.
* *
* @param filename is the name of the file * @param file is the name of the file
* @param string is the new extension, without the dot * @param ext is the new extension, without the dot
* @return * @return
*/ */
public static String changeExtension(String file, String ext) { public static String changeExtension(String file, String ext) {

View file

@ -199,7 +199,7 @@ public class HttpPrintStream extends PrintStream{
super.print(req_type+" "+req_url+" HTTP/1.0"); super.print(req_type+" "+req_url+" HTTP/1.0");
else else
super.print("HTTP/1.0 "+res_status_code+" "+getStatusString(res_status_code)); super.print("HTTP/1.0 "+res_status_code+" "+getStatusString(res_status_code));
super.println(); super.print(System.lineSeparator());
res_status_code = null; res_status_code = null;
req_type = null; req_type = null;
req_url = null; req_url = null;
@ -207,7 +207,7 @@ public class HttpPrintStream extends PrintStream{
if(headers != null){ if(headers != null){
for(String key : headers.keySet()){ for(String key : headers.keySet()){
super.print(key+": "+headers.get(key)); super.print(key+": "+headers.get(key));
super.println(); super.print(System.lineSeparator());
} }
headers = null; headers = null;
} }
@ -218,16 +218,16 @@ public class HttpPrintStream extends PrintStream{
for(String key : cookies.keySet()){ for(String key : cookies.keySet()){
super.print(key+"="+cookies.get(key)+"; "); super.print(key+"="+cookies.get(key)+"; ");
} }
super.println(); super.print(System.lineSeparator());
} }
else{ else{
for(String key : cookies.keySet()){ for(String key : cookies.keySet()){
super.print("Set-Cookie: "+key+"="+cookies.get(key)+";"); super.print("Set-Cookie: "+key+"="+cookies.get(key)+";");
super.println(); super.print(System.lineSeparator());
} }
} }
} }
super.println(); super.print(System.lineSeparator());
cookies = null; cookies = null;
} }
super.print(s); super.print(s);

View file

@ -53,7 +53,6 @@ public class HttpServer extends ThreadedTCPNetworkServer{
public static final int COOKIE_TTL = 200; public static final int COOKIE_TTL = 200;
public static final int SESSION_TTL = 10*60*1000; // in milliseconds public static final int SESSION_TTL = 10*60*1000; // in milliseconds
public final String server_url;
public final int server_port; public final int server_port;
private Map<String,HttpPage> pages; private Map<String,HttpPage> pages;
@ -63,26 +62,23 @@ public class HttpServer extends ThreadedTCPNetworkServer{
/** /**
* Creates a new instance of the sever * 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 port The port that the server should listen to
*/ */
public HttpServer(String url, int port){ public HttpServer(int port){
this(url, port, null, null); this(port, null, null);
} }
/** /**
* Creates a new instance of the sever * 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 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 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 * @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 ); super( port, keyStore, keyStorePass );
this.server_url = url;
this.server_port = port; this.server_port = port;
pages = new ConcurrentHashMap<String,HttpPage>(); pages = new ConcurrentHashMap<String,HttpPage>();

View file

@ -56,7 +56,8 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
System.out.println(LogUtil.getCalingClass()); System.out.println(LogUtil.getCalingClass());
LogUtil.setGlobalLevel(Level.FINEST); LogUtil.setGlobalLevel(Level.FINEST);
SSDPClient ssdp = new SSDPClient(); SSDPClient ssdp = new SSDPClient();
ssdp.requestService("upnp:rootdevice"); //ssdp.requestService("upnp:rootdevice");
ssdp.requestService("zap:discover");
ssdp.start(); ssdp.start();
for(int i=0; true ;++i){ for(int i=0; true ;++i){
@ -73,13 +74,13 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
* @throws IOException * @throws IOException
*/ */
public SSDPClient() throws IOException{ public SSDPClient() throws IOException{
super( null ); super(null);
super.setThread( this ); super.setThread(this);
services_st = new HashMap<String, LinkedList<SSDPServiceInfo>>(); services_st = new HashMap<String, LinkedList<SSDPServiceInfo>>();
services_usn = new HashMap<String, SSDPServiceInfo>(); services_usn = new HashMap<String, SSDPServiceInfo>();
} }
/** /**
* Sends an request for an service * Sends an request for an service
* *
@ -94,6 +95,9 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
* *
*/ */
public void requestService(String st){ public void requestService(String st){
requestService(st, null);
}
public void requestService(String st, HashMap<String,String> headers){
try { try {
services_st.put( st, new LinkedList<SSDPServiceInfo>() ); services_st.put( st, new LinkedList<SSDPServiceInfo>() );
@ -106,9 +110,14 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
http.setHeader("ST", st ); http.setHeader("ST", st );
http.setHeader("Man", "\"ssdp:discover\"" ); http.setHeader("Man", "\"ssdp:discover\"" );
http.setHeader("MX", "3" ); http.setHeader("MX", "3" );
if(headers != null) {
for (String key : headers.keySet()) {
http.setHeader(key, headers.get(key));
}
}
http.flush(); http.flush();
logger.log(Level.FINEST, "***** REQUEST: \n"+msg); logger.log(Level.FINEST, "Sending Multicast: \n"+msg);
byte[] data = msg.toString().getBytes(); byte[] data = msg.toString().getBytes();
DatagramPacket packet = new DatagramPacket( DatagramPacket packet = new DatagramPacket(
data, data.length, data, data.length,
@ -120,7 +129,14 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
e.printStackTrace(); 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 * Returns a list of received services by
* the given search target. * the given search target.
@ -176,7 +192,7 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
*/ */
public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) { public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) {
HttpHeaderParser header = new HttpHeaderParser( new String( packet.getData() ) ); 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 usn = header.getHeader("USN");
String st = header.getHeader("ST"); String st = header.getHeader("ST");
@ -199,11 +215,13 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
service.setLocation( header.getHeader("LOCATION") ); service.setLocation( header.getHeader("LOCATION") );
service.setST( st ); service.setST( st );
service.setUSN( usn ); service.setUSN( usn );
service.setExpirationTime( service.setInetAddress(packet.getAddress());
System.currentTimeMillis() + if(header.getHeader("Cache-Control") != null) {
1000 * getCacheTime(header.getHeader("Cache-Control")) ); 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) if(listener != null && newService)
listener.newService(service); listener.newService(service);
} }

View file

@ -25,6 +25,7 @@ package zutil.net.ssdp;
import java.io.IOException; import java.io.IOException;
import java.net.DatagramPacket; import java.net.DatagramPacket;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.HashMap; import java.util.HashMap;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@ -80,10 +81,14 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork
public static void main(String[] args) throws IOException{ public static void main(String[] args) throws IOException{
LogUtil.setGlobalLevel(Level.FINEST); LogUtil.setGlobalLevel(Level.FINEST);
SSDPServer ssdp = new SSDPServer();
StandardSSDPInfo service = new StandardSSDPInfo(); StandardSSDPInfo service = new StandardSSDPInfo();
service.setLocation("nowhere"); service.setLocation("nowhere");
service.setST("upnp:rootdevice"); service.setST("zep:discover");
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Alias", "Desktop");
headers.put("PublicKey", "SuperDesktopKey");
service.setHeaders(headers);
SSDPServer ssdp = new SSDPServer();
ssdp.addService(service); ssdp.addService(service);
ssdp.start(); ssdp.start();
MultiPrintStream.out.println("SSDP Server running"); MultiPrintStream.out.println("SSDP Server running");
@ -178,31 +183,36 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork
String msg = new String( packet.getData() ); String msg = new String( packet.getData() );
HttpHeaderParser header = new HttpHeaderParser( msg ); HttpHeaderParser header = new HttpHeaderParser( msg );
logger.log(Level.FINEST, "#### Received:\n"+header);
// ******* Respond // ******* Respond
// Check that the message is an ssdp discovery message // Check that the message is an ssdp discovery message
if( header.getRequestType() != null && header.getRequestType().equalsIgnoreCase("M-SEARCH") ){ 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"); String st = header.getHeader("ST");
// Check that its the correct URL and that its an ssdp:discover message // 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 // Check if the requested service exists
if( services.containsKey( st ) ){ if( services.containsKey( st ) ){
logger.log(Level.FINEST, "Received Multicast(from: "+packet.getAddress()+"):\n"+header);
// Generate the SSDP response // Generate the SSDP response
StringOutputStream response = new StringOutputStream(); StringOutputStream response = new StringOutputStream();
HttpPrintStream http = new HttpPrintStream( response ); HttpPrintStream http = new HttpPrintStream( response );
http.setStatusCode(200); http.setStatusCode(200);
http.setHeader("Location", services.get(st).getLocation() );
http.setHeader("USN", services.get(st).getUSN() );
http.setHeader("Server", SERVER_INFO ); http.setHeader("Server", SERVER_INFO );
http.setHeader("ST", st ); http.setHeader("ST", st );
http.setHeader("Location", services.get(st).getLocation() );
http.setHeader("EXT", "" ); http.setHeader("EXT", "" );
http.setHeader("Cache-Control", "max-age = "+cache_time ); 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(); http.flush();
String strData = response.toString(); String strData = response.toString();
logger.log(Level.FINEST, "#### Response:\n"+strData); logger.log(Level.FINEST, "Response:\n"+strData);
byte[] data = strData.getBytes(); byte[] data = strData.getBytes();
packet = new DatagramPacket( packet = new DatagramPacket(
data, data.length, data, data.length,
@ -269,7 +279,7 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork
http.setHeader("USN", services.get(searchTarget).getUSN() ); http.setHeader("USN", services.get(searchTarget).getUSN() );
http.close(); http.close();
logger.log(Level.FINEST, "#### Notification:\n"+msg); logger.log(Level.FINEST, "Notification:\n" + msg);
byte[] data = msg.toString().getBytes(); byte[] data = msg.toString().getBytes();
DatagramPacket packet = new DatagramPacket( DatagramPacket packet = new DatagramPacket(
data, data.length, data, data.length,
@ -318,7 +328,7 @@ public class SSDPServer extends ThreadedUDPNetwork implements ThreadedUDPNetwork
http.setHeader("USN", services.get(searchTarget).getUSN() ); http.setHeader("USN", services.get(searchTarget).getUSN() );
http.close(); http.close();
logger.log(Level.FINEST, "******** ByeBye:\n"+msg); logger.log(Level.FINEST, "ByeBye:\n" + msg);
byte[] data = msg.toString().getBytes(); byte[] data = msg.toString().getBytes();
DatagramPacket packet = new DatagramPacket( DatagramPacket packet = new DatagramPacket(
data, data.length, data, data.length,

View file

@ -22,6 +22,8 @@
package zutil.net.ssdp; package zutil.net.ssdp;
import zutil.net.http.HttpPrintStream;
/** /**
* This class contains information about a service from * This class contains information about a service from
* or through the SSDP protocol * or through the SSDP protocol

View file

@ -22,7 +22,11 @@
package zutil.net.ssdp; package zutil.net.ssdp;
import zutil.net.http.HttpPrintStream;
import java.net.InetAddress;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
/** /**
@ -31,12 +35,15 @@ import java.util.UUID;
* *
* @author Ziver * @author Ziver
*/ */
public class StandardSSDPInfo implements SSDPServiceInfo{ public class StandardSSDPInfo implements SSDPServiceInfo, SSDPCustomInfo{
private String location; private String location;
private String st; private String st;
private String usn; private String usn;
private long expiration_time; private long expiration_time;
// All header parameters
private HashMap<String, String> headers;
private InetAddress inetAddress;
/** /**
* @param l is the value to set the Location variable * @param l is the value to set the Location variable
*/ */
@ -103,11 +110,10 @@ public class StandardSSDPInfo implements SSDPServiceInfo{
usn = genUSN(); usn = genUSN();
return usn; return usn;
} }
/** /**
* Generates an unique USN for the service * Generates an unique USN for the service
* *
* @param searchTarget is the service ST name
* @return an unique string that corresponds to the service * @return an unique string that corresponds to the service
*/ */
private String genUSN(){ private String genUSN(){
@ -117,4 +123,30 @@ public class StandardSSDPInfo implements SSDPServiceInfo{
public String toString(){ public String toString(){
return "USN: "+usn+"\nLocation: "+location+"\nST: "+st+"\nExpiration-Time: "+new Date(expiration_time); return "USN: "+usn+"\nLocation: "+location+"\nST: "+st+"\nExpiration-Time: "+new Date(expiration_time);
} }
public void setHeaders(HashMap<String, String> 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;
}
} }

View file

@ -62,7 +62,7 @@ public class TorrentMetainfo {
public TorrentMetainfo(File torrent) throws IOException{ public TorrentMetainfo(File torrent) throws IOException{
this(FileUtil.getFileContent( torrent )); this(FileUtil.getContent(torrent));
} }
public TorrentMetainfo(String data){ public TorrentMetainfo(String data){

View file

@ -58,7 +58,7 @@ public abstract class OSAbstractionLayer {
* @param cmd the command to run * @param cmd the command to run
* @return first line of the command * @return first line of the command
*/ */
protected String getFirstLineFromCommand(String cmd) throws InterruptedException, IOException { protected String getFirstLineFromCommand(String cmd) {
String[] tmp = runCommand(cmd); String[] tmp = runCommand(cmd);
if(tmp.length > 1) if(tmp.length > 1)
return tmp[0]; return tmp[0];
@ -71,18 +71,25 @@ public abstract class OSAbstractionLayer {
* @param cmd the command to run * @param cmd the command to run
* @return a String list of the output of the command * @return a String list of the output of the command
*/ */
public String[] runCommand(String cmd) throws InterruptedException, IOException { public String[] runCommand(String cmd) {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(cmd);
proc.waitFor();
BufferedReader output = new BufferedReader(new InputStreamReader(proc.getInputStream()));
ArrayList<String> ret = new ArrayList<String>(); ArrayList<String> ret = new ArrayList<String>();
String line; try {
while((line = output.readLine()) != null){ Runtime runtime = Runtime.getRuntime();
ret.add(line); 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]); return ret.toArray(new String[1]);
} }

View file

@ -99,11 +99,11 @@ public class DataNode implements Iterable<DataNode>{
* @return an JSONNode that contains the next level of the List or Map * @return an JSONNode that contains the next level of the List or Map
*/ */
public DataNode get(int index){ public DataNode get(int index){
if(map != null) if(map != null)
return map.get(""+index); return map.get(""+index);
else if(list != null) else if(list != null)
return list.get(index); return list.get(index);
return null; return null;
} }
/** /**
* @param index is the key in the Map * @param index is the key in the Map

View file

@ -111,15 +111,14 @@ public class JSONParser{
case '\"': case '\"':
root = new DataNode(DataType.String); root = new DataNode(DataType.String);
StringBuilder str = new StringBuilder(); StringBuilder str = new StringBuilder();
while((c=(char)in.read()) != (char)-1 && c != '\"') while((c=(char)in.read()) >= 0 && c != '\"')
str.append(c); str.append(c);
root.set(str.toString()); root.set(str.toString());
break; break;
// Parse unknown type // Parse unknown type
default: default:
StringBuilder tmp = new StringBuilder().append(c); StringBuilder tmp = new StringBuilder().append(c);
while((c=(char)in.read()) != (char)-1 && !Character.isWhitespace(c) && while((c=(char)in.read()) >= 0 && c != ',' && c != '='){
c != ',' && c != '='){
if(c == ']' || c == '}'){ if(c == ']' || c == '}'){
end.i = 1; end.i = 1;
break; break;
@ -127,7 +126,7 @@ public class JSONParser{
tmp.append(c); tmp.append(c);
} }
// Check what type of type the data is // Check what type of type the data is
String data = tmp.toString(); String data = tmp.toString().trim();
if( BOOLEAN_PATTERN.matcher(data).matches() ) if( BOOLEAN_PATTERN.matcher(data).matches() )
root = new DataNode(DataType.Boolean); root = new DataNode(DataType.Boolean);
else if( NUMBER_PATTERN.matcher(data).matches() ) else if( NUMBER_PATTERN.matcher(data).matches() )
@ -140,4 +139,6 @@ public class JSONParser{
return root; return root;
} }
} }

View file

@ -22,9 +22,18 @@
package zutil.plugin; package zutil.plugin;
import zutil.ClassUtil;
import zutil.log.LogUtil;
import zutil.parser.DataNode; import zutil.parser.DataNode;
import javax.xml.crypto.Data;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader; 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 * This class contains information about a plugin
@ -32,18 +41,36 @@ import java.net.URLClassLoader;
* *
* @author Ziver * @author Ziver
*/ */
public class PluginData<T> { public class PluginData {
private static Logger log = LogUtil.getLogger();
private double pluginVersion; private double pluginVersion;
private String pluginName; private String pluginName;
private String pluginClass; private HashMap<Class, Class> classMap;
private HashMap<Class, Object> objectMap;
private T obj; protected PluginData(DataNode data) throws ClassNotFoundException, MalformedURLException {
classMap = new HashMap<Class, Class>();
objectMap = new HashMap<Class, Object>();
protected PluginData(String intf, DataNode data){
pluginVersion = data.getDouble("version"); pluginVersion = data.getDouble("version");
pluginName = data.getString("name"); pluginName = data.getString("name");
pluginClass = data.get("interfaces").getString(intf); log.fine("Found plugin: "+pluginName);
DataNode node = data.get("interfaces");
Iterator<String> 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(){ public double getVersion(){
@ -52,13 +79,23 @@ public class PluginData<T> {
public String getName(){ public String getName(){
return pluginName; return pluginName;
} }
@SuppressWarnings("unchecked") public <T> T getObject(Class<T> intf) {
public T getObject() throws InstantiationException, IllegalAccessException, ClassNotFoundException{ if(classMap.containsKey(intf)) {
//if(obj == null) try {
// new URLClassLoader(pluginClass); Class subClass = classMap.get(intf);
// //obj = (T) Class.forName(pluginClass).newInstance(); if (objectMap.containsKey(subClass))
return obj; 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);
}
} }

View file

@ -24,11 +24,17 @@ package zutil.plugin;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; 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.FileSearch;
import zutil.io.file.FileUtil; import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
import zutil.parser.DataNode; import zutil.parser.DataNode;
import zutil.parser.json.JSONParser; import zutil.parser.json.JSONParser;
@ -40,39 +46,85 @@ import zutil.parser.json.JSONParser;
* *
* @author Ziver * @author Ziver
*/ */
public class PluginManager<T> implements Iterable<PluginData<T>>{ public class PluginManager<T> implements Iterable<PluginData>{
private HashMap<String, PluginData<T>> plugins; private static Logger log = LogUtil.getLogger();
public static <T> PluginManager<T> load(Class<T> intfClass) throws IOException{ private HashMap<String, PluginData> plugins;
return new PluginManager<T>(intfClass);
public static <T> PluginManager<T> load(String path){
return new PluginManager<T>(path);
} }
public PluginManager(){
private PluginManager(Class<T> intfClass) throws IOException{ this("./");
FileSearch search = new FileSearch(new File(".")); }
public PluginManager(String path){
plugins = new HashMap<String, PluginData>();
FileSearch search = new FileSearch(new File(path));
search.setRecursive(true); search.setRecursive(true);
search.searchFolders(false); search.searchFolders(false);
search.setFileName("plugin.json"); search.setFileName("plugin.json");
log.fine("Searching for plugins...");
for(FileSearch.FileSearchItem file : search){ for(FileSearch.FileSearchItem file : search){
DataNode node = JSONParser.read(FileUtil.getContent(file.getUrl())); try {
PluginData<T> plugin = new PluginData<T>(intfClass.getName(), node); DataNode node = JSONParser.read(IOUtil.getContentString(file.getInputStream()));
PluginData plugin = new PluginData(node);
if(node.get("interfaces").getString(intfClass.getName()) != null){
if(plugins.containsKey(plugin.getName())){ if (!plugins.containsKey(plugin.getName()) ||
if(plugins.get(plugin.getName()).getVersion() < plugin.getVersion()) plugins.get(plugin.getName()).getVersion() < plugin.getVersion()){
plugins.put(plugin.getName(), plugin);
}
else{
plugins.put(plugin.getName(), plugin); plugins.put(plugin.getName(), plugin);
} }
} catch (Exception e) {
e.printStackTrace();
} }
} }
} }
@Override @Override
public Iterator<PluginData<T>> iterator() { public Iterator<PluginData> iterator() {
return plugins.values().iterator(); return plugins.values().iterator();
} }
public <T> Iterator<T> iterator(Class<T> intf) {
return new PluginInterfaceIterator<T>(plugins.values().iterator(), intf);
}
public class PluginInterfaceIterator<T> implements Iterator<T> {
private Class<T> intf;
private Iterator<PluginData> it;
private PluginData next;
PluginInterfaceIterator(Iterator<PluginData> it, Class<T> 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");
}
}
} }

View file

@ -43,17 +43,28 @@ public class ConverterTest {
assertEquals( 0x00, Converter.hexToByte('0','0') ); assertEquals( 0x00, Converter.hexToByte('0','0') );
assertEquals( 0x11, Converter.hexToByte('1','1') ); assertEquals( 0x11, Converter.hexToByte('1','1') );
assertEquals( 0x75, Converter.hexToByte('7','5') ); assertEquals( 0x75, Converter.hexToByte('7','5') );
assertEquals( 0xDA, Converter.hexToByte('D','A') ); assertEquals( 0xDA, Converter.hexToByte('D','A') & 0xFF );
assertEquals( 0xFA, Converter.hexToByte('F','a') ); assertEquals( 0xFA, Converter.hexToByte('F','a') & 0xFF );
assertEquals( 0xFF, Converter.hexToByte('f','f') ); 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 @Test
public void testUrlEncode() { public void testUrlEncode() {
assertEquals( "fas8dg7%20a0d1%2313f9g8d7%200h9a%a4%25h0", assertEquals( "fas8dg7%20a0d1%2313f9g8d7%200h9a%25h0",
Converter.urlEncode("fas8dg7 a0d1#13f9g8d7 0h9a<39>%h0") ); Converter.urlEncode("fas8dg7 a0d1#13f9g8d7 0h9a%h0") );
assertEquals( "9i34%e5%202y92%a452%25%2623%20463765%a4(%2f%26(", assertEquals( "9i34%202y9252%25%2623%20463765(%2f%26(",
Converter.urlEncode("9i34<EFBFBD> 2y92<39>52%&23 463765<36>(/&(") ); Converter.urlEncode("9i34 2y9252%&23 463765(/&(") );
} }
@ -61,8 +72,8 @@ public class ConverterTest {
public void testUrlDecode() { public void testUrlDecode() {
assertEquals( "fas8dg7 a0d1#13f9g8d7 0h9a%h0", assertEquals( "fas8dg7 a0d1#13f9g8d7 0h9a%h0",
Converter.urlDecode("fas8dg7%20a0d1%2313f9g8d7%200h9a%25h0") ); Converter.urlDecode("fas8dg7%20a0d1%2313f9g8d7%200h9a%25h0") );
assertEquals( "9i34<EFBFBD> 2y9252%&23 463765(/&(", assertEquals( "9i34 2y9252%&23 463765(/&(",
Converter.urlDecode("9i34%e5%202y9252%25%2623%20463765(%2f%26(") ); Converter.urlDecode("9i34%202y9252%25%2623%20463765(%2f%26(") );
} }
} }

View file

@ -35,7 +35,7 @@ public class HTTPGuessTheNumber implements HttpPage{
public static void main(String[] args) throws IOException{ public static void main(String[] args) throws IOException{
//HttpServer server = new HttpServer("localhost", 443, FileFinder.find("keySSL"), "rootroot");//SSL //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.setDefaultPage(new HTTPGuessTheNumber());
server.run(); server.run();
} }

View file

@ -35,7 +35,7 @@ import zutil.net.http.HttpServer;
public class HTTPUploaderTest implements HttpPage{ public class HTTPUploaderTest implements HttpPage{
public static void main(String[] args) throws IOException{ public static void main(String[] args) throws IOException{
HttpServer server = new HttpServer("localhost", 80); HttpServer server = new HttpServer(80);
server.setDefaultPage(new HTTPUploaderTest()); server.setDefaultPage(new HTTPUploaderTest());
server.run(); server.run();
} }

View file

@ -42,7 +42,7 @@ public class UPnPServerTest {
UPnPContentDirectory cds = new UPnPContentDirectory(new File("C:\\Users\\Ziver\\Desktop\\lan")); UPnPContentDirectory cds = new UPnPContentDirectory(new File("C:\\Users\\Ziver\\Desktop\\lan"));
WebServiceDef ws = new WebServiceDef( UPnPContentDirectory.class ); 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.setDefaultPage(upnp);
http.setPage("/RootDesc", upnp ); http.setPage("/RootDesc", upnp );
http.setPage("/SCP/ContentDir", cds ); http.setPage("/SCP/ContentDir", cds );