This commit is contained in:
parent
e822a4b35c
commit
91cadbb301
20 changed files with 342 additions and 130 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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(); }
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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>();
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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){
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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(") );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 );
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue