This commit is contained in:
parent
e822a4b35c
commit
91cadbb301
20 changed files with 342 additions and 130 deletions
|
|
@ -72,6 +72,27 @@ public class Converter {
|
|||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -113,18 +113,19 @@ public class FileSearch implements Iterable<FileSearch.FileSearchItem>{
|
|||
protected class FileSearchIterator implements Iterator<FileSearchItem>{
|
||||
private ArrayList<FileSearchItem> fileList;
|
||||
private int currentIndex;
|
||||
private FileSearchItem nextItem;
|
||||
|
||||
public FileSearchIterator(){
|
||||
fileList = new ArrayList<FileSearchItem>();
|
||||
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<FileSearch.FileSearchItem>{
|
|||
|
||||
@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<fileList.size(); currentIndex++){
|
||||
FileSearchItem file = fileList.get(currentIndex);
|
||||
if(recursive && file.isDirectory()){
|
||||
addFiles(file.listFiles());
|
||||
addFiles(file, file.listFiles());
|
||||
if(searchFolders && file.getName().equalsIgnoreCase(fileName))
|
||||
break;
|
||||
}
|
||||
else if(searchCompressedFiles && file.isFile() &&
|
||||
compressedFileExtensions.contains(FileUtil.getFileExtension(file.getName()).toLowerCase())){
|
||||
try {
|
||||
String url = file.getUrl().getFile();
|
||||
ZipFile zipFile = new ZipFile(url);
|
||||
ZipFile zipFile = new ZipFile(file.getPath());
|
||||
Enumeration<? extends ZipEntry> 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<FileSearch.FileSearchItem>{
|
|||
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<FileSearch.FileSearchItem>{
|
|||
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<FileSearch.FileSearchItem>{
|
|||
}
|
||||
|
||||
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<FileSearch.FileSearchItem>{
|
|||
}
|
||||
|
||||
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(); }
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<String,HttpPage> pages;
|
||||
|
|
@ -64,25 +63,22 @@ 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<String,HttpPage>();
|
||||
|
|
|
|||
|
|
@ -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,8 +74,8 @@ 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<String, LinkedList<SSDPServiceInfo>>();
|
||||
services_usn = new HashMap<String, SSDPServiceInfo>();
|
||||
|
|
@ -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<String,String> headers){
|
||||
try {
|
||||
services_st.put( st, new LinkedList<SSDPServiceInfo>() );
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
@ -121,6 +130,13 @@ public class SSDPClient extends ThreadedUDPNetwork implements ThreadedUDPNetwork
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.setInetAddress(packet.getAddress());
|
||||
if(header.getHeader("Cache-Control") != null) {
|
||||
service.setExpirationTime(
|
||||
System.currentTimeMillis() +
|
||||
1000 * getCacheTime(header.getHeader("Cache-Control")) );
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<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.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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,11 +35,14 @@ 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<String, String> headers;
|
||||
private InetAddress inetAddress;
|
||||
|
||||
/**
|
||||
* @param l is the value to set the Location variable
|
||||
|
|
@ -107,7 +114,6 @@ public class StandardSSDPInfo implements SSDPServiceInfo{
|
|||
/**
|
||||
* 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<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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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){
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
public String[] runCommand(String cmd) {
|
||||
ArrayList<String> ret = new ArrayList<String>();
|
||||
try {
|
||||
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>();
|
||||
|
||||
String line;
|
||||
while((line = output.readLine()) != null){
|
||||
while ((line = output.readLine()) != null) {
|
||||
ret.add(line);
|
||||
}
|
||||
output.close();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return ret.toArray(new String[1]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T> {
|
||||
public class PluginData {
|
||||
private static Logger log = LogUtil.getLogger();
|
||||
|
||||
private double pluginVersion;
|
||||
private String pluginName;
|
||||
private String pluginClass;
|
||||
|
||||
private T obj;
|
||||
private HashMap<Class, Class> classMap;
|
||||
private HashMap<Class, Object> objectMap;
|
||||
|
||||
|
||||
protected PluginData(String intf, DataNode data){
|
||||
protected PluginData(DataNode data) throws ClassNotFoundException, MalformedURLException {
|
||||
classMap = new HashMap<Class, Class>();
|
||||
objectMap = new HashMap<Class, Object>();
|
||||
|
||||
pluginVersion = data.getDouble("version");
|
||||
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(){
|
||||
|
|
@ -53,12 +80,22 @@ public class PluginData<T> {
|
|||
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> T getObject(Class<T> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T> implements Iterable<PluginData<T>>{
|
||||
private HashMap<String, PluginData<T>> plugins;
|
||||
public class PluginManager<T> implements Iterable<PluginData>{
|
||||
private static Logger log = LogUtil.getLogger();
|
||||
|
||||
public static <T> PluginManager<T> load(Class<T> intfClass) throws IOException{
|
||||
return new PluginManager<T>(intfClass);
|
||||
private HashMap<String, PluginData> plugins;
|
||||
|
||||
|
||||
public static <T> PluginManager<T> load(String path){
|
||||
return new PluginManager<T>(path);
|
||||
}
|
||||
|
||||
public PluginManager(){
|
||||
this("./");
|
||||
}
|
||||
public PluginManager(String path){
|
||||
plugins = new HashMap<String, PluginData>();
|
||||
|
||||
private PluginManager(Class<T> intfClass) throws IOException{
|
||||
FileSearch search = new FileSearch(new File("."));
|
||||
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<T> plugin = new PluginData<T>(intfClass.getName(), node);
|
||||
try {
|
||||
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.get(plugin.getName()).getVersion() < plugin.getVersion())
|
||||
plugins.put(plugin.getName(), plugin);
|
||||
}
|
||||
else{
|
||||
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<PluginData<T>> iterator() {
|
||||
public Iterator<PluginData> 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<39>%h0") );
|
||||
assertEquals( "9i34%e5%202y92%a452%25%2623%20463765%a4(%2f%26(",
|
||||
Converter.urlEncode("9i34<EFBFBD> 2y92<39>52%&23 463765<36>(/&(") );
|
||||
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<EFBFBD> 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(") );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue