diff --git a/licenses/LICENSE-UPnP.txt b/licenses/LICENSE-UPnP.txt index 7e2a36863..e75a1be16 100644 --- a/licenses/LICENSE-UPnP.txt +++ b/licenses/LICENSE-UPnP.txt @@ -1,12 +1,21 @@ -Copyright (C) 2003-2006 Satoshi Konno +Copyright (c) 2003-2010, Satoshi Konno + All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of the Cyber Garage nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/router/java/src/org/cybergarage/http/Date.java b/router/java/src/org/cybergarage/http/Date.java index a3424eb57..117964d34 100644 --- a/router/java/src/org/cybergarage/http/Date.java +++ b/router/java/src/org/cybergarage/http/Date.java @@ -1,8 +1,8 @@ /****************************************************************** * -* CyberHTTP for Java -* -* Copyright (C) Satoshi Konno 2002-2003 +* CyberHTTP for Java +* +* Copyright (C) Satoshi Konno 2002-2003 * * File : Date.java * @@ -16,7 +16,7 @@ * getHour(), getDateString() getTimeString() * - Fixed getInstance() to return GMT instance. * -******************************************************************/ +******************************************************************/ package org.cybergarage.http; @@ -136,15 +136,15 @@ public class Date public String getDateString() { // Thanks for Theo Beisch (10/20/04) - Calendar _cal = getCalendar(); + Calendar cal = getCalendar(); return - toWeekString(_cal.get(Calendar.DAY_OF_WEEK)) +", " + - toTimeString(_cal.get(Calendar.DATE)) + " " + - toMonthString(_cal.get(Calendar.MONTH)) + " " + - Integer.toString(_cal.get(Calendar.YEAR)) + " " + - toTimeString(_cal.get(Calendar.HOUR_OF_DAY)) + ":" + - toTimeString(_cal.get(Calendar.MINUTE)) + ":" + - toTimeString(_cal.get(Calendar.SECOND)) + " GMT"; + toWeekString(cal.get(Calendar.DAY_OF_WEEK)) +", " + + toTimeString(cal.get(Calendar.DATE)) + " " + + toMonthString(cal.get(Calendar.MONTH)) + " " + + Integer.toString(cal.get(Calendar.YEAR)) + " " + + toTimeString(cal.get(Calendar.HOUR_OF_DAY)) + ":" + + toTimeString(cal.get(Calendar.MINUTE)) + ":" + + toTimeString(cal.get(Calendar.SECOND)) + " GMT"; } //////////////////////////////////////////////// @@ -154,11 +154,11 @@ public class Date public String getTimeString() { // Thanks for Theo Beisch (10/20/04) - Calendar _cal = getCalendar(); + Calendar cal = getCalendar(); return - toDateString(_cal.get(Calendar.HOUR_OF_DAY)) + - (((_cal.get(Calendar.SECOND) % 2) == 0) ? ":" : " ") + - toDateString(_cal.get(Calendar.MINUTE)); + toDateString(cal.get(Calendar.HOUR_OF_DAY)) + + (((cal.get(Calendar.SECOND) % 2) == 0) ? ":" : " ") + + toDateString(cal.get(Calendar.MINUTE)); } } diff --git a/router/java/src/org/cybergarage/http/HTTP.java b/router/java/src/org/cybergarage/http/HTTP.java index ec7ccbde1..554da7f25 100644 --- a/router/java/src/org/cybergarage/http/HTTP.java +++ b/router/java/src/org/cybergarage/http/HTTP.java @@ -30,7 +30,7 @@ package org.cybergarage.http; -import java.net.*; +import java.net.URL; public class HTTP { @@ -45,6 +45,8 @@ public class HTTP public static final String VERSION_11 = "1.1"; public static final String CRLF = "\r\n"; + public static final byte CR = '\r'; + public static final byte LF = '\n'; public static final String TAB = "\t"; public static final String SOAP_ACTION = "SOAPACTION"; @@ -59,19 +61,20 @@ public class HTTP public static final String DATE = "Date"; public static final String CACHE_CONTROL = "Cache-Control"; - public static final String NO_CACHE = "no-cache"; - public static final String MAX_AGE = "max-age"; + public static final String NO_CACHE = "no-cache"; + public static final String MAX_AGE = "max-age"; public static final String CONNECTION = "Connection"; - public static final String CLOSE = "close"; + public static final String CLOSE = "close"; public static final String KEEP_ALIVE = "Keep-Alive"; public static final String CONTENT_TYPE = "Content-Type"; + public static final String CHARSET = "charset"; public static final String CONTENT_LENGTH = "Content-Length"; public static final String CONTENT_RANGE = "Content-Range"; - public static final String CONTENT_RANGE_BYTES = "bytes"; + public static final String CONTENT_RANGE_BYTES = "bytes"; // Thanks for Brent Hills (10/20/04) public static final String RANGE = "Range"; public static final String TRANSFER_ENCODING = "Transfer-Encoding"; - public static final String CHUNKED = "Chunked"; + public static final String CHUNKED = "Chunked"; public static final String LOCATION = "Location"; public static final String SERVER = "Server"; diff --git a/router/java/src/org/cybergarage/http/HTTPHeader.java b/router/java/src/org/cybergarage/http/HTTPHeader.java index 129ec7226..c6b28e17c 100644 --- a/router/java/src/org/cybergarage/http/HTTPHeader.java +++ b/router/java/src/org/cybergarage/http/HTTPHeader.java @@ -5,34 +5,37 @@ * Copyright (C) Satoshi Konno 2002 * * File: HTTPHeader.java -* -* Revision; -* -* 11/19/02 -* - first revision. +* +* Revision; +* +* 11/19/02 +* - first revision. * 05/26/04 * - Jan Newmarch (05/26/04) * - Fixed getValue() to compare using String::equals() instead of String::startWidth(). * ******************************************************************/ - + package org.cybergarage.http; - -import java.io.*; + +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.StringReader; import java.util.Locale; -import org.cybergarage.util.*; - -public class HTTPHeader +import org.cybergarage.util.Debug; + +public class HTTPHeader { - private String name; - private String value; - - public HTTPHeader(String name, String value) - { - setName(name); - setValue(value); - } + private static int MAX_LENGTH = 1024; + private String name; + private String value; + + public HTTPHeader(String name, String value) + { + setName(name); + setValue(value); + } public HTTPHeader(String lineStr) { @@ -43,35 +46,35 @@ public class HTTPHeader int colonIdx = lineStr.indexOf(':'); if (colonIdx < 0) return; - String _name = new String(lineStr.getBytes(), 0, colonIdx); - String _value = new String(lineStr.getBytes(), colonIdx+1, lineStr.length()-colonIdx-1); - setName(_name.trim()); - setValue(_value.trim()); + String name = new String(lineStr.getBytes(), 0, colonIdx); + String value = new String(lineStr.getBytes(), colonIdx+1, lineStr.length()-colonIdx-1); + setName(name.trim()); + setValue(value.trim()); } - + //////////////////////////////////////////////// // Member //////////////////////////////////////////////// - public void setName(String name) - { - this.name = name; - } - - public void setValue(String value) - { - this.value = value; - } - - public String getName() - { - return name; - } - - public String getValue() - { - return value; - } + public void setName(String name) + { + this.name = name; + } + + public void setValue(String value) + { + this.value = value; + } + + public String getName() + { + return name; + } + + public String getValue() + { + return value; + } public boolean hasName() { @@ -79,67 +82,68 @@ public class HTTPHeader return false; return true; } - - //////////////////////////////////////////////// - // static methods - //////////////////////////////////////////////// - - public final static String getValue(LineNumberReader reader, String name) - { - String bigName = name.toUpperCase(Locale.US); - try { - String lineStr = reader.readLine(); - while (lineStr != null && 0 < lineStr.length()) { + + //////////////////////////////////////////////// + // static methods + //////////////////////////////////////////////// + + public final static String getValue(LineNumberReader reader, String name) + { + String bigName = name.toUpperCase(Locale.US); + try { + String lineStr = reader.readLine(); + while (lineStr != null && 0 < lineStr.length()) { HTTPHeader header = new HTTPHeader(lineStr); - if (header.hasName() == false) { - lineStr = reader.readLine(); - continue; - } + if (header.hasName() == false) { + lineStr = reader.readLine(); + continue; + } String bigLineHeaderName = header.getName().toUpperCase(Locale.US); - // Thanks for Jan Newmarch (05/26/04) - if (bigLineHeaderName.equals(bigName) == false) { - lineStr = reader.readLine(); - continue; - } - return header.getValue(); - } - } + // Thanks for Jan Newmarch (05/26/04) + if (bigLineHeaderName.equals(bigName) == false) { + lineStr = reader.readLine(); + continue; + } + return header.getValue(); + } + } catch (IOException e) { - Debug.warning(e); - return ""; - } - return ""; - } - - public final static String getValue(String data, String name) + Debug.warning(e); + return ""; + } + return ""; + } + + public final static String getValue(String data, String name) { + /* Thanks for Stephan Mehlhase (2010-10-26) */ StringReader strReader = new StringReader(data); - LineNumberReader lineReader = new LineNumberReader(strReader); - return getValue(lineReader, name); - } - - public final static String getValue(byte[] data, String name) - { - return getValue(new String(data), name); - } - - public final static int getIntegerValue(String data, String name) + LineNumberReader lineReader = new LineNumberReader(strReader, Math.min(data.length(), MAX_LENGTH)); + return getValue(lineReader, name); + } + + public final static String getValue(byte[] data, String name) + { + return getValue(new String(data), name); + } + + public final static int getIntegerValue(String data, String name) { try { return Integer.parseInt(getValue(data, name)); } catch (Exception e) { return 0; - } - } - - public final static int getIntegerValue(byte[] data, String name) - { + } + } + + public final static int getIntegerValue(byte[] data, String name) + { try { return Integer.parseInt(getValue(data, name)); } catch (Exception e) { return 0; } - } + } } diff --git a/router/java/src/org/cybergarage/http/HTTPPacket.java b/router/java/src/org/cybergarage/http/HTTPPacket.java index 7a5ea924d..9a7575f32 100644 --- a/router/java/src/org/cybergarage/http/HTTPPacket.java +++ b/router/java/src/org/cybergarage/http/HTTPPacket.java @@ -59,17 +59,35 @@ * hasTransferEncoding(), setTransferEncoding(), getTransferEncoding(), isChunked(). * 03/02/05 * - Changed post() to suppot chunked stream. +* 06/11/05 +* - Added setHost(). +* 07/07/05 +* - Lee Peik Feng +* - Andrey Ovchar +* - Fixed set() to parse the chunk size as a hex string. +* 11/02/05 +* - Changed set() to use BufferedInputStream instead of BufferedReader to +* get the content as a byte stream. +* 11/06/05 +* - Added getCharSet(). +* - Changed getContentString() to return the content string using the charset. * *******************************************************************/ package org.cybergarage.http; -import java.io.*; -import java.util.*; - -import org.cybergarage.net.*; -import org.cybergarage.util.*; +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; import java.util.Calendar; +import java.util.StringTokenizer; +import java.util.Vector; + +import org.cybergarage.net.HostInterface; +import org.cybergarage.util.Debug; +import org.cybergarage.util.StringUtil; public class HTTPPacket { @@ -129,18 +147,44 @@ public class HTTPPacket // set //////////////////////////////////////////////// + private String readLine(BufferedInputStream in) + { + ByteArrayOutputStream lineBuf = new ByteArrayOutputStream(); + byte readBuf[] = new byte[1]; + + try { + int readLen = in.read(readBuf); + while (0 < readLen) { + if (readBuf[0] == HTTP.LF) + break; + if (readBuf[0] != HTTP.CR) + lineBuf.write(readBuf[0]); + readLen = in.read(readBuf); + } + } + catch (InterruptedIOException e) { + //Ignoring warning because it's a way to break the HTTP connecttion + //TODO Create a new level of Logging and log the event + } + catch (IOException e) { + Debug.warning(e); + } + + return lineBuf.toString(); + } + protected boolean set(InputStream in, boolean onlyHeaders) { try { - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + BufferedInputStream reader = new BufferedInputStream(in); - String _firstLine = reader.readLine(); - if (_firstLine == null || _firstLine.length() <= 0) + String firstLine = readLine(reader); + if (firstLine == null || firstLine.length() <= 0) return false; - setFirstLine(_firstLine); + setFirstLine(firstLine); // Thanks for Giordano Sassaroli (09/03/03) - HTTPStatus httpStatus = new HTTPStatus(_firstLine); + HTTPStatus httpStatus = new HTTPStatus(firstLine); int statCode = httpStatus.getStatusCode(); if (statCode == HTTPStatus.CONTINUE){ //ad hoc code for managing iis non-standard behaviour @@ -148,15 +192,15 @@ public class HTTPPacket //stream, so the code should check the presence of the actual //response in the stream. //skip all header lines - String headerLine = reader.readLine(); + String headerLine = readLine(reader); while ((headerLine != null) && (0 < headerLine.length()) ) { HTTPHeader header = new HTTPHeader(headerLine); if (header.hasName() == true) setHeader(header); - headerLine = reader.readLine(); + headerLine = readLine(reader); } //look forward another first line - String actualFirstLine = reader.readLine(); + String actualFirstLine = readLine(reader); if ((actualFirstLine != null) && (0 < actualFirstLine.length()) ) { //this is the actual first line setFirstLine(actualFirstLine); @@ -165,12 +209,12 @@ public class HTTPPacket } } - String headerLine = reader.readLine(); + String headerLine = readLine(reader); while ((headerLine != null) && (0 < headerLine.length()) ) { HTTPHeader header = new HTTPHeader(headerLine); if (header.hasName() == true) setHeader(header); - headerLine = reader.readLine(); + headerLine = readLine(reader); } if (onlyHeaders == true) { @@ -183,19 +227,24 @@ public class HTTPPacket long contentLen = 0; if (isChunkedRequest == true) { try { - String chunkSizeLine = reader.readLine(); - contentLen = Long.parseLong(new String(chunkSizeLine.getBytes(), 0, chunkSizeLine.length()-2)); + String chunkSizeLine = readLine(reader); + // Thanks for Lee Peik Feng (07/07/05) + //contentLen = Long.parseLong(new String(chunkSizeLine.getBytes(), 0, chunkSizeLine.length()-2), 16); + contentLen = (chunkSizeLine != null) ? Long.parseLong(chunkSizeLine.trim(), 16) : 0; } - catch (Exception e) {} + catch (Exception e) {}; } else contentLen = getContentLength(); - StringBuilder contentBuf = new StringBuilder(); + ByteArrayOutputStream contentBuf = new ByteArrayOutputStream(); while (0 < contentLen) { int chunkSize = HTTP.getChunkSize(); - char readBuf[] = new char[chunkSize]; + + /* Thanks for Stephan Mehlhase (2010-10-26) */ + byte readBuf[] = new byte[(int) (contentLen > chunkSize ? chunkSize : contentLen)]; + long readCnt = 0; while (readCnt < contentLen) { try { @@ -206,7 +255,7 @@ public class HTTPPacket int readLen = reader.read(readBuf, 0, (int)bufReadLen); if (readLen < 0) break; - contentBuf.append(new String(readBuf, 0, readLen)); + contentBuf.write(readBuf, 0, readLen); readCnt += readLen; } catch (Exception e) @@ -226,20 +275,19 @@ public class HTTPPacket } while (skipLen < HTTP.CRLF.length()); // read next chunk size try { - String chunkSizeLine = reader.readLine(); - contentLen = Long.parseLong(new String(chunkSizeLine.getBytes(), 0, chunkSizeLine.length()-2)); + String chunkSizeLine = readLine(reader); + // Thanks for Lee Peik Feng (07/07/05) + contentLen = Long.parseLong(new String(chunkSizeLine.getBytes(), 0, chunkSizeLine.length()-2), 16); } catch (Exception e) { contentLen = 0; - } + }; } else contentLen = 0; } - // Thanks for Ralf G. R. Bergs (02/09/04) - String contentStr = contentBuf.toString(); - setContent(contentStr.getBytes(), false); + setContent(contentBuf.toByteArray(), false); } catch (Exception e) { Debug.warning(e); @@ -464,7 +512,7 @@ public class HTTPPacket public String getHeaderString() { - StringBuilder str = new StringBuilder(); + StringBuffer str = new StringBuffer(); int nHeaders = getNHeaders(); for (int n=0; n * - Add a relative URL check to setURI(). @@ -44,26 +44,46 @@ * - Added to check the range of Content-Range request in post(). * 03/02/05 * - Changed post() to suppot chunked stream. +* 06/10/05 +* - Changed post() to add a HOST headedr before the posting. +* 07/07/05 +* - Lee Peik Feng +* - Fixed post() to output the chunk size as a hex string. * ******************************************************************/ - + package org.cybergarage.http; - -import java.io.*; -import java.net.*; -import java.util.*; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.InetSocketAddress; +import java.util.StringTokenizer; import org.cybergarage.util.Debug; - -public class HTTPRequest extends HTTPPacket -{ - //////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////// - - public HTTPRequest() - { - } +/** + * + * This class rappresnet an HTTP request, and act as HTTP client when it sends the request
+ * + * @author Satoshi "skonno" Konno + * @author Stefano "Kismet" Lenzi + * @version 1.8 + * + */ +public class HTTPRequest extends HTTPPacket +{ + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + public HTTPRequest() + { + setVersion(HTTP.VERSION_10); + } public HTTPRequest(InputStream in) { @@ -76,23 +96,23 @@ public class HTTPRequest extends HTTPPacket setSocket(httpSock); } - //////////////////////////////////////////////// - // Method - //////////////////////////////////////////////// - - private String method = null; - - public void setMethod(String value) + //////////////////////////////////////////////// + // Method + //////////////////////////////////////////////// + + private String method = null; + + public void setMethod(String value) + { + method = value; + } + + public String getMethod() { - method = value; - } - - public String getMethod() - { - if (method != null) + if (method != null) return method; - return getFirstLineToken(0); - } + return getFirstLineToken(0); + } public boolean isMethod(String method) { @@ -101,16 +121,16 @@ public class HTTPRequest extends HTTPPacket return false; return headerMethod.equalsIgnoreCase(method); } - - public boolean isGetRequest() - { - return isMethod(HTTP.GET); - } - - public boolean isPostRequest() + + public boolean isGetRequest() { + return isMethod(HTTP.GET); + } + + public boolean isPostRequest() + { return isMethod(HTTP.POST); - } + } public boolean isHeadRequest() { @@ -132,33 +152,33 @@ public class HTTPRequest extends HTTPPacket return isMethod(HTTP.NOTIFY); } - //////////////////////////////////////////////// - // URI - //////////////////////////////////////////////// - - private String uri = null; - - public void setURI(String value, boolean isCheckRelativeURL) - { + //////////////////////////////////////////////// + // URI + //////////////////////////////////////////////// + + private String uri = null; + + public void setURI(String value, boolean isCheckRelativeURL) + { uri = value; if (isCheckRelativeURL == false) return; // Thanks for Giordano Sassaroli (09/02/03) uri = HTTP.toRelativeURL(uri); - } + } public void setURI(String value) { setURI(value, false); } - public String getURI() + public String getURI() { - if (uri != null) - return uri; + if (uri != null) + return uri; return getFirstLineToken(1); - } - + } + //////////////////////////////////////////////// // URI Parameter //////////////////////////////////////////////// @@ -166,17 +186,17 @@ public class HTTPRequest extends HTTPPacket public ParameterList getParameterList() { ParameterList paramList = new ParameterList(); - String _uri = getURI(); - if (_uri == null) + String uri = getURI(); + if (uri == null) return paramList; - int paramIdx = _uri.indexOf('?'); + int paramIdx = uri.indexOf('?'); if (paramIdx < 0) return paramList; while (0 < paramIdx) { - int eqIdx = _uri.indexOf('=', (paramIdx+1)); - String name = _uri.substring(paramIdx+1, eqIdx); - int nextParamIdx = _uri.indexOf('&', (eqIdx+1)); - String value = _uri.substring(eqIdx+1, (0 < nextParamIdx) ? nextParamIdx : _uri.length()); + int eqIdx = uri.indexOf('=', (paramIdx+1)); + String name = uri.substring(paramIdx+1, eqIdx); + int nextParamIdx = uri.indexOf('&', (eqIdx+1)); + String value = uri.substring(eqIdx+1, (0 < nextParamIdx) ? nextParamIdx : uri.length()); Parameter param = new Parameter(name, value); paramList.add(param); paramIdx = nextParamIdx; @@ -227,21 +247,21 @@ public class HTTPRequest extends HTTPPacket return requestPort; } - //////////////////////////////////////////////// - // Socket - //////////////////////////////////////////////// - - private HTTPSocket httpSocket = null; - - public void setSocket(HTTPSocket value) - { - httpSocket = value; - } - - public HTTPSocket getSocket() - { - return httpSocket; - } + //////////////////////////////////////////////// + // Socket + //////////////////////////////////////////////// + + private HTTPSocket httpSocket = null; + + public void setSocket(HTTPSocket value) + { + httpSocket = value; + } + + public HTTPSocket getSocket() + { + return httpSocket; + } /////////////////////////// ///////////////////// // local address/port @@ -256,25 +276,25 @@ public class HTTPRequest extends HTTPPacket { return getSocket().getLocalPort(); } - - //////////////////////////////////////////////// - // parseRequest - //////////////////////////////////////////////// - - public boolean parseRequestLine(String lineStr) - { - StringTokenizer st = new StringTokenizer(lineStr, HTTP.REQEST_LINE_DELIM); - if (st.hasMoreTokens() == false) - return false; - setMethod(st.nextToken()); - if (st.hasMoreTokens() == false) - return false; - setURI(st.nextToken()); - if (st.hasMoreTokens() == false) - return false; - setVersion(st.nextToken()); - return true; - } + + //////////////////////////////////////////////// + // parseRequest + //////////////////////////////////////////////// + + public boolean parseRequestLine(String lineStr) + { + StringTokenizer st = new StringTokenizer(lineStr, HTTP.REQEST_LINE_DELIM); + if (st.hasMoreTokens() == false) + return false; + setMethod(st.nextToken()); + if (st.hasMoreTokens() == false) + return false; + setURI(st.nextToken()); + if (st.hasMoreTokens() == false) + return false; + setVersion(st.nextToken()); + return true; + } //////////////////////////////////////////////// // First Line @@ -292,22 +312,22 @@ public class HTTPRequest extends HTTPPacket return getMethod() + " " + getURI() + " " + getHTTPVersion() + HTTP.CRLF; } - //////////////////////////////////////////////// - // getHeader - //////////////////////////////////////////////// - - public String getHeader() - { - StringBuilder str = new StringBuilder(); - - str.append(getFirstLineString()); - + //////////////////////////////////////////////// + // getHeader + //////////////////////////////////////////////// + + public String getHeader() + { + StringBuffer str = new StringBuffer(); + + str.append(getFirstLineString()); + String headerString = getHeaderString(); str.append(headerString); - - return str.toString(); - } - + + return str.toString(); + } + //////////////////////////////////////////////// // isKeepAlive //////////////////////////////////////////////// @@ -334,9 +354,9 @@ public class HTTPRequest extends HTTPPacket return super.read(getSocket()); } - //////////////////////////////////////////////// - // POST (Response) - //////////////////////////////////////////////// + //////////////////////////////////////////////// + // POST (Response) + //////////////////////////////////////////////// public boolean post(HTTPResponse httpRes) { @@ -361,17 +381,19 @@ public class HTTPRequest extends HTTPPacket return httpSock.post(httpRes, offset, length, isHeadRequest()); //httpSock.close(); } - + //////////////////////////////////////////////// // POST (Request) //////////////////////////////////////////////// private Socket postSocket = null; - public HTTPResponse post(String host, int port, boolean isKeepAlive) - { + public HTTPResponse post(String host, int port, boolean isKeepAlive) + { HTTPResponse httpRes = new HTTPResponse(); + setHost(host); + setConnection((isKeepAlive == true) ? HTTP.KEEP_ALIVE : HTTP.CLOSE); boolean isHeaderRequest = isHeadRequest(); @@ -396,9 +418,9 @@ public class HTTPRequest extends HTTPPacket postSocket.connect(sa, 3000); } - out = postSocket.getOutputStream(); - PrintStream pout = new PrintStream(out); - pout.print(getHeader()); + out = postSocket.getOutputStream(); + PrintStream pout = new PrintStream(out); + pout.print(getHeader()); pout.print(HTTP.CRLF); boolean isChunkedRequest = isChunked(); @@ -407,10 +429,11 @@ public class HTTPRequest extends HTTPPacket int contentLength = 0; if (content != null) contentLength = content.length(); - + if (0 < contentLength) { if (isChunkedRequest == true) { - String chunSizeBuf = Long.toString(contentLength); + // Thanks for Lee Peik Feng (07/07/05) + String chunSizeBuf = Long.toHexString(contentLength); pout.print(chunSizeBuf); pout.print(HTTP.CRLF); } @@ -424,34 +447,37 @@ public class HTTPRequest extends HTTPPacket pout.print(HTTP.CRLF); } - pout.flush(); + pout.flush(); in = postSocket.getInputStream(); httpRes.set(in, isHeaderRequest); - } - catch (Exception e) { + } catch (SocketException e) { + httpRes.setStatusCode(HTTPStatus.INTERNAL_SERVER_ERROR); + Debug.warning(e); + } catch (IOException e) { + //Socket create but without connection + //TODO Blacklistening the device httpRes.setStatusCode(HTTPStatus.INTERNAL_SERVER_ERROR); - // I2P addition Debug.warning(e); } finally { if (isKeepAlive == false) { try { in.close(); - } catch (Exception e) {} + } catch (Exception e) {}; if (in != null) try { out.close(); - } catch (Exception e) {} + } catch (Exception e) {}; if (out != null) try { postSocket.close(); - } catch (Exception e) {} + } catch (Exception e) {}; postSocket = null; } } return httpRes; - } + } public HTTPResponse post(String host, int port) { @@ -490,21 +516,20 @@ public class HTTPRequest extends HTTPPacket return returnResponse(HTTPStatus.BAD_REQUEST); } - //////////////////////////////////////////////// - // toString - //////////////////////////////////////////////// - - @Override - public String toString() - { - StringBuilder str = new StringBuilder(); - - str.append(getHeader()); - str.append(HTTP.CRLF); - str.append(getContentString()); - - return str.toString(); - } + //////////////////////////////////////////////// + // toString + //////////////////////////////////////////////// + + public String toString() + { + StringBuffer str = new StringBuffer(); + + str.append(getHeader()); + str.append(HTTP.CRLF); + str.append(getContentString()); + + return str.toString(); + } public void print() { diff --git a/router/java/src/org/cybergarage/http/HTTPResponse.java b/router/java/src/org/cybergarage/http/HTTPResponse.java index 9d6818083..8c9c25091 100644 --- a/router/java/src/org/cybergarage/http/HTTPResponse.java +++ b/router/java/src/org/cybergarage/http/HTTPResponse.java @@ -5,11 +5,11 @@ * Copyright (C) Satoshi Konno 2002-2003 * * File: HTTPResponse.java -* -* Revision; -* -* 11/18/02 -* - first revision. +* +* Revision; +* +* 11/18/02 +* - first revision. * 10/22/03 * - Changed to initialize a content length header. * 10/22/04 @@ -17,23 +17,24 @@ * ******************************************************************/ -package org.cybergarage.http; +package org.cybergarage.http; -import java.io.*; +import java.io.InputStream; import org.cybergarage.util.Debug; - -public class HTTPResponse extends HTTPPacket -{ - //////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////// - - public HTTPResponse() - { + +public class HTTPResponse extends HTTPPacket +{ + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + public HTTPResponse() + { + setVersion(HTTP.VERSION_11); setContentType(HTML.CONTENT_TYPE); setServer(HTTPServer.getName()); setContent(""); - } + } public HTTPResponse(HTTPResponse httpRes) { @@ -49,25 +50,25 @@ public class HTTPResponse extends HTTPPacket { this(httpSock.getInputStream()); } - - //////////////////////////////////////////////// - // Status Line - //////////////////////////////////////////////// + + //////////////////////////////////////////////// + // Status Line + //////////////////////////////////////////////// private int statusCode = 0; - - public void setStatusCode(int code) + + public void setStatusCode(int code) { - statusCode = code; - } - - public int getStatusCode() + statusCode = code; + } + + public int getStatusCode() { if (statusCode != 0) - return statusCode; + return statusCode; HTTPStatus httpStatus = new HTTPStatus(getFirstLine()); - return httpStatus.getStatusCode(); - } + return httpStatus.getStatusCode(); + } public boolean isSuccessful() { @@ -78,29 +79,28 @@ public class HTTPResponse extends HTTPPacket { return "HTTP/" + getVersion() + " " + getStatusCode() + " " + HTTPStatus.code2String(statusCode) + HTTP.CRLF; } - - //////////////////////////////////////////////// - // getHeader - //////////////////////////////////////////////// - - public String getHeader() - { - StringBuilder str = new StringBuilder(); - - str.append(getStatusLineString()); + + //////////////////////////////////////////////// + // getHeader + //////////////////////////////////////////////// + + public String getHeader() + { + StringBuffer str = new StringBuffer(); + + str.append(getStatusLineString()); str.append(getHeaderString()); - - return str.toString(); - } + + return str.toString(); + } //////////////////////////////////////////////// // toString //////////////////////////////////////////////// - @Override public String toString() { - StringBuilder str = new StringBuilder(); + StringBuffer str = new StringBuffer(); str.append(getStatusLineString()); str.append(getHeaderString()); diff --git a/router/java/src/org/cybergarage/http/HTTPServer.java b/router/java/src/org/cybergarage/http/HTTPServer.java index 75c88c2b8..e498b7198 100644 --- a/router/java/src/org/cybergarage/http/HTTPServer.java +++ b/router/java/src/org/cybergarage/http/HTTPServer.java @@ -5,36 +5,57 @@ * Copyright (C) Satoshi Konno 2002-2003 * * File: HTTPServer.java -* -* Revision; -* -* 12/12/02 -* - first revision. +* +* Revision; +* +* 12/12/02 +* - first revision. * 10/20/03 * - Improved the HTTP server using multithreading. * 08/27/04 * - Changed accept() to set a default timeout, HTTP.DEFAULT_TIMEOUT, to the socket. * ******************************************************************/ - -package org.cybergarage.http; - -import java.io.*; -import java.net.*; - -import org.cybergarage.util.*; - -public class HTTPServer implements Runnable -{ - //////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////// - + +package org.cybergarage.http; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; + +import org.cybergarage.util.Debug; +import org.cybergarage.util.ListenerList; + +/** + * + * This class identifies an HTTP over TCP server
+ * The server must be initialized iether by the {@link HTTPServer#open(InetAddress, int)} or the {@link HTTPServer#open(String, int)} method.
+ * Optionally a set of {@link HTTPRequestListener} may be set
+ * The server then can be started or stopped by the method {@link HTTPServer#start()} and {@link HTTPServer#stop()} + * + * @author Satoshi "skonno" Konno + * @author Stefano "Kismet" Lenzi + * @version 1.8 + * + */ +public class HTTPServer implements Runnable +{ + //////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////// + public final static String NAME = "CyberHTTP"; public final static String VERSION = "1.0"; public final static int DEFAULT_PORT = 80; - + + /** + * Default timeout connection for HTTP comunication + * @since 1.8 + */ + public final static int DEFAULT_TIMEOUT = DEFAULT_PORT * 1000; + public static String getName() { String osName = System.getProperty("os.name"); @@ -42,27 +63,33 @@ public class HTTPServer implements Runnable return osName + "/" + osVer + " " + NAME + "/" + VERSION; } - //////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////// - - public HTTPServer() + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + public HTTPServer() { - serverSock = null; - } - - //////////////////////////////////////////////// - // ServerSocket - //////////////////////////////////////////////// - - private ServerSocket serverSock = null; + serverSock = null; + + } + + //////////////////////////////////////////////// + // ServerSocket + //////////////////////////////////////////////// + + private ServerSocket serverSock = null; private InetAddress bindAddr = null; private int bindPort = 0; - - public ServerSocket getServerSock() - { - return serverSock; - } + /** + * Store the current TCP timeout value + * The variable should be accessed by getter and setter metho + */ + protected int timeout = DEFAULT_TIMEOUT; + + public ServerSocket getServerSock() + { + return serverSock; + } public String getBindAddress() { @@ -76,106 +103,135 @@ public class HTTPServer implements Runnable return bindPort; } + + //////////////////////////////////////////////// // open/close //////////////////////////////////////////////// - - public boolean open(String addr, int port) + + /** + * Get the current socket timeout + * @since 1.8 + */ + public synchronized int getTimeout() { + return timeout; + } + + /** + * Set the current socket timeout + * @param longout new timeout + * @since 1.8 + */ + public synchronized void setTimeout(int timeout) { + this.timeout = timeout; + } + + public boolean open(InetAddress addr,int port){ + if (serverSock != null) + return true; + try { + serverSock = new ServerSocket(bindPort, 0, bindAddr); + }catch (IOException e) { + return false; + } + return true; + } + + public boolean open(String addr, int port) { if (serverSock != null) return true; - try { + try { bindAddr = InetAddress.getByName(addr); bindPort = port; serverSock = new ServerSocket(bindPort, 0, bindAddr); - serverSock.setSoTimeout(10*1000); } catch (IOException e) { Debug.warning("HTTP server open failed " + addr + " " + port, e); return false; } - return true; - } - - public boolean close() - { + return true; + } + + public boolean close() + { if (serverSock == null) return true; try { serverSock.close(); serverSock = null; bindAddr = null; - bindPort = 0; - } - catch (Exception e) { - Debug.warning(e); - return false; + bindPort = 0; } - return true; - } - - public Socket accept() - { + catch (Exception e) { + Debug.warning(e); + return false; + } + return true; + } + + public Socket accept() + { if (serverSock == null) return null; - try { + try { Socket sock = serverSock.accept(); - sock.setSoTimeout(HTTP.DEFAULT_TIMEOUT * 1000); - return sock; - } - catch (Exception e) { - return null; - } - } - - public boolean isOpened() - { - return (serverSock != null) ? true : false; - } - - //////////////////////////////////////////////// - // httpRequest - //////////////////////////////////////////////// - - private ListenerList httpRequestListenerList = new ListenerList(); - - public void addRequestListener(HTTPRequestListener listener) - { - httpRequestListenerList.add(listener); - } - - public void removeRequestListener(HTTPRequestListener listener) - { - httpRequestListenerList.remove(listener); - } - - public void performRequestListener(HTTPRequest httpReq) - { - int listenerSize = httpRequestListenerList.size(); - for (int n=0; n +* - Fixed post() to output the chunk size as a hex string. * ******************************************************************/ package org.cybergarage.http; -import java.io.*; -import java.net.*; -import java.util.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.util.Calendar; public class HTTPSocket { @@ -45,7 +51,6 @@ public class HTTPSocket setOutputStream(socket.getOutputStream()); } - @Override public void finalize() { close(); @@ -120,6 +125,7 @@ public class HTTPSocket sockOut = sock.getOutputStream(); } catch (Exception e) { + //TODO Add blacklistening of the UPnP Device return false; } return true; @@ -147,7 +153,9 @@ public class HTTPSocket private boolean post(HTTPResponse httpRes, byte content[], long contentOffset, long contentLength, boolean isOnlyHeader) { + //TODO Check for bad HTTP agents, this method may be list for IOInteruptedException and for blacklistening httpRes.setDate(Calendar.getInstance()); + OutputStream out = getOutputStream(); try { @@ -163,7 +171,8 @@ public class HTTPSocket boolean isChunkedResponse = httpRes.isChunked(); if (isChunkedResponse == true) { - String chunSizeBuf = Long.toString(contentLength); + // Thanks for Lee Peik Feng (07/07/05) + String chunSizeBuf = Long.toHexString(contentLength); out.write(chunSizeBuf.getBytes()); out.write(HTTP.CRLF.getBytes()); } @@ -188,7 +197,9 @@ public class HTTPSocket private boolean post(HTTPResponse httpRes, InputStream in, long contentOffset, long contentLength, boolean isOnlyHeader) { + //TODO Check for bad HTTP agents, this method may be list for IOInteruptedException and for blacklistening httpRes.setDate(Calendar.getInstance()); + OutputStream out = getOutputStream(); try { @@ -214,7 +225,8 @@ public class HTTPSocket int readLen = in.read(readBuf, 0, (int)readSize); while (0 < readLen && readCnt < contentLength) { if (isChunkedResponse == true) { - String chunSizeBuf = Long.toString(readLen); + // Thanks for Lee Peik Feng (07/07/05) + String chunSizeBuf = Long.toHexString(readLen); out.write(chunSizeBuf.getBytes()); out.write(HTTP.CRLF.getBytes()); } @@ -243,6 +255,7 @@ public class HTTPSocket public boolean post(HTTPResponse httpRes, long contentOffset, long contentLength, boolean isOnlyHeader) { + //TODO Close if Connection != keep-alive if (httpRes.hasContentInputStream() == true) return post(httpRes,httpRes.getContentInputStream(), contentOffset, contentLength, isOnlyHeader); return post(httpRes,httpRes.getContent(), contentOffset, contentLength, isOnlyHeader); diff --git a/router/java/src/org/cybergarage/http/HTTPStatus.java b/router/java/src/org/cybergarage/http/HTTPStatus.java index b112b2bd0..651fecb34 100644 --- a/router/java/src/org/cybergarage/http/HTTPStatus.java +++ b/router/java/src/org/cybergarage/http/HTTPStatus.java @@ -25,9 +25,9 @@ package org.cybergarage.http; -import java.util.*; - -import org.cybergarage.util.*; +import java.util.StringTokenizer; + +import org.cybergarage.util.Debug; public class HTTPStatus { diff --git a/router/java/src/org/cybergarage/http/ParameterList.java b/router/java/src/org/cybergarage/http/ParameterList.java index 9a0b2a6d1..9f395be6a 100644 --- a/router/java/src/org/cybergarage/http/ParameterList.java +++ b/router/java/src/org/cybergarage/http/ParameterList.java @@ -15,12 +15,10 @@ package org.cybergarage.http; -import java.util.*; +import java.util.Vector; public class ParameterList extends Vector { - private static final long serialVersionUID = -6026765325018137641L; - public ParameterList() { } diff --git a/router/java/src/org/cybergarage/net/HostInterface.java b/router/java/src/org/cybergarage/net/HostInterface.java index 237dfb640..b4453c93d 100644 --- a/router/java/src/org/cybergarage/net/HostInterface.java +++ b/router/java/src/org/cybergarage/net/HostInterface.java @@ -5,11 +5,11 @@ * Copyright (C) Satoshi Konno 2002-2003 * * File: HostInterface.java -* -* Revision; -* -* 05/12/03 -* - first revision. +* +* Revision; +* +* 05/12/03 +* - first revision. * 05/13/03 * - Added support for IPv6 and loopback address. * 02/15/04 @@ -22,14 +22,22 @@ * - Changed isUseAddress() to isUsableAddress(). * ******************************************************************/ + +package org.cybergarage.net; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Vector; -package org.cybergarage.net; - -import java.net.*; -import java.util.*; - -public class HostInterface -{ +import org.cybergarage.util.Debug; + +public class HostInterface +{ //////////////////////////////////////////////// // Constants //////////////////////////////////////////////// @@ -43,6 +51,9 @@ public class HostInterface //////////////////////////////////////////////// private static String ifAddress = ""; + public final static int IPV4_BITMASK = 0x0001; + public final static int IPV6_BITMASK = 0x0010; + public final static int LOCAL_BITMASK = 0x0100; public final static void setInterface(String ifaddr) { @@ -101,10 +112,62 @@ public class HostInterface } } } - catch(Exception e){} + catch(Exception e){ + Debug.warning(e); + }; return nHostAddrs; } + /** + * + * @param ipfilter + * @param interfaces + * @return + * @since 1.8.0 + * @author Stefano "Kismet" Lenzi <kismet.sl@gmail.com> + */ + public final static InetAddress[] getInetAddress(int ipfilter,String[] interfaces){ + Enumeration nis; + if(interfaces!=null){ + Vector iflist = new Vector(); + for (int i = 0; i < interfaces.length; i++) { + NetworkInterface ni; + try { + ni = NetworkInterface.getByName(interfaces[i]); + } catch (SocketException e) { + continue; + } + if(ni != null) iflist.add(ni); + + } + nis = iflist.elements(); + }else{ + try { + nis = NetworkInterface.getNetworkInterfaces(); + } catch (SocketException e) { + return null; + } + } + ArrayList addresses = new ArrayList(); + while (nis.hasMoreElements()){ + NetworkInterface ni = (NetworkInterface)nis.nextElement(); + Enumeration addrs = ni.getInetAddresses(); + while (addrs.hasMoreElements()) { + InetAddress addr = (InetAddress)addrs.nextElement(); + if(((ipfilter & LOCAL_BITMASK)==0) && addr.isLoopbackAddress()) + continue; + + if (((ipfilter & IPV4_BITMASK)!=0) && addr instanceof Inet4Address ) { + addresses.add(addr); + }else if (((ipfilter & IPV6_BITMASK)!=0)&& addr instanceof InetAddress) { + addresses.add(addr); + } + } + } + return (InetAddress[]) addresses.toArray(new InetAddress[]{}); + } + + public final static String getHostAddress(int n) { if (hasAssignedInterface() == true) @@ -131,7 +194,7 @@ public class HostInterface } } } - catch(Exception e){} + catch(Exception e){}; return ""; } @@ -143,7 +206,9 @@ public class HostInterface { try { InetAddress addr = InetAddress.getByName(host); - return (addr instanceof Inet6Address); + if (addr instanceof Inet6Address) + return true; + return false; } catch (Exception e) {} return false; @@ -153,7 +218,9 @@ public class HostInterface { try { InetAddress addr = InetAddress.getByName(host); - return (addr instanceof Inet4Address); + if (addr instanceof Inet4Address) + return true; + return false; } catch (Exception e) {} return false; diff --git a/router/java/src/org/cybergarage/soap/SOAP.java b/router/java/src/org/cybergarage/soap/SOAP.java index dec42f7ed..bc44b35a8 100644 --- a/router/java/src/org/cybergarage/soap/SOAP.java +++ b/router/java/src/org/cybergarage/soap/SOAP.java @@ -15,7 +15,8 @@ package org.cybergarage.soap; -import org.cybergarage.xml.*; +import org.cybergarage.xml.Node; +import org.cybergarage.xml.Parser; public class SOAP { diff --git a/router/java/src/org/cybergarage/soap/SOAPRequest.java b/router/java/src/org/cybergarage/soap/SOAPRequest.java index 7fa54871c..f355b0a92 100644 --- a/router/java/src/org/cybergarage/soap/SOAPRequest.java +++ b/router/java/src/org/cybergarage/soap/SOAPRequest.java @@ -5,11 +5,11 @@ * Copyright (C) Satoshi Konno 2002 * * File: SOAPRequest.java -* -* Revision; -* -* 12/11/02 -* - first revision. +* +* Revision; +* +* 12/11/02 +* - first revision. * 02/13/04 * - Ralf G. R. Bergs , Inma Marin Lopez . * - Added XML header, to setContent(). @@ -17,28 +17,32 @@ * - Changed the XML header to in setContent(). * ******************************************************************/ + +package org.cybergarage.soap; + +import java.io.ByteArrayInputStream; -package org.cybergarage.soap; - -import java.io.*; - -import org.cybergarage.http.*; -import org.cybergarage.xml.*; -import org.cybergarage.util.*; - -public class SOAPRequest extends HTTPRequest +import org.cybergarage.http.HTTP; +import org.cybergarage.http.HTTPRequest; +import org.cybergarage.http.HTTPResponse; +import org.cybergarage.util.Debug; +import org.cybergarage.xml.Node; +import org.cybergarage.xml.Parser; +import org.cybergarage.xml.ParserException; + +public class SOAPRequest extends HTTPRequest { private final static String SOAPACTION = "SOAPACTION"; - - //////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////// - - public SOAPRequest() + + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + public SOAPRequest() { - setContentType(SOAP.CONTENT_TYPE); - setMethod(HTTP.POST); - } + setContentType(SOAP.CONTENT_TYPE); + setMethod(HTTP.POST); + } public SOAPRequest(HTTPRequest httpReq) { @@ -71,33 +75,33 @@ public class SOAPRequest extends HTTPRequest return false; return soapAction.equals(value); } - - //////////////////////////////////////////////// - // post - //////////////////////////////////////////////// - - public SOAPResponse postMessage(String host, int port) - { - HTTPResponse httpRes = post(host, port); + + //////////////////////////////////////////////// + // post + //////////////////////////////////////////////// + + public SOAPResponse postMessage(String host, int port) + { + HTTPResponse httpRes = post(host, port); - SOAPResponse soapRes = new SOAPResponse(httpRes); - - byte content[] = soapRes.getContent(); - if (content.length <= 0) - return soapRes; - - try { - ByteArrayInputStream byteIn = new ByteArrayInputStream(content); - Parser xmlParser = SOAP.getXMLParser(); - Node _rootNode = xmlParser.parse(byteIn); - soapRes.setEnvelopeNode(_rootNode); - } - catch (Exception e) { - Debug.warning(e); - } - - return soapRes; - } + SOAPResponse soapRes = new SOAPResponse(httpRes); + + byte content[] = soapRes.getContent(); + if (content.length <= 0) + return soapRes; + + try { + ByteArrayInputStream byteIn = new ByteArrayInputStream(content); + Parser xmlParser = SOAP.getXMLParser(); + Node rootNode = xmlParser.parse(byteIn); + soapRes.setEnvelopeNode(rootNode); + } + catch (Exception e) { + Debug.warning(e); + } + + return soapRes; + } //////////////////////////////////////////////// // Node @@ -170,7 +174,6 @@ public class SOAPRequest extends HTTPRequest // print //////////////////////////////////////////////// - @Override public void print() { Debug.message(toString()); diff --git a/router/java/src/org/cybergarage/soap/SOAPResponse.java b/router/java/src/org/cybergarage/soap/SOAPResponse.java index 51f0abf73..4326cd2cc 100644 --- a/router/java/src/org/cybergarage/soap/SOAPResponse.java +++ b/router/java/src/org/cybergarage/soap/SOAPResponse.java @@ -20,9 +20,10 @@ package org.cybergarage.soap; -import org.cybergarage.http.*; +import org.cybergarage.http.HTTPResponse; import org.cybergarage.util.Debug; -import org.cybergarage.xml.*; +import org.cybergarage.xml.Node; +import org.cybergarage.xml.XML; public class SOAPResponse extends HTTPResponse { @@ -179,7 +180,6 @@ public class SOAPResponse extends HTTPResponse // print //////////////////////////////////////////////// - @Override public void print() { Debug.message(toString()); diff --git a/router/java/src/org/cybergarage/upnp/Action.java b/router/java/src/org/cybergarage/upnp/Action.java index 84fcb33d8..1384608de 100644 --- a/router/java/src/org/cybergarage/upnp/Action.java +++ b/router/java/src/org/cybergarage/upnp/Action.java @@ -22,16 +22,22 @@ * 07/09/04 * - Thanks for Dimas and Stefano Lenzi * - Changed postControlAction() to set the status code to the UPnPStatus. +* 04/12/06 +* - Added setUserData() and getUserData() to set a user original data object. * ******************************************************************/ package org.cybergarage.upnp; +import java.util.Iterator; -import org.cybergarage.xml.*; -import org.cybergarage.util.*; - -import org.cybergarage.upnp.xml.*; -import org.cybergarage.upnp.control.*; +import org.cybergarage.upnp.control.ActionListener; +import org.cybergarage.upnp.control.ActionRequest; +import org.cybergarage.upnp.control.ActionResponse; +import org.cybergarage.upnp.control.ControlResponse; +import org.cybergarage.upnp.xml.ActionData; +import org.cybergarage.util.Debug; +import org.cybergarage.util.Mutex; +import org.cybergarage.xml.Node; public class Action { @@ -58,6 +64,16 @@ public class Action return new Service(getServiceNode()); } + void setService(Service s){ + serviceNode=s.getServiceNode(); + /*To ensure integrity of the XML structure*/ + Iterator i = getArgumentList().iterator(); + while (i.hasNext()) { + Argument arg = (Argument) i.next(); + arg.setService(s); + } + } + public Node getActionNode() { return actionNode; @@ -66,6 +82,11 @@ public class Action //////////////////////////////////////////////// // Constructor //////////////////////////////////////////////// + public Action(Node serviceNode){ + //TODO Test + this.serviceNode = serviceNode; + this.actionNode = new Node(Action.ELEM_NAME); + } public Action(Node serviceNode, Node actionNode) { @@ -139,6 +160,23 @@ public class Action argumentList.add(argument); } return argumentList; + } + + public void setArgumentList(ArgumentList al){ + Node argumentListNode = getActionNode().getNode(ArgumentList.ELEM_NAME); + if (argumentListNode == null){ + argumentListNode = new Node(ArgumentList.ELEM_NAME); + getActionNode().addNode(argumentListNode); + }else{ + argumentListNode.removeAllNodes(); + } + Iterator i = al.iterator(); + while (i.hasNext()) { + Argument a = (Argument) i.next(); + a.setService(getService()); + argumentListNode.addNode(a.getArgumentNode()); + } + } public ArgumentList getInputArgumentList() @@ -184,10 +222,35 @@ public class Action return null; } + /** + * @deprecated You should use one of the following methods instead:
+ * - {@link #setInArgumentValues(ArgumentList)}
+ * - {@link #setOutArgumentValues(ArgumentList)} + */ public void setArgumentValues(ArgumentList argList) { getArgumentList().set(argList); } + + /** + * + * @param argList + * @since 1.8.0 + */ + public void setInArgumentValues(ArgumentList argList) + { + getArgumentList().setReqArgs(argList); + } + + /** + * + * @param argList + * @since 1.8.0 + */ + public void setOutArgumentValues(ArgumentList argList) + { + getArgumentList().setResArgs(argList); + } public void setArgumentValue(String name, String value) { @@ -272,8 +335,8 @@ public class Action actionRes.setResponse(this); } else { - UPnPStatus _upnpStatus = getStatus(); - actionRes.setFaultResponse(_upnpStatus.getCode(), _upnpStatus.getDescription()); + UPnPStatus upnpStatus = getStatus(); + actionRes.setFaultResponse(upnpStatus.getCode(), upnpStatus.getDescription()); } if (Debug.isOn() == true) actionRes.print(); @@ -323,7 +386,12 @@ public class Action if (ctrlRes.isSuccessful() == false) return false; ArgumentList outArgList = ctrlRes.getResponse(); - actionArgList.set(outArgList); + try { + actionArgList.setResArgs(outArgList); + } catch (IllegalArgumentException ex){ + setStatus(UPnPStatus.INVALID_ARGS,"Action succesfully delivered but invalid arguments returned."); + return false; + } return true; } @@ -367,4 +435,19 @@ public class Action return upnpStatus; } + //////////////////////////////////////////////// + // userData + //////////////////////////////////////////////// + + private Object userData = null; + + public void setUserData(Object data) + { + userData = data; + } + + public Object getUserData() + { + return userData; + } } diff --git a/router/java/src/org/cybergarage/upnp/ActionList.java b/router/java/src/org/cybergarage/upnp/ActionList.java index 6a5a688dc..f18130c46 100644 --- a/router/java/src/org/cybergarage/upnp/ActionList.java +++ b/router/java/src/org/cybergarage/upnp/ActionList.java @@ -15,15 +15,14 @@ package org.cybergarage.upnp; -import java.util.*; +import java.util.Vector; public class ActionList extends Vector { //////////////////////////////////////////////// // Constants //////////////////////////////////////////////// - - private static final long serialVersionUID = 1965922721316119846L; + public final static String ELEM_NAME = "actionList"; //////////////////////////////////////////////// diff --git a/router/java/src/org/cybergarage/upnp/AllowedValue.java b/router/java/src/org/cybergarage/upnp/AllowedValue.java index 24bc45769..133d8417e 100644 --- a/router/java/src/org/cybergarage/upnp/AllowedValue.java +++ b/router/java/src/org/cybergarage/upnp/AllowedValue.java @@ -5,26 +5,26 @@ * Copyright (C) Satoshi Konno 2002-2004 * * File: AllowedValue.java -* -* Revision: -* -* 03/27/04 -* - first revision. +* +* Revision: +* +* 03/27/04 +* - first revision. * ******************************************************************/ - -package org.cybergarage.upnp; -import org.cybergarage.xml.*; - -public class AllowedValue -{ - //////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////// - - public final static String ELEM_NAME = "allowedValue"; - +package org.cybergarage.upnp; + +import org.cybergarage.xml.Node; + +public class AllowedValue +{ + //////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////// + + public final static String ELEM_NAME = "allowedValue"; + //////////////////////////////////////////////// // Member //////////////////////////////////////////////// @@ -45,15 +45,30 @@ public class AllowedValue allowedValueNode = node; } - //////////////////////////////////////////////// - // isAllowedValueNode - //////////////////////////////////////////////// - - public static boolean isAllowedValueNode(Node node) - { - return ELEM_NAME.equals(node.getName()); - } - + /** + * Create an AllowedValue by the value String, + * and will create the Node structure by itself + * + * @param value The value that will be associate to thi object + * + * @author Stefano "Kismet" Lenzi - kismet-sl@users.sourceforge.net - 2005 + */ + public AllowedValue(String value) { + + //TODO Some test are done not stable + allowedValueNode = new Node(ELEM_NAME); //better (twa) + setValue(value); //better (twa) + } + + //////////////////////////////////////////////// + // isAllowedValueNode + //////////////////////////////////////////////// + + public static boolean isAllowedValueNode(Node node) + { + return ELEM_NAME.equals(node.getName()); + } + //////////////////////////////////////////////// // Value //////////////////////////////////////////////// diff --git a/router/java/src/org/cybergarage/upnp/AllowedValueList.java b/router/java/src/org/cybergarage/upnp/AllowedValueList.java index da1058996..a0b0b3131 100644 --- a/router/java/src/org/cybergarage/upnp/AllowedValueList.java +++ b/router/java/src/org/cybergarage/upnp/AllowedValueList.java @@ -5,29 +5,29 @@ * Copyright (C) Satoshi Konno 2002-2004 * * File: AllowedValueList.java -* -* Revision: -* -* 03/27/04 -* - first revision. +* +* Revision: +* +* 03/27/04 +* - first revision. * 02/28/05 * - Changed to use AllowedValue instead of String as the member. * ******************************************************************/ - -package org.cybergarage.upnp; - -import java.util.*; - -public class AllowedValueList extends Vector -{ - //////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////// - - private static final long serialVersionUID = 5740394642751180992L; - public final static String ELEM_NAME = "allowedValueList"; - + +package org.cybergarage.upnp; + +import java.util.Iterator; +import java.util.Vector; + +public class AllowedValueList extends Vector +{ + //////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////// + + public final static String ELEM_NAME = "allowedValueList"; + //////////////////////////////////////////////// // Constructor @@ -36,6 +36,14 @@ public class AllowedValueList extends Vector public AllowedValueList() { } + + public AllowedValueList(String[] values) { + for (int i = 0; i < values.length; i++) { + add(new AllowedValue(values[i])); + }; + + } + //////////////////////////////////////////////// // Methods @@ -46,4 +54,12 @@ public class AllowedValueList extends Vector return (AllowedValue)get(n); } + public boolean isAllowed(String v){ + for (Iterator i = this.iterator(); i.hasNext();) { + AllowedValue av = (AllowedValue) i.next(); + if(av.getValue().equals(v)) + return true; + } + return false; + } } diff --git a/router/java/src/org/cybergarage/upnp/AllowedValueRange.java b/router/java/src/org/cybergarage/upnp/AllowedValueRange.java index 3c4ba60c1..679c8e0c6 100644 --- a/router/java/src/org/cybergarage/upnp/AllowedValueRange.java +++ b/router/java/src/org/cybergarage/upnp/AllowedValueRange.java @@ -5,71 +5,86 @@ * Copyright (C) Satoshi Konno 2002-2004 * * File: AllowedValueRange.java -* -* Revision: -* -* 03/27/04 -* - first revision. +* +* Revision: +* +* 03/27/04 +* - first revision. * ******************************************************************/ - -package org.cybergarage.upnp; - -import org.cybergarage.xml.*; - -public class AllowedValueRange -{ - //////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////// - - public final static String ELEM_NAME = "allowedValueRange"; - - //////////////////////////////////////////////// - // Member - //////////////////////////////////////////////// - - private Node allowedValueRangeNode; - - public Node getAllowedValueRangeNode() - { - return allowedValueRangeNode; - } - - //////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////// - - public AllowedValueRange(Node node) - { - allowedValueRangeNode = node; - } - - //////////////////////////////////////////////// - // isAllowedValueRangeNode - //////////////////////////////////////////////// - - public static boolean isAllowedValueRangeNode(Node node) - { - return ELEM_NAME.equals(node.getName()); - } - - //////////////////////////////////////////////// - // minimum - //////////////////////////////////////////////// - - private final static String MINIMUM = "minimum"; - - public void setMinimum(String value) - { - getAllowedValueRangeNode().setNode(MINIMUM, value); - } - - public String getMinimum() - { - return getAllowedValueRangeNode().getNodeValue(MINIMUM); - } - + +package org.cybergarage.upnp; + +import org.cybergarage.xml.Node; + +public class AllowedValueRange +{ + //////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////// + + public final static String ELEM_NAME = "allowedValueRange"; + + //////////////////////////////////////////////// + // Member + //////////////////////////////////////////////// + + private Node allowedValueRangeNode; + + public Node getAllowedValueRangeNode() + { + return allowedValueRangeNode; + } + + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + public AllowedValueRange(Node node) + { + allowedValueRangeNode = node; + } + + public AllowedValueRange(){ + //TODO Test + allowedValueRangeNode = new Node(ELEM_NAME); + } + //////////////////////////////////////////////// + // isAllowedValueRangeNode + //////////////////////////////////////////////// + + public AllowedValueRange(Number max, Number min, Number step) { + //TODO Test + allowedValueRangeNode = new Node(ELEM_NAME); + if(max!=null) + setMaximum(max.toString()); + if(min!=null) + setMinimum(min.toString()); + if(step!=null) + setStep(step.toString()); + } + + public static boolean isAllowedValueRangeNode(Node node) + { + return ELEM_NAME.equals(node.getName()); + } + + //////////////////////////////////////////////// + // minimum + //////////////////////////////////////////////// + + private final static String MINIMUM = "minimum"; + + public void setMinimum(String value) + { + getAllowedValueRangeNode().setNode(MINIMUM, value); + } + + public String getMinimum() + { + return getAllowedValueRangeNode().getNodeValue(MINIMUM); + } + //////////////////////////////////////////////// // maximum //////////////////////////////////////////////// @@ -86,19 +101,19 @@ public class AllowedValueRange return getAllowedValueRangeNode().getNodeValue(MAXIMUM); } - //////////////////////////////////////////////// - // width - //////////////////////////////////////////////// - - private final static String STEP = "step"; - - public void setStep(String value) - { - getAllowedValueRangeNode().setNode(STEP, value); - } - - public String getStep() - { - return getAllowedValueRangeNode().getNodeValue(STEP); - } + //////////////////////////////////////////////// + // width + //////////////////////////////////////////////// + + private final static String STEP = "step"; + + public void setStep(String value) + { + getAllowedValueRangeNode().setNode(STEP, value); + } + + public String getStep() + { + return getAllowedValueRangeNode().getNodeValue(STEP); + } } diff --git a/router/java/src/org/cybergarage/upnp/Argument.java b/router/java/src/org/cybergarage/upnp/Argument.java index 6a1907551..86e2fba5e 100644 --- a/router/java/src/org/cybergarage/upnp/Argument.java +++ b/router/java/src/org/cybergarage/upnp/Argument.java @@ -5,11 +5,11 @@ * Copyright (C) Satoshi Konno 2002 * * File: Argument.java -* -* Revision; -* -* 12/05/02 -* - first revision. +* +* Revision; +* +* 12/05/02 +* - first revision. * 03/28/04 * - Added getRelatedStateVariable(). * - Changed setRelatedStateVariable() to setRelatedStateVariableName(). @@ -17,37 +17,38 @@ * - Added getActionNode() and getAction(). * - Added getServiceNode() and getService(). * - Added the parent service node to the constructor. +* 04/12/06 +* - Added setUserData() and getUserData() to set a user original data object. * ******************************************************************/ - -package org.cybergarage.upnp; - -import org.cybergarage.xml.*; -import org.cybergarage.upnp.xml.*; - -public class Argument -{ - //////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////// - - public final static String ELEM_NAME = "argument"; +package org.cybergarage.upnp; + +import org.cybergarage.upnp.xml.ArgumentData; +import org.cybergarage.xml.Node; + +public class Argument +{ + //////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////// + + public final static String ELEM_NAME = "argument"; public final static String IN = "in"; public final static String OUT = "out"; - - //////////////////////////////////////////////// - // Member - //////////////////////////////////////////////// - - private Node argumentNode; + + //////////////////////////////////////////////// + // Member + //////////////////////////////////////////////// + + private Node argumentNode; private Node serviceNode; - - public Node getArgumentNode() - { - return argumentNode; - } + + public Node getArgumentNode() + { + return argumentNode; + } private Node getServiceNode() { @@ -59,6 +60,10 @@ public class Argument return new Service(getServiceNode()); } + void setService(Service s){ + s.getServiceNode(); + } + public Node getActionNode() { Node argumentLinstNode = getArgumentNode().getParentNode(); @@ -71,27 +76,32 @@ public class Argument return null; return actionNode; } - + public Action getAction() { return new Action(getServiceNode(), getActionNode()); } - //////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////// - + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + public Argument() { - argumentNode = new Node(); + argumentNode = new Node(ELEM_NAME); serviceNode = null; } - public Argument(Node servNode, Node argNode) + public Argument(Node servNode){ + argumentNode = new Node(ELEM_NAME); + serviceNode = servNode; + } + + public Argument(Node servNode, Node argNode) { - serviceNode = servNode; - argumentNode = argNode; - } + serviceNode = servNode; + argumentNode = argNode; + } public Argument(String name, String value) { @@ -100,46 +110,46 @@ public class Argument setValue(value); } - //////////////////////////////////////////////// - // isArgumentNode - //////////////////////////////////////////////// - - public static boolean isArgumentNode(Node node) - { - return Argument.ELEM_NAME.equals(node.getName()); - } - - //////////////////////////////////////////////// - // name - //////////////////////////////////////////////// - - private final static String NAME = "name"; - - public void setName(String value) - { - getArgumentNode().setNode(NAME, value); - } - - public String getName() - { - return getArgumentNode().getNodeValue(NAME); - } - - //////////////////////////////////////////////// - // direction - //////////////////////////////////////////////// - - private final static String DIRECTION = "direction"; - - public void setDirection(String value) - { - getArgumentNode().setNode(DIRECTION, value); - } - - public String getDirection() - { - return getArgumentNode().getNodeValue(DIRECTION); - } + //////////////////////////////////////////////// + // isArgumentNode + //////////////////////////////////////////////// + + public static boolean isArgumentNode(Node node) + { + return Argument.ELEM_NAME.equals(node.getName()); + } + + //////////////////////////////////////////////// + // name + //////////////////////////////////////////////// + + private final static String NAME = "name"; + + public void setName(String value) + { + getArgumentNode().setNode(NAME, value); + } + + public String getName() + { + return getArgumentNode().getNodeValue(NAME); + } + + //////////////////////////////////////////////// + // direction + //////////////////////////////////////////////// + + private final static String DIRECTION = "direction"; + + public void setDirection(String value) + { + getArgumentNode().setNode(DIRECTION, value); + } + + public String getDirection() + { + return getArgumentNode().getNodeValue(DIRECTION); + } public boolean isInDirection() { @@ -153,22 +163,22 @@ public class Argument { return !isInDirection(); } - - //////////////////////////////////////////////// - // relatedStateVariable - //////////////////////////////////////////////// - - private final static String RELATED_STATE_VARIABLE = "relatedStateVariable"; - - public void setRelatedStateVariableName(String value) - { - getArgumentNode().setNode(RELATED_STATE_VARIABLE, value); - } - - public String getRelatedStateVariableName() - { - return getArgumentNode().getNodeValue(RELATED_STATE_VARIABLE); - } + + //////////////////////////////////////////////// + // relatedStateVariable + //////////////////////////////////////////////// + + private final static String RELATED_STATE_VARIABLE = "relatedStateVariable"; + + public void setRelatedStateVariableName(String value) + { + getArgumentNode().setNode(RELATED_STATE_VARIABLE, value); + } + + public String getRelatedStateVariableName() + { + return getArgumentNode().getNodeValue(RELATED_STATE_VARIABLE); + } public StateVariable getRelatedStateVariable() { @@ -226,6 +236,18 @@ public class Argument } //////////////////////////////////////////////// - // Related + // userData //////////////////////////////////////////////// + + private Object userData = null; + + public void setUserData(Object data) + { + userData = data; + } + + public Object getUserData() + { + return userData; + } } diff --git a/router/java/src/org/cybergarage/upnp/ArgumentList.java b/router/java/src/org/cybergarage/upnp/ArgumentList.java index 95620d281..3f1a5ec44 100644 --- a/router/java/src/org/cybergarage/upnp/ArgumentList.java +++ b/router/java/src/org/cybergarage/upnp/ArgumentList.java @@ -1,77 +1,121 @@ -/****************************************************************** -* -* CyberUPnP for Java -* -* Copyright (C) Satoshi Konno 2002 +/****************************************************************** * -* File: ArgumentList.java -* -* Revision: -* -* 12/05/02 -* - first revision. -* -******************************************************************/ +* CyberUPnP for Java +* +* Copyright (C) Satoshi Konno 2002 +* +* File: ArgumentList.java +* +* Revision: +* +* 12/05/02 +* - first revision. +* +******************************************************************/ + +package org.cybergarage.upnp; + +import java.util.Vector; + +public class ArgumentList extends Vector +{ + //////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////// + + public final static String ELEM_NAME = "argumentList"; + + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + public ArgumentList() + { + } + + //////////////////////////////////////////////// + // Methods + //////////////////////////////////////////////// + + public Argument getArgument(int n) + { + return (Argument)get(n); + } + + public Argument getArgument(String name) + { + int nArgs = size(); + for (int n=0; n * - Added a new setActionListener() and serQueryListner() to include the sub devices. +* 07/24/05 +* - Thanks for Stefano Lenzi +* - Fixed a bug of getParentDevice() to return the parent device normally. +* 02/21/06 +* - Changed httpRequestRecieved() not to ignore HEAD requests. +* 04/12/06 +* - Added setUserData() and getUserData() to set a user original data object. +* 03/29/08 +* - Added isRunning() to know whether the device is running. * ******************************************************************/ package org.cybergarage.upnp; -import java.net.*; -import java.io.*; -import java.util.*; +import java.io.File; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.URL; +import java.util.Calendar; -import org.cybergarage.net.*; -import org.cybergarage.http.*; -import org.cybergarage.util.*; -import org.cybergarage.xml.*; -import org.cybergarage.soap.*; - -import org.cybergarage.upnp.ssdp.*; -import org.cybergarage.upnp.device.*; -import org.cybergarage.upnp.control.*; -import org.cybergarage.upnp.event.*; -import org.cybergarage.upnp.xml.*; +import org.cybergarage.http.HTTP; +import org.cybergarage.http.HTTPRequest; +import org.cybergarage.http.HTTPResponse; +import org.cybergarage.http.HTTPServerList; +import org.cybergarage.http.HTTPStatus; +import org.cybergarage.net.HostInterface; +import org.cybergarage.soap.SOAPResponse; +import org.cybergarage.upnp.control.ActionListener; +import org.cybergarage.upnp.control.ActionRequest; +import org.cybergarage.upnp.control.ActionResponse; +import org.cybergarage.upnp.control.ControlRequest; +import org.cybergarage.upnp.control.ControlResponse; +import org.cybergarage.upnp.control.QueryListener; +import org.cybergarage.upnp.control.QueryRequest; +import org.cybergarage.upnp.device.Advertiser; +import org.cybergarage.upnp.device.Description; +import org.cybergarage.upnp.device.InvalidDescriptionException; +import org.cybergarage.upnp.device.NTS; +import org.cybergarage.upnp.device.ST; +import org.cybergarage.upnp.device.SearchListener; +import org.cybergarage.upnp.device.USN; +import org.cybergarage.upnp.event.Subscriber; +import org.cybergarage.upnp.event.Subscription; +import org.cybergarage.upnp.event.SubscriptionRequest; +import org.cybergarage.upnp.event.SubscriptionResponse; +import org.cybergarage.upnp.ssdp.SSDPNotifyRequest; +import org.cybergarage.upnp.ssdp.SSDPNotifySocket; +import org.cybergarage.upnp.ssdp.SSDPPacket; +import org.cybergarage.upnp.ssdp.SSDPSearchResponse; +import org.cybergarage.upnp.ssdp.SSDPSearchResponseSocket; +import org.cybergarage.upnp.ssdp.SSDPSearchSocketList; +import org.cybergarage.upnp.xml.DeviceData; +import org.cybergarage.util.Debug; +import org.cybergarage.util.FileUtil; +import org.cybergarage.util.Mutex; +import org.cybergarage.util.TimerUtil; +import org.cybergarage.xml.Node; +import org.cybergarage.xml.Parser; +import org.cybergarage.xml.ParserException; +import org.cybergarage.xml.XML; public class Device implements org.cybergarage.http.HTTPRequestListener, SearchListener { @@ -188,6 +228,16 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL loadDescription(descriptionFile); } + /** + * @since 1.8.0 + */ + public Device(InputStream input) throws InvalidDescriptionException + { + this(null, null); + loadDescription(input); + } + + public Device(String descriptionFileName) throws InvalidDescriptionException { this(new File(descriptionFileName)); @@ -209,6 +259,47 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL mutex.unlock(); } + //////////////////////////////////////////////// + // getAbsoluteURL + //////////////////////////////////////////////// + + public String getAbsoluteURL(String urlString) + { + try { + URL url = new URL(urlString); + return url.toString(); + } + catch (Exception e) {} + + Device rootDev = getRootDevice(); + String urlBaseStr = rootDev.getURLBase(); + + // Thanks for Steven Yen (2003/09/03) + if (urlBaseStr == null || urlBaseStr.length() <= 0) { + String location = rootDev.getLocation(); + String locationHost = HTTP.getHost(location); + int locationPort = HTTP.getPort(location); + urlBaseStr = HTTP.getRequestHostURL(locationHost, locationPort); + } + + urlString = HTTP.toRelativeURL(urlString); + String absUrl = urlBaseStr + urlString; + try { + URL url = new URL(absUrl); + return url.toString(); + } + catch (Exception e) {} + + absUrl = HTTP.getAbsoluteURL(urlBaseStr, urlString); + try { + URL url = new URL(absUrl); + return url.toString(); + } + catch (Exception e) {} + + return ""; + } + //////////////////////////////////////////////// // NMPR //////////////////////////////////////////////// @@ -285,13 +376,13 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL public Device getRootDevice() { - Node _rootNode = getRootNode(); - if (_rootNode == null) + Node rootNode = getRootNode(); + if (rootNode == null) return null; - Node devNode = _rootNode.getNode(Device.ELEM_NAME); + Node devNode = rootNode.getNode(Device.ELEM_NAME); if (devNode == null) return null; - return new Device(_rootNode, devNode); + return new Device(rootNode, devNode); } //////////////////////////////////////////////// @@ -300,15 +391,71 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL // Thanks for Stefano Lenzi (07/24/04) - public Device getParentDevice() - { + /** + * + * @return A Device that contain this object.
+ * Return null if this is a root device. + * @author Stefano "Kismet" Lenzi + */ + public Device getParentDevice() { if(isRootDevice()) return null; Node devNode = getDeviceNode(); + Node aux = null; // - devNode = devNode.getParentNode().getParentNode().getNode(Device.ELEM_NAME); - return new Device(devNode); + aux = devNode.getParentNode().getParentNode(); + return new Device(aux); } + /** + * Add a Service to device without checking for duplicate or syntax error + * + * @param s Add Service s to the Device + */ + public void addService(Service s) { + Node serviceListNode = getDeviceNode().getNode(ServiceList.ELEM_NAME); + if (serviceListNode == null) { + serviceListNode = new Node(ServiceList.ELEM_NAME); + getDeviceNode().addNode(serviceListNode); + } + serviceListNode.addNode(s.getServiceNode()); + } + + /** + * Add a Device to device without checking for duplicate or syntax error. + * This method set or reset the root node of the Device and itself
+ *
+ * Note: This method should be used to create a dynamic
+ * Device withtout writing any XML that describe the device
. + * + * @param d Add Device d to the Device + * + * @author Stefano "Kismet" Lenzi - kismet-sl@users.sourceforge.net - 2005 + * + */ + public void addDevice(Device d) { + Node deviceListNode = getDeviceNode().getNode(DeviceList.ELEM_NAME); + if (deviceListNode == null) { + //deviceListNode = new Node(ServiceList.ELEM_NAME); twa wrong ELEM_NAME; + deviceListNode = new Node(DeviceList.ELEM_NAME); + getDeviceNode().addNode(deviceListNode); + } + deviceListNode.addNode(d.getDeviceNode()); + d.setRootNode(null); + if(getRootNode()==null){ + Node root = new Node(RootDescription.ROOT_ELEMENT); + root.setNameSpace("",RootDescription.ROOT_ELEMENT_NAMESPACE); + Node spec = new Node(RootDescription.SPECVERSION_ELEMENT); + Node maj =new Node(RootDescription.MAJOR_ELEMENT); + maj.setValue("1"); + Node min =new Node(RootDescription.MINOR_ELEMENT); + min.setValue("0"); + spec.addNode(maj); + spec.addNode(min); + root.addNode(spec); + setRootNode(root); + } + } + //////////////////////////////////////////////// // UserData @@ -365,6 +512,32 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL return ""; return descriptionFile.getAbsoluteFile().getParent(); } + + /** + * @since 1.8.0 + */ + public boolean loadDescription(InputStream input) throws InvalidDescriptionException + { + try { + Parser parser = UPnP.getXMLParser(); + rootNode = parser.parse(input); + if (rootNode == null) + throw new InvalidDescriptionException(Description.NOROOT_EXCEPTION); + deviceNode = rootNode.getNode(Device.ELEM_NAME); + if (deviceNode == null) + throw new InvalidDescriptionException(Description.NOROOTDEVICE_EXCEPTION); + } + catch (ParserException e) { + throw new InvalidDescriptionException(e); + } + + if (initializeLoadedDescription() == false) + return false; + + setDescriptionFile(null); + + return true; + } public boolean loadDescription(String descString) throws InvalidDescriptionException { @@ -438,9 +611,8 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL // Root Device //////////////////////////////////////////////// - public boolean isRootDevice() - { - return (getRootNode() != null) ? true : false; + public boolean isRootDevice(){ + return getRootNode().getNode("device").getNodeValue(UDN).equals(getUDN()); } //////////////////////////////////////////////// @@ -603,7 +775,7 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL // manufacture //////////////////////////////////////////////// - private final static String MANUFACTURE = "manufacture"; + private final static String MANUFACTURE = "manufacturer"; public void setManufacture(String value) { @@ -619,7 +791,7 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL // manufactureURL //////////////////////////////////////////////// - private final static String MANUFACTURE_URL = "manufactureURL"; + private final static String MANUFACTURE_URL = "manufacturerURL"; public void setManufactureURL(String value) { @@ -1066,6 +1238,24 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL return iconList.getIcon(n); } + public Icon getSmallestIcon() + { + Icon smallestIcon = null; + IconList iconList = getIconList(); + int iconCount = iconList.size(); + for (int n=0; n < iconCount; n++) { + Icon icon = iconList.getIcon(n); + if (null == smallestIcon) { + smallestIcon = icon; + continue; + } + if (icon.getWidth() < smallestIcon.getWidth()) + smallestIcon = icon; + } + + return smallestIcon; + } + //////////////////////////////////////////////// // Notify //////////////////////////////////////////////// @@ -1103,7 +1293,6 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL { TimerUtil.waitRandom(DEFAULT_DISCOVERY_WAIT_TIME); } - public void announce(String bindAddr) { String devLocation = getLocationURL(bindAddr); @@ -1123,6 +1312,11 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL ssdpReq.setNT(devNT); ssdpReq.setUSN(devUSN); ssdpSock.post(ssdpReq); + + String devUDN = getUDN(); + ssdpReq.setNT(devUDN); + ssdpReq.setUSN(devUDN); + ssdpSock.post(ssdpReq); } // uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:v @@ -1150,18 +1344,29 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL } } - public void announce() - { + public void announce(){ notifyWait(); - - int nHostAddrs = HostInterface.getNHostAddresses(); - for (int n=0; nnull to get the default beahvior + */ + public void setSSDPBindAddress(InetAddress[] inets){ + this.getDeviceData().setSSDPBindAddress(inets); + } + + + /** + * + * @return inets The IP that will be used for binding the SSDP service. + * null means the default setted by the class UPnP + */ + public InetAddress[] getSSDPBindAddress(){ + return this.getDeviceData().getSSDPBindAddress(); + } + + /** + * + * @param ip The IPv4 address used for Multicast comunication + */ + public void setMulticastIPv4Address(String ip){ + this.getDeviceData().setMulticastIPv4Address(ip); + } + + /** + * + * @return The IPv4 address used for Multicast comunication + */ + public String getMulticastIPv4Address(){ + return this.getDeviceData().getMulticastIPv4Address(); + } + + /** + * + * @param ip The IPv address used for Multicast comunication + */ + public void setMulticastIPv6Address(String ip){ + this.getDeviceData().setMulticastIPv6Address(ip); + } + + /** + * + * @return The IPv address used for Multicast comunication + */ + public String getMulticastIPv6Address(){ + return this.getDeviceData().getMulticastIPv6Address(); + } + private SSDPSearchSocketList getSSDPSearchSocketList() { @@ -1708,6 +2054,11 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL return stop(true); } + public boolean isRunning() + { + return (getAdvertiser() != null) ? true : false; + } + //////////////////////////////////////////////// // Interface Address //////////////////////////////////////////////// @@ -1775,6 +2126,22 @@ public class Device implements org.cybergarage.http.HTTPRequestListener, SearchL } } } + + //////////////////////////////////////////////// + // userData + //////////////////////////////////////////////// + + private Object userData = null; + + public void setUserData(Object data) + { + userData = data; + } + + public Object getUserData() + { + return userData; + } //////////////////////////////////////////////// // output diff --git a/router/java/src/org/cybergarage/upnp/DeviceList.java b/router/java/src/org/cybergarage/upnp/DeviceList.java index 729b2245f..afa23ffc9 100644 --- a/router/java/src/org/cybergarage/upnp/DeviceList.java +++ b/router/java/src/org/cybergarage/upnp/DeviceList.java @@ -1,46 +1,45 @@ -/****************************************************************** -* -* CyberUPnP for Java -* -* Copyright (C) Satoshi Konno 2002 +/****************************************************************** * -* File: DeviceList.java -* -* Revision; -* -* 12/04/02 -* - first revision. -* -******************************************************************/ +* CyberUPnP for Java +* +* Copyright (C) Satoshi Konno 2002 +* +* File: DeviceList.java +* +* Revision; +* +* 12/04/02 +* - first revision. +* +******************************************************************/ + +package org.cybergarage.upnp; + +import java.util.Vector; + +public class DeviceList extends Vector +{ + //////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////// + + public final static String ELEM_NAME = "deviceList"; + + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + public DeviceList() + { + } + + //////////////////////////////////////////////// + // Methods + //////////////////////////////////////////////// + + public Device getDevice(int n) + { + return (Device)get(n); + } +} -package org.cybergarage.upnp; - -import java.util.*; - -public class DeviceList extends Vector -{ - //////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////// - - private static final long serialVersionUID = 3773784061607435126L; - public final static String ELEM_NAME = "deviceList"; - - //////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////// - - public DeviceList() - { - } - - //////////////////////////////////////////////// - // Methods - //////////////////////////////////////////////// - - public Device getDevice(int n) - { - return (Device)get(n); - } -} - diff --git a/router/java/src/org/cybergarage/upnp/Icon.java b/router/java/src/org/cybergarage/upnp/Icon.java index 7566b3117..0f76c44a3 100644 --- a/router/java/src/org/cybergarage/upnp/Icon.java +++ b/router/java/src/org/cybergarage/upnp/Icon.java @@ -10,12 +10,14 @@ * * 11/28/02 * - first revision. +* 04/12/06 +* - Added setUserData() and getUserData() to set a user original data object. * ******************************************************************/ package org.cybergarage.upnp; -import org.cybergarage.xml.*; +import org.cybergarage.xml.Node; public class Icon { @@ -81,9 +83,21 @@ public class Icon getIconNode().setNode(WIDTH, value); } - public String getWidth() - { - return getIconNode().getNodeValue(WIDTH); + public void setWidth(int value) + { + try { + setWidth(Integer.toString(value)); + } + catch (Exception e) {}; + } + + public int getWidth() + { + try { + return Integer.parseInt(getIconNode().getNodeValue(WIDTH)); + } + catch (Exception e) {}; + return 0; } //////////////////////////////////////////////// @@ -97,9 +111,21 @@ public class Icon getIconNode().setNode(HEIGHT, value); } - public String getHeight() + public void setHeight(int value) + { + try { + setHeight(Integer.toString(value)); + } + catch (Exception e) {}; + } + + public int getHeight() { - return getIconNode().getNodeValue(HEIGHT); + try { + return Integer.parseInt(getIconNode().getNodeValue(HEIGHT)); + } + catch (Exception e) {}; + return 0; } //////////////////////////////////////////////// @@ -132,5 +158,21 @@ public class Icon public String getURL() { return getIconNode().getNodeValue(URL); - } + } + + //////////////////////////////////////////////// + // userData + //////////////////////////////////////////////// + + private Object userData = null; + + public void setUserData(Object data) + { + userData = data; + } + + public Object getUserData() + { + return userData; + } } diff --git a/router/java/src/org/cybergarage/upnp/IconList.java b/router/java/src/org/cybergarage/upnp/IconList.java index 2e60de0fc..a78f810cc 100644 --- a/router/java/src/org/cybergarage/upnp/IconList.java +++ b/router/java/src/org/cybergarage/upnp/IconList.java @@ -15,7 +15,7 @@ package org.cybergarage.upnp; -import java.util.*; +import java.util.Vector; public class IconList extends Vector { @@ -23,7 +23,6 @@ public class IconList extends Vector // Constants //////////////////////////////////////////////// - private static final long serialVersionUID = -1097238335037012991L; public final static String ELEM_NAME = "iconList"; //////////////////////////////////////////////// diff --git a/router/java/src/org/cybergarage/upnp/RootDescription.java b/router/java/src/org/cybergarage/upnp/RootDescription.java new file mode 100644 index 000000000..19b5ad926 --- /dev/null +++ b/router/java/src/org/cybergarage/upnp/RootDescription.java @@ -0,0 +1,19 @@ +package org.cybergarage.upnp; + + +/** + * @author Stefano "Kismet" Lenzi - kismet-sl@users.sourceforge.net
+ * Copyright (c) 2005 + * + */ +public interface RootDescription { + + public final String ROOT_ELEMENT = "root"; + public final String ROOT_ELEMENT_NAMESPACE = "urn:schemas-upnp-org:device-1-0"; + + + public final String SPECVERSION_ELEMENT = "specVersion"; + public final String MAJOR_ELEMENT = "major"; + public final String MINOR_ELEMENT = "minor"; + public final String SERVICE_LIST_ELEMENT = "serviceList"; +} diff --git a/router/java/src/org/cybergarage/upnp/Service.java b/router/java/src/org/cybergarage/upnp/Service.java index e588feba6..3f517b0bf 100644 --- a/router/java/src/org/cybergarage/upnp/Service.java +++ b/router/java/src/org/cybergarage/upnp/Service.java @@ -60,23 +60,42 @@ * 04/25/05 * - Thanks for Mikael Hakman * - Changed getSCPDData() to add a XML declaration at first line. +* 06/21/05 +* - Changed notify() to continue when the subscriber is null. +* 04/12/06 +* - Added setUserData() and getUserData() to set a user original data object. +* 09/18/2010 Robin V. +* - Fixed getSCPDNode() not to occur recursive http get requests. * ******************************************************************/ package org.cybergarage.upnp; -import java.io.*; -import java.net.*; +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.util.Iterator; -import org.cybergarage.http.*; -import org.cybergarage.xml.*; -import org.cybergarage.util.*; - -import org.cybergarage.upnp.ssdp.*; -import org.cybergarage.upnp.xml.*; -import org.cybergarage.upnp.device.*; -import org.cybergarage.upnp.control.*; -import org.cybergarage.upnp.event.*; +import org.cybergarage.http.HTTP; +import org.cybergarage.http.HTTPResponse; +import org.cybergarage.upnp.control.ActionListener; +import org.cybergarage.upnp.control.QueryListener; +import org.cybergarage.upnp.device.InvalidDescriptionException; +import org.cybergarage.upnp.device.NTS; +import org.cybergarage.upnp.device.ST; +import org.cybergarage.upnp.event.NotifyRequest; +import org.cybergarage.upnp.event.Subscriber; +import org.cybergarage.upnp.event.SubscriberList; +import org.cybergarage.upnp.ssdp.SSDPNotifyRequest; +import org.cybergarage.upnp.ssdp.SSDPNotifySocket; +import org.cybergarage.upnp.ssdp.SSDPPacket; +import org.cybergarage.upnp.xml.ServiceData; +import org.cybergarage.util.Debug; +import org.cybergarage.util.Mutex; +import org.cybergarage.util.StringUtil; +import org.cybergarage.xml.Node; +import org.cybergarage.xml.Parser; +import org.cybergarage.xml.ParserException; public class Service { @@ -100,6 +119,34 @@ public class Service //////////////////////////////////////////////// // Constructor //////////////////////////////////////////////// + public static final String SCPD_ROOTNODE="scpd"; + public static final String SCPD_ROOTNODE_NS="urn:schemas-upnp-org:service-1-0"; + + public static final String SPEC_VERSION="specVersion"; + public static final String MAJOR="major"; + public static final String MAJOR_VALUE="1"; + public static final String MINOR="minor"; + public static final String MINOR_VALUE="0"; + + public Service(){ + this(new Node(ELEM_NAME)); + + Node sp = new Node(SPEC_VERSION); + + Node M =new Node(MAJOR); + M.setValue(MAJOR_VALUE); + sp.addNode(M); + + Node m =new Node(MINOR); + m.setValue(MINOR_VALUE); + sp.addNode(m); + + //Node scpd = new Node(SCPD_ROOTNODE,SCPD_ROOTNODE_NS); wrong! + Node scpd = new Node(SCPD_ROOTNODE); // better (twa) + scpd.addAttribute("xmlns",SCPD_ROOTNODE_NS); // better (twa) + scpd.addNode(sp); + getServiceData().setSCPDNode(scpd); + } public Service(Node node) { @@ -306,6 +353,32 @@ public class Service data.setSCPDNode(scpdNode); return true; } + + /** + * @since 1.8.0 + */ + public boolean loadSCPD(InputStream input) throws ParserException + { + Parser parser = UPnP.getXMLParser(); + Node scpdNode = parser.parse(input); + if (scpdNode == null) + return false; + ServiceData data = getServiceData(); + data.setSCPDNode(scpdNode); + return true; + } + + + public void setDescriptionURL(String value) + { + getServiceData().setDescriptionURL(value); + } + + public String getDescriptionURL() + { + return getServiceData().getDescriptionURL(); + } + private Node getSCPDNode(URL scpdUrl) throws ParserException { @@ -326,48 +399,53 @@ public class Service if (scpdNode != null) return scpdNode; + // Thanks for Jaap (Sep 18, 2010) + Device rootDev = getRootDevice(); + if (rootDev == null) + return null; + String scpdURLStr = getSCPDURL(); - try { - URL scpdUrl = new URL(scpdURLStr); - scpdNode = getSCPDNode(scpdUrl); - } - catch (Exception e1) { - Device rootDev = getRootDevice(); - String urlBaseStr = rootDev.getURLBase(); - // Thanks for Steven Yen (2003/09/03) - if (urlBaseStr == null || urlBaseStr.length() <= 0) { - String location = rootDev.getLocation(); - String locationHost = HTTP.getHost(location); - int locationPort = HTTP.getPort(location); - urlBaseStr = HTTP.getRequestHostURL(locationHost, locationPort); - } - scpdURLStr = HTTP.toRelativeURL(scpdURLStr); - String newScpdURLStr = urlBaseStr + scpdURLStr; - try { - URL newScpdURL = new URL(newScpdURLStr); - scpdNode = getSCPDNode(newScpdURL); - } - catch (Exception e2) { - newScpdURLStr = HTTP.getAbsoluteURL(urlBaseStr, scpdURLStr); + + // Thanks for Robin V. (Sep 18, 2010) + String rootDevPath = rootDev.getDescriptionFilePath(); + if(rootDevPath!=null) { + File f; + f = new File(rootDevPath.concat(scpdURLStr)); + + if(f.exists()) { try { - URL newScpdURL = new URL(newScpdURLStr); - scpdNode = getSCPDNode(newScpdURL); + scpdNode = getSCPDNode(f); + } catch (ParserException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } - catch (Exception e3) { - newScpdURLStr = rootDev.getDescriptionFilePath() + scpdURLStr; - try { - scpdNode = getSCPDNode(new File(newScpdURLStr)); - } - catch (Exception e4) { - Debug.warning(e4); - } + if(scpdNode!=null) { + data.setSCPDNode(scpdNode); + return scpdNode; } } } - data.setSCPDNode(scpdNode); + try { + URL scpdUrl = new URL(rootDev.getAbsoluteURL(scpdURLStr)); + scpdNode = getSCPDNode(scpdUrl); + if (scpdNode != null) { + data.setSCPDNode(scpdNode); + return scpdNode; + } + } + catch (Exception e) {} - return scpdNode; + String newScpdURLStr = rootDev.getDescriptionFilePath() + HTTP.toRelativeURL(scpdURLStr); + try { + scpdNode = getSCPDNode(new File(newScpdURLStr)); + return scpdNode; + } + catch (Exception e) { + Debug.warning(e); + } + + return null; } public byte[] getSCPDData() @@ -396,13 +474,12 @@ public class Service Node actionListNode = scdpNode.getNode(ActionList.ELEM_NAME); if (actionListNode == null) return actionList; - Node _serviceNode = getServiceNode(); int nNode = actionListNode.getNNodes(); for (int n=0; n + *
+ * Note: This method should be used to create a dynamic
+ * Device withtout writing any XML that describe the device
. + *
+ * Note: that no control for duplicate StateVariable is done. + * + * @param var StateVariable that will be added + * + * @author Stefano "Kismet" Lenzi - kismet-sl@users.sourceforge.net - 2005 + */ + public void addStateVariable(StateVariable var) { + //TODO Some test are done not stable + Node stateTableNode = getSCPDNode().getNode(ServiceStateTable.ELEM_NAME); + if (stateTableNode == null){ + stateTableNode = new Node(ServiceStateTable.ELEM_NAME); + /* + * Force the node to be the first node inside + */ + //getSCPDNode().insertNode(stateTableNode,0); + getSCPDNode().addNode(stateTableNode); + } + var.setServiceNode(getServiceNode()); + stateTableNode.addNode(var.getStateVariableNode()); + } + + //////////////////////////////////////////////// + // userData + //////////////////////////////////////////////// + + private Object userData = null; + + public void setUserData(Object data) + { + userData = data; + } + + public Object getUserData() + { + return userData; + } } diff --git a/router/java/src/org/cybergarage/upnp/ServiceList.java b/router/java/src/org/cybergarage/upnp/ServiceList.java index cb7da3548..55dee276f 100644 --- a/router/java/src/org/cybergarage/upnp/ServiceList.java +++ b/router/java/src/org/cybergarage/upnp/ServiceList.java @@ -3,7 +3,7 @@ * CyberUPnP for Java * * Copyright (C) Satoshi Konno 2002 -* +* * File: ServiceList.java * * Revision; @@ -14,10 +14,10 @@ * - Added caching a ArrayIndexOfBound exception. * ******************************************************************/ - + package org.cybergarage.upnp; -import java.util.*; +import java.util.Vector; public class ServiceList extends Vector { @@ -25,7 +25,6 @@ public class ServiceList extends Vector // Constants //////////////////////////////////////////////// - private static final long serialVersionUID = 6372904993975135597L; public final static String ELEM_NAME = "serviceList"; //////////////////////////////////////////////// @@ -46,7 +45,7 @@ public class ServiceList extends Vector try { obj = get(n); } - catch (Exception e) {} + catch (Exception e) {}; return (Service)obj; } } diff --git a/router/java/src/org/cybergarage/upnp/ServiceStateTable.java b/router/java/src/org/cybergarage/upnp/ServiceStateTable.java index 0f1b7eed3..daddfbf86 100644 --- a/router/java/src/org/cybergarage/upnp/ServiceStateTable.java +++ b/router/java/src/org/cybergarage/upnp/ServiceStateTable.java @@ -15,7 +15,7 @@ package org.cybergarage.upnp; -import java.util.*; +import java.util.Vector; public class ServiceStateTable extends Vector { @@ -23,7 +23,6 @@ public class ServiceStateTable extends Vector // Constants //////////////////////////////////////////////// - private static final long serialVersionUID = 7626909231678469365L; public final static String ELEM_NAME = "serviceStateTable"; //////////////////////////////////////////////// diff --git a/router/java/src/org/cybergarage/upnp/StateVariable.java b/router/java/src/org/cybergarage/upnp/StateVariable.java index c75625e28..9016652d6 100644 --- a/router/java/src/org/cybergarage/upnp/StateVariable.java +++ b/router/java/src/org/cybergarage/upnp/StateVariable.java @@ -39,16 +39,21 @@ * - Fixed setValue() to compare only when the current value is not null. * 02/28/05 * - Changed getAllowedValueList() to use AllowedValue instead of String as the member. +* 04/12/06 +* - Added setUserData() and getUserData() to set a user original data object. * ******************************************************************/ package org.cybergarage.upnp; +import java.util.Iterator; -import org.cybergarage.xml.*; -import org.cybergarage.util.*; - -import org.cybergarage.upnp.control.*; -import org.cybergarage.upnp.xml.*; +import org.cybergarage.upnp.control.QueryListener; +import org.cybergarage.upnp.control.QueryRequest; +import org.cybergarage.upnp.control.QueryResponse; +import org.cybergarage.upnp.xml.NodeData; +import org.cybergarage.upnp.xml.StateVariableData; +import org.cybergarage.util.Debug; +import org.cybergarage.xml.Node; public class StateVariable extends NodeData { @@ -69,13 +74,17 @@ public class StateVariable extends NodeData { return serviceNode; } + + void setServiceNode(Node n){ + serviceNode=n; + } public Service getService() { - Node _serviceNode = getServiceNode(); - if (_serviceNode == null) + Node serviceNode = getServiceNode(); + if (serviceNode == null) return null; - return new Service(_serviceNode); + return new Service(serviceNode); } public Node getStateVariableNode() @@ -90,7 +99,7 @@ public class StateVariable extends NodeData public StateVariable() { this.serviceNode = null; - this.stateVariableNode = new Node(); + this.stateVariableNode = new Node(ELEM_NAME); } public StateVariable(Node serviceNode, Node stateVarNode) @@ -238,7 +247,7 @@ public class StateVariable extends NodeData AllowedValueList valueList= new AllowedValueList(); Node valueListNode = getStateVariableNode().getNode(AllowedValueList.ELEM_NAME); if (valueListNode == null) - return valueList; + return null; int nNode = valueListNode.getNNodes(); for (int n=0; n + * of this object.
+ *
+ * Note: This method should be used to create a dynamic
+ * Device withtout writing any XML that describe the device
. + *
+ * Note2: The enforce the constraint of the SCPD rule the
+ * AllowedValueList and AllowedValueRange are mutal exclusive
+ * the last set will be the only present
+ * + * @param avl The new AllowedValueList + * + * @author Stefano "Kismet" Lenzi - kismet-sl@users.sourceforge.net - 2005 + */ + public void setAllowedValueList(AllowedValueList avl) { + //TODO Some test done not stable + getStateVariableNode().removeNode(AllowedValueList.ELEM_NAME); + getStateVariableNode().removeNode(AllowedValueRange.ELEM_NAME); + Node n = new Node(AllowedValueList.ELEM_NAME); + Iterator i=avl.iterator(); + while (i.hasNext()) { + AllowedValue av = (AllowedValue) i.next(); + //n.addNode(new Node(AllowedValue.ELEM_NAME,av.getValue())); wrong! + n.addNode(av.getAllowedValueNode()); //better (twa) + } + getStateVariableNode().addNode(n); + + } + + public boolean hasAllowedValueList() { AllowedValueList valueList = getAllowedValueList(); - return (0 < valueList.size()) ? true : false; + return (valueList != null) ? true : false; } //////////////////////////////////////////////// @@ -267,6 +307,29 @@ public class StateVariable extends NodeData return null; return new AllowedValueRange(valueRangeNode); } + + /** + * This method ovverride the value of the AllowedValueRange Node
+ * of this object.
+ *
+ * Note: This method should be used to create a dynamic
+ * Device withtout writing any XML that describe the device
. + *
+ * Note2: The enforce the constraint of the SCPD rule the
+ * AllowedValueList and AllowedValueRange are mutal exclusive
+ * the last set will be the only present
+ * + * @param avr The new AllowedValueRange + * + * @author Stefano "Kismet" Lenzi - kismet-sl@users.sourceforge.net - 2005 + */ + public void setAllowedValueRange(AllowedValueRange avr){ + //TODO Some test done not stable + getStateVariableNode().removeNode(AllowedValueList.ELEM_NAME); + getStateVariableNode().removeNode(AllowedValueRange.ELEM_NAME); + getStateVariableNode().addNode(avr.getAllowedValueRangeNode()); + + } public boolean hasAllowedValueRange() { @@ -301,8 +364,8 @@ public class StateVariable extends NodeData queryRes.setResponse(retVar); } else { - UPnPStatus _upnpStatus = retVar.getStatus(); - queryRes.setFaultResponse(_upnpStatus.getCode(), _upnpStatus.getDescription()); + UPnPStatus upnpStatus = retVar.getStatus(); + queryRes.setFaultResponse(upnpStatus.getCode(), upnpStatus.getDescription()); } queryReq.post(queryRes); return true; @@ -371,4 +434,44 @@ public class StateVariable extends NodeData { return upnpStatus; } + + private static final String DEFAULT_VALUE = "defaultValue"; + //////////////////////////////////////////////// + /** + * Get the value of DefaultValue of this StateVariable + * + * @author Stefano Lenzi kismet-sl@users.sourceforge.net + */ + public String getDefaultValue() { + return getStateVariableNode().getNodeValue(DEFAULT_VALUE); + } + + /** + * This method ovverride the value of the DefaultValue of this object.
+ *
+ * Note: This method should be used to create a dynamic
+ * Device withtout writing any XML that describe the device
. + * + * @param value The new String value + * + * @author Stefano Lenzi kismet-sl@users.sourceforge.net + */ + public void setDefaultValue(String value){ + getStateVariableNode().setNode(DEFAULT_VALUE,value); + } + //////////////////////////////////////////////// + // userData + //////////////////////////////////////////////// + + private Object userData = null; + + public void setUserData(Object data) + { + userData = data; + } + + public Object getUserData() + { + return userData; + } } diff --git a/router/java/src/org/cybergarage/upnp/UPnP.java b/router/java/src/org/cybergarage/upnp/UPnP.java index 22f209d6a..efb7e56bb 100644 --- a/router/java/src/org/cybergarage/upnp/UPnP.java +++ b/router/java/src/org/cybergarage/upnp/UPnP.java @@ -5,54 +5,64 @@ * Copyright (C) Satoshi Konno 2002-2003 * * File: UPnP.java -* -* Revision; -* -* 11/18/02 -* - first revision. +* +* Revision; +* +* 11/18/02 +* - first revision. * 05/13/03 * - Added support for IPv6 and loopback address. * 12/26/03 * - Added support for XML Parser * 06/18/03 * - Added INMPR03 and INMPR03_VERSION. +* 04/14/06 +* - Added some functios about time-to-live, and the default value is 4. +* 05/11/09 +* - Changed loadDefaultXMLParser() to load org.cybergarage.xml.parser.XmlPullParser at first. * ******************************************************************/ - -package org.cybergarage.upnp; -import org.cybergarage.upnp.ssdp.*; -//import org.cybergarage.util.*; -import org.cybergarage.xml.*; -import org.cybergarage.xml.parser.*; -import org.cybergarage.soap.*; -import org.cybergarage.net.*; +package org.cybergarage.upnp; -public class UPnP -{ - //////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////// - - public final static String NAME = "CyberLink"; - public final static String VERSION = "1.7"; +import org.cybergarage.net.HostInterface; +import org.cybergarage.soap.SOAP; +import org.cybergarage.upnp.ssdp.SSDP; +import org.cybergarage.util.Debug; +import org.cybergarage.xml.Parser; + +public class UPnP +{ + //////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////// + + /** + * Name of the system properties used to identifies the default XML Parser.
+ * The value of the properties MUST BE the fully qualified class name of
+ * XML Parser which CyberLink should use. + */ + public final static String XML_CLASS_PROPERTTY="cyberlink.upnp.xml.parser"; + + public final static String NAME = "CyberLinkJava"; + public final static String VERSION = "1.8"; // I2P was 100 public final static int SERVER_RETRY_COUNT = 4; public final static int DEFAULT_EXPIRED_DEVICE_EXTRA_TIME = 60; - public final static String getServerName() + public final static String getServerName() { String osName = System.getProperty("os.name"); String osVer = System.getProperty("os.version"); - return osName + "/" + osVer + " UPnP/1.0 " + NAME + "/" + VERSION; - } + return osName + "/" + osVer + " UPnP/1.0 " + NAME + "/" + VERSION; + } public final static String INMPR03 = "INMPR03"; public final static String INMPR03_VERSION = "1.0"; public final static int INMPR03_DISCOVERY_OVER_WIRELESS_COUNT = 4; - public final static String XML_DECLARATION = ""; + public final static String XML_DECLARATION = ""; //////////////////////////////////////////////// // Enable / Disable @@ -194,8 +204,67 @@ public class UPnP public final static Parser getXMLParser() { + if(xmlParser == null){ + xmlParser = loadDefaultXMLParser(); + if(xmlParser == null) + throw new RuntimeException("No XML parser defined. And unable to laod any. \n" + + "Try to invoke UPnP.setXMLParser before UPnP.getXMLParser"); + SOAP.setXMLParser(xmlParser); + } return xmlParser; } + + /** + * This method loads the default XML Parser using the following behavior: + * - First if present loads the parsers specified by the system property {@link UPnP#XML_CLASS_PROPERTTY}
+ * - Second by a fall-back technique, it tries to load the XMLParser from one
+ * of the following classes: {@link JaxpParser}, {@link kXML2Parser}, {@link XercesParser} + * + * @return {@link Parser} which has been loaded successuflly or null otherwise + * + * @since 1.8.0 + */ + private static Parser loadDefaultXMLParser() { + Parser parser = null; + + String[] parserClass = new String[]{ + System.getProperty(XML_CLASS_PROPERTTY), + "org.cybergarage.xml.parser.XmlPullParser", + "org.cybergarage.xml.parser.JaxpParser", + "org.cybergarage.xml.parser.kXML2Parser", + "org.cybergarage.xml.parser.XercesParser" + }; + + for (int i = 0; i < parserClass.length; i++) { + if(parserClass[i]==null) + continue; + try { + parser = (Parser) Class.forName(parserClass[i]).newInstance(); + return parser; + } catch (Throwable e) { + Debug.warning("Unable to load "+parserClass[i]+" as XMLParser due to "+e); + } + } + return null; + } + + //////////////////////////////////////////////// + // TTL + //////////////////////////////////////////////// + + public final static int DEFAULT_TTL = 4; + + private static int timeToLive = DEFAULT_TTL; + + public final static void setTimeToLive(int value) + { + timeToLive = value; + } + + public final static int getTimeToLive() + { + return timeToLive; + } //////////////////////////////////////////////// // Initialize @@ -207,16 +276,14 @@ public class UPnP // Interface Option //////////////////////////// - setXMLParser(new JaxpParser()); //setXMLParser(new kXML2Parser()); + //////////////////////////// - // Interface Option + // TimeToLive //////////////////////////// - /* - if (HostInterface.hasIPv6Addresses() == true) - setEnable(USE_ONLY_IPV6_ADDR); - */ + + setTimeToLive(DEFAULT_TTL); //////////////////////////// // Debug Option diff --git a/router/java/src/org/cybergarage/upnp/UPnPStatus.java b/router/java/src/org/cybergarage/upnp/UPnPStatus.java index f00ba6921..0244a6b1d 100644 --- a/router/java/src/org/cybergarage/upnp/UPnPStatus.java +++ b/router/java/src/org/cybergarage/upnp/UPnPStatus.java @@ -16,6 +16,7 @@ ******************************************************************/ package org.cybergarage.upnp; +import org.cybergarage.http.HTTPStatus; public class UPnPStatus { @@ -39,8 +40,8 @@ public class UPnPStatus case INVALID_VAR: return "Invalid Var"; case PRECONDITION_FAILED: return "Precondition Failed"; case ACTION_FAILED: return "Action Failed"; + default: return HTTPStatus.code2String(code); } - return ""; } //////////////////////////////////////////////// diff --git a/router/java/src/org/cybergarage/upnp/control/ControlResponse.java b/router/java/src/org/cybergarage/upnp/control/ControlResponse.java index 36fcab89d..b764a6ae7 100644 --- a/router/java/src/org/cybergarage/upnp/control/ControlResponse.java +++ b/router/java/src/org/cybergarage/upnp/control/ControlResponse.java @@ -102,6 +102,11 @@ public class ControlResponse extends SOAPResponse return faultNode; } + private Node createFaultResponseNode(int errCode) + { + return createFaultResponseNode(errCode, UPnPStatus.code2String(errCode)); + } + //////////////////////////////////////////////// // UPnP Error //////////////////////////////////////////////// diff --git a/router/java/src/org/cybergarage/upnp/control/QueryRequest.java b/router/java/src/org/cybergarage/upnp/control/QueryRequest.java index d222051fc..ad8b437e5 100644 --- a/router/java/src/org/cybergarage/upnp/control/QueryRequest.java +++ b/router/java/src/org/cybergarage/upnp/control/QueryRequest.java @@ -74,6 +74,8 @@ public class QueryRequest extends ControlRequest { Service service = stateVar.getService(); + String ctrlURL = service.getControlURL(); + setRequestHost(service); setEnvelopeNode(SOAP.createEnvelopeBodyNode()); diff --git a/router/java/src/org/cybergarage/upnp/control/RenewSubscriber.java b/router/java/src/org/cybergarage/upnp/control/RenewSubscriber.java index 6b5fef987..7b8d2e059 100644 --- a/router/java/src/org/cybergarage/upnp/control/RenewSubscriber.java +++ b/router/java/src/org/cybergarage/upnp/control/RenewSubscriber.java @@ -51,7 +51,6 @@ public class RenewSubscriber extends ThreadCore // Thread //////////////////////////////////////////////// - @Override public void run() { ControlPoint ctrlp = getControlPoint(); diff --git a/router/java/src/org/cybergarage/upnp/device/Advertiser.java b/router/java/src/org/cybergarage/upnp/device/Advertiser.java index 58b5dd610..373fea82d 100644 --- a/router/java/src/org/cybergarage/upnp/device/Advertiser.java +++ b/router/java/src/org/cybergarage/upnp/device/Advertiser.java @@ -51,7 +51,6 @@ public class Advertiser extends ThreadCore // Thread //////////////////////////////////////////////// - @Override public void run() { Device dev = getDevice(); diff --git a/router/java/src/org/cybergarage/upnp/device/Disposer.java b/router/java/src/org/cybergarage/upnp/device/Disposer.java index e76befec3..1de8ceb3b 100644 --- a/router/java/src/org/cybergarage/upnp/device/Disposer.java +++ b/router/java/src/org/cybergarage/upnp/device/Disposer.java @@ -49,7 +49,6 @@ public class Disposer extends ThreadCore // Thread //////////////////////////////////////////////// - @Override public void run() { Thread.currentThread().setName("UPnP-Disposer"); diff --git a/router/java/src/org/cybergarage/upnp/device/InvalidDescriptionException.java b/router/java/src/org/cybergarage/upnp/device/InvalidDescriptionException.java index a08b3a393..514524589 100644 --- a/router/java/src/org/cybergarage/upnp/device/InvalidDescriptionException.java +++ b/router/java/src/org/cybergarage/upnp/device/InvalidDescriptionException.java @@ -19,8 +19,6 @@ import java.io.*; public class InvalidDescriptionException extends Exception { - private static final long serialVersionUID = -3144583349586910509L; - public InvalidDescriptionException() { super(); diff --git a/router/java/src/org/cybergarage/upnp/event/NotifyRequest.java b/router/java/src/org/cybergarage/upnp/event/NotifyRequest.java index 048a0369a..5ebc1f21c 100644 --- a/router/java/src/org/cybergarage/upnp/event/NotifyRequest.java +++ b/router/java/src/org/cybergarage/upnp/event/NotifyRequest.java @@ -115,6 +115,7 @@ public class NotifyRequest extends SOAPRequest public boolean setRequest(Subscriber sub, String varName, String value) { + String callback = sub.getDeliveryURL(); String sid = sub.getSID(); long notifyCnt = sub.getNotifyCount(); String host = sub.getDeliveryHost(); @@ -154,6 +155,19 @@ public class NotifyRequest extends SOAPRequest return propSetNode; } + private Node getVariableNode() + { + Node rootNode = getEnvelopeNode(); + if (rootNode == null) + return null; + if (rootNode.hasNodes() == false) + return null; + Node propNode = rootNode.getNode(0); + if (propNode.hasNodes() == false) + return null; + return propNode.getNode(0); + } + // Thanks for Giordano Sassaroli (09/08/03) private Property getProperty(Node varNode) { diff --git a/router/java/src/org/cybergarage/upnp/event/PropertyList.java b/router/java/src/org/cybergarage/upnp/event/PropertyList.java index f890bb3af..f2d8a22a7 100644 --- a/router/java/src/org/cybergarage/upnp/event/PropertyList.java +++ b/router/java/src/org/cybergarage/upnp/event/PropertyList.java @@ -23,7 +23,6 @@ public class PropertyList extends Vector // Constants //////////////////////////////////////////////// - private static final long serialVersionUID = 8718064210738306226L; public final static String ELEM_NAME = "PropertyList"; //////////////////////////////////////////////// diff --git a/router/java/src/org/cybergarage/upnp/event/SubscriberList.java b/router/java/src/org/cybergarage/upnp/event/SubscriberList.java index 0a991204a..63bfdb786 100644 --- a/router/java/src/org/cybergarage/upnp/event/SubscriberList.java +++ b/router/java/src/org/cybergarage/upnp/event/SubscriberList.java @@ -25,8 +25,6 @@ public class SubscriberList extends Vector // Constructor //////////////////////////////////////////////// - private static final long serialVersionUID = -648427977601494972L; - public SubscriberList() { } diff --git a/router/java/src/org/cybergarage/upnp/event/Subscription.java b/router/java/src/org/cybergarage/upnp/event/Subscription.java index c03638daa..0685e4fa8 100644 --- a/router/java/src/org/cybergarage/upnp/event/Subscription.java +++ b/router/java/src/org/cybergarage/upnp/event/Subscription.java @@ -68,6 +68,8 @@ public class Subscription { if (headerValue == null) return ""; + if (headerValue.startsWith(Subscription.UUID) == false) + return headerValue; return headerValue.substring(Subscription.UUID.length(), headerValue.length()); } diff --git a/router/java/src/org/cybergarage/upnp/event/SubscriptionRequest.java b/router/java/src/org/cybergarage/upnp/event/SubscriptionRequest.java index a3e11cc65..4ba930c12 100644 --- a/router/java/src/org/cybergarage/upnp/event/SubscriptionRequest.java +++ b/router/java/src/org/cybergarage/upnp/event/SubscriptionRequest.java @@ -43,12 +43,12 @@ public class SubscriptionRequest extends HTTPRequest // Constructor //////////////////////////////////////////////// - public SubscriptionRequest() - { + public SubscriptionRequest(){ + setContentLength(0); } - public SubscriptionRequest(HTTPRequest httpReq) - { + public SubscriptionRequest(HTTPRequest httpReq){ + this(); set(httpReq); } diff --git a/router/java/src/org/cybergarage/upnp/ssdp/HTTPMUSocket.java b/router/java/src/org/cybergarage/upnp/ssdp/HTTPMUSocket.java index ed70b118a..57c60d009 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/HTTPMUSocket.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/HTTPMUSocket.java @@ -19,16 +19,32 @@ * 11/19/04 * - Theo Beisch * - Changed send() to set the TTL as 4. +* 08/23/07 +* - Thanks for Kazuyuki Shudo +* - Changed receive() to throw IOException. +* 01/10/08 +* - Changed getLocalAddress() to return a brank string when the ssdpMultiGroup or ssdpMultiIf is null on Android m3-rc37a. * ******************************************************************/ package org.cybergarage.upnp.ssdp; -import java.net.*; -import java.util.*; +import java.net.DatagramPacket; +import java.net.MulticastSocket; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.util.Enumeration; +import java.io.IOException; -import org.cybergarage.http.*; -import org.cybergarage.util.*; +import org.cybergarage.http.HTTPRequest; +import org.cybergarage.upnp.UPnP; +import org.cybergarage.util.Debug; + +// Dummy Class for Android m3-rc37a +// import org.cybergarage.android.MulticastSocket; public class HTTPMUSocket { @@ -39,7 +55,7 @@ public class HTTPMUSocket private InetSocketAddress ssdpMultiGroup = null; private MulticastSocket ssdpMultiSock = null; private NetworkInterface ssdpMultiIf = null; - + //////////////////////////////////////////////// // Constructor //////////////////////////////////////////////// @@ -53,7 +69,6 @@ public class HTTPMUSocket open(addr, port, bindAddr); } - @Override protected void finalize() { close(); @@ -65,6 +80,8 @@ public class HTTPMUSocket public String getLocalAddress() { + if (ssdpMultiGroup == null || ssdpMultiIf == null) + return ""; InetAddress mcastAddr = ssdpMultiGroup.getAddress(); Enumeration addrs = ssdpMultiIf.getInetAddresses(); while (addrs.hasMoreElements()) { @@ -77,6 +94,34 @@ public class HTTPMUSocket return ""; } + /** + * + * @return the destination port for multicast packet + * @since 1.8 + */ + public int getMulticastPort(){ + return ssdpMultiGroup.getPort(); + } + + /** + * + * @return the source port for multicast packet + * @since 1.8 + */ + public int getLocalPort(){ + return ssdpMultiSock.getLocalPort(); + } + + /** + * + * @return the opened {@link MulticastSocket} + * @since 1.8 + */ + public MulticastSocket getSocket(){ + return ssdpMultiSock; + } + + //////////////////////////////////////////////// // MulticastAddr //////////////////////////////////////////////// @@ -91,19 +136,20 @@ public class HTTPMUSocket return getMulticastInetAddress().getHostAddress(); } - //////////////////////////////////////////////// - // open/close - //////////////////////////////////////////////// - - public boolean open(String addr, int port, String bindAddr) - { + /** + * @param addr {@link String} rappresenting the multicast hostname to join into. + * @param port int rappresenting the port to be use poth as source and destination + * @param bindAddr {@link InetAddress} which identify the hostname of the interface + * to use for sending and recieving multicast packet + */ + public boolean open(String addr,int port, InetAddress bindAddr){ try { ssdpMultiSock = new MulticastSocket(null); ssdpMultiSock.setReuseAddress(true); InetSocketAddress bindSockAddr = new InetSocketAddress(port); ssdpMultiSock.bind(bindSockAddr); ssdpMultiGroup = new InetSocketAddress(InetAddress.getByName(addr), port); - ssdpMultiIf = NetworkInterface.getByInetAddress(InetAddress.getByName(bindAddr)); + ssdpMultiIf = NetworkInterface.getByInetAddress(bindAddr); ssdpMultiSock.joinGroup(ssdpMultiGroup, ssdpMultiIf); } catch (Exception e) { @@ -111,7 +157,17 @@ public class HTTPMUSocket return false; } - return true; + return true; + } + + public boolean open(String addr, int port, String bindAddr) + { + try { + return open(addr,port,InetAddress.getByName(bindAddr)); + }catch (Exception e) { + Debug.warning(e); + return false; + } } public boolean close() @@ -120,9 +176,8 @@ public class HTTPMUSocket return true; try { - // I2P close it instead of leaving group so the thread dies - //ssdpMultiSock.leaveGroup(ssdpMultiGroup, ssdpMultiIf); - ssdpMultiSock.close(); + ssdpMultiSock.leaveGroup(ssdpMultiGroup, ssdpMultiIf); + ssdpMultiSock.close(); ssdpMultiSock = null; } catch (Exception e) { @@ -144,12 +199,12 @@ public class HTTPMUSocket if ((bindAddr) != null && (0 < bindPort)) { msock = new MulticastSocket(null); msock.bind(new InetSocketAddress(bindAddr, bindPort)); - } - else + }else{ msock = new MulticastSocket(); + } DatagramPacket dgmPacket = new DatagramPacket(msg.getBytes(), msg.length(), ssdpMultiGroup); - // Thnaks for Tho Beisch (11/09/04) - msock.setTimeToLive(4); + // Thnaks for Theo Beisch (11/09/04) + msock.setTimeToLive(UPnP.getTimeToLive()); msock.send(dgmPacket); msock.close(); } @@ -183,20 +238,22 @@ public class HTTPMUSocket // reveive //////////////////////////////////////////////// - public SSDPPacket receive() + public SSDPPacket receive() throws IOException { byte ssdvRecvBuf[] = new byte[SSDP.RECV_MESSAGE_BUFSIZE]; SSDPPacket recvPacket = new SSDPPacket(ssdvRecvBuf, ssdvRecvBuf.length); recvPacket.setLocalAddress(getLocalAddress()); - try { - ssdpMultiSock.receive(recvPacket.getDatagramPacket()); - recvPacket.setTimeStamp(System.currentTimeMillis()); - Debug.message("Received SSDP multicast packet on " + getLocalAddress() + " from " + recvPacket.getRemoteAddress()); - } - catch (Exception e) { - //Debug.warning(e); - } - return recvPacket; + + // Thanks for Kazuyuki Shudo (08/23/07) + // Thanks for Stephan Mehlhase (2010-10-26) + if (ssdpMultiSock != null) + ssdpMultiSock.receive(recvPacket.getDatagramPacket()); // throws IOException + else + throw new IOException("Multicast socket has already been closed."); + + recvPacket.setTimeStamp(System.currentTimeMillis()); + + return recvPacket; } } diff --git a/router/java/src/org/cybergarage/upnp/ssdp/HTTPUSocket.java b/router/java/src/org/cybergarage/upnp/ssdp/HTTPUSocket.java index f7c1bc60a..bded92b89 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/HTTPUSocket.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/HTTPUSocket.java @@ -5,11 +5,11 @@ * Copyright (C) Satoshi Konno 2002-2003 * * File: HTTPMU.java -* -* Revision; -* -* 11/20/02 -* - first revision. +* +* Revision; +* +* 11/20/02 +* - first revision. * 12/12/03 * - Inma Mar?n * - Changed open(addr, port) to send IPv6 SSDP packets. @@ -20,47 +20,49 @@ * - Added to set a current timestamp when the packet are received. * ******************************************************************/ + +package org.cybergarage.upnp.ssdp; + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; -package org.cybergarage.upnp.ssdp; - -import java.net.*; - -import org.cybergarage.util.*; - -public class HTTPUSocket -{ - //////////////////////////////////////////////// - // Member - //////////////////////////////////////////////// - - private DatagramSocket ssdpUniSock = null; +import org.cybergarage.util.Debug; + +public class HTTPUSocket +{ + //////////////////////////////////////////////// + // Member + //////////////////////////////////////////////// + + private DatagramSocket ssdpUniSock = null; //private MulticastSocket ssdpUniSock = null; - - public DatagramSocket getDatagramSocket() - { - return ssdpUniSock; - } - - //////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////// - - public HTTPUSocket() + + public DatagramSocket getDatagramSocket() + { + return ssdpUniSock; + } + + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + public HTTPUSocket() { open(); - } - - public HTTPUSocket(String bindAddr, int bindPort) + } + + public HTTPUSocket(String bindAddr, int bindPort) { open(bindAddr, bindPort); - } + } public HTTPUSocket(int bindPort) { open(bindPort); } - - @Override + protected void finalize() { close(); @@ -76,6 +78,15 @@ public class HTTPUSocket { localAddr = addr; } + + /** + * + * @return {@link DatagramSocket} open for receieving packets + * @since 1.8 + */ + public DatagramSocket getUDPSocket(){ + return ssdpUniSock; + } public String getLocalAddress() { @@ -108,16 +119,29 @@ public class HTTPUSocket close(); try { - // Bind only using the port without the interface address. (2003/12/12) - InetSocketAddress bindSock = new InetSocketAddress(/*InetAddress.getByName(bindAddr), */ bindPort); - ssdpUniSock = new DatagramSocket(null); - ssdpUniSock.setReuseAddress(true); - ssdpUniSock.bind(bindSock); + // Changed to bind the specified address and port for Android v1.6 (2009/10/07) + InetSocketAddress bindInetAddr = new InetSocketAddress(InetAddress.getByName(bindAddr), bindPort); + ssdpUniSock = new DatagramSocket(bindInetAddr); } catch (Exception e) { Debug.warning(e); return false; } + + /* + try { + // Bind only using the port without the interface address. (2003/12/12) + InetSocketAddress bindInetAddr = new InetSocketAddress(bindPort); + ssdpUniSock = new DatagramSocket(null); + ssdpUniSock.setReuseAddress(true); + ssdpUniSock.bind(bindInetAddr); + return true; + } + catch (Exception e) { + Debug.warning(e); + return false; + } + */ setLocalAddress(bindAddr); @@ -142,67 +166,67 @@ public class HTTPUSocket return true; } - //////////////////////////////////////////////// - // close - //////////////////////////////////////////////// - - public boolean close() - { - if (ssdpUniSock == null) - return true; - - try { + //////////////////////////////////////////////// + // close + //////////////////////////////////////////////// + + public boolean close() + { + if (ssdpUniSock == null) + return true; + + try { ssdpUniSock.close(); - ssdpUniSock = null; - } - catch (Exception e) { - Debug.warning(e); - return false; - } - - return true; - } + ssdpUniSock = null; + } + catch (Exception e) { + Debug.warning(e); + return false; + } + + return true; + } - //////////////////////////////////////////////// - // send - //////////////////////////////////////////////// - - public boolean post(String addr, int port, String msg) - { - try { - InetAddress inetAddr = InetAddress.getByName(addr); - DatagramPacket dgmPacket = new DatagramPacket(msg.getBytes(), msg.length(), inetAddr, port); + //////////////////////////////////////////////// + // send + //////////////////////////////////////////////// + + public boolean post(String addr, int port, String msg) + { + try { + InetAddress inetAddr = InetAddress.getByName(addr); + DatagramPacket dgmPacket = new DatagramPacket(msg.getBytes(), msg.length(), inetAddr, port); ssdpUniSock.send(dgmPacket); - } + } catch (Exception e) { - Debug.warning("addr = " +ssdpUniSock.getLocalAddress().getHostName()); + Debug.warning("addr = " +ssdpUniSock.getLocalAddress().getHostName()); Debug.warning("port = " + ssdpUniSock.getLocalPort()); - Debug.warning(e); - return false; - } - return true; - } - - //////////////////////////////////////////////// - // reveive - //////////////////////////////////////////////// - - public SSDPPacket receive() - { - byte ssdvRecvBuf[] = new byte[SSDP.RECV_MESSAGE_BUFSIZE]; - SSDPPacket recvPacket = new SSDPPacket(ssdvRecvBuf, ssdvRecvBuf.length); + Debug.warning(e); + return false; + } + return true; + } + + //////////////////////////////////////////////// + // reveive + //////////////////////////////////////////////// + + public SSDPPacket receive() + { + byte ssdvRecvBuf[] = new byte[SSDP.RECV_MESSAGE_BUFSIZE]; + SSDPPacket recvPacket = new SSDPPacket(ssdvRecvBuf, ssdvRecvBuf.length); recvPacket.setLocalAddress(getLocalAddress()); - try { - ssdpUniSock.receive(recvPacket.getDatagramPacket()); + try { + ssdpUniSock.receive(recvPacket.getDatagramPacket()); recvPacket.setTimeStamp(System.currentTimeMillis()); Debug.message("Received SSDP unicast packet on " + getLocalAddress() + " from " + recvPacket.getRemoteAddress()); - } - catch (Exception e) { + } + catch (Exception e) { //Debug.warning(e); - return null; - } - return recvPacket; - } + return null; + } + return recvPacket; + } //////////////////////////////////////////////// // join/leave @@ -237,5 +261,5 @@ public class HTTPUSocket return true; } */ -} - +} + diff --git a/router/java/src/org/cybergarage/upnp/ssdp/SSDP.java b/router/java/src/org/cybergarage/upnp/ssdp/SSDP.java index 8f692355f..0d1867ff5 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/SSDP.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/SSDP.java @@ -5,27 +5,49 @@ * Copyright (C) Satoshi Konno 2002 * * File: SSDP.java -* -* Revision; -* -* 11/18/02 -* - first revision. +* +* Revision; +* +* 11/18/02 +* - first revision. * 05/13/03 * - Added constants for IPv6. +* 08/03/05 +* - Thanks for Stefano Lenzi +* and Mikael +* - Fixed getLeaseTime() to parse normally when the value includes extra strings such as white space. * ******************************************************************/ - -package org.cybergarage.upnp.ssdp; - -public class SSDP -{ - //////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////// - - public static final int PORT = 1900; - - public static final String ADDRESS = "239.255.255.250"; + +package org.cybergarage.upnp.ssdp; + +import org.cybergarage.util.Debug; + +/** + * + * This class defines constant value related to SSDP.
+ * All the values defined here are complaint to the UPnP Standard + * + * @author Satoshi "skonno" Konno + * @author Stefano "Kismet" Lenzi + * @version 1.0 + * + */ +public class SSDP +{ + //////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////// + + /** + * Default destination port for SSDP multicast messages + */ + public static final int PORT = 1900; + + /** + * Default IPv4 multicast address for SSDP messages + */ + public static final String ADDRESS = "239.255.255.250"; public static final String IPV6_LINK_LOCAL_ADDRESS = "FF02::C"; public static final String IPV6_SUBNET_ADDRESS = "FF03::C"; @@ -37,7 +59,7 @@ public class SSDP public static final void setIPv6Address(String addr) { - IPV6_ADDRESS = addr; + IPV6_ADDRESS = addr; } public static final String getIPv6Address() @@ -45,9 +67,9 @@ public class SSDP return IPV6_ADDRESS; } - public static final int DEFAULT_MSEARCH_MX = 3; - - public static final int RECV_MESSAGE_BUFSIZE = 1024; + public static final int DEFAULT_MSEARCH_MX = 3; + + public static final int RECV_MESSAGE_BUFSIZE = 1024; //////////////////////////////////////////////// // Initialize @@ -61,17 +83,27 @@ public class SSDP //////////////////////////////////////////////// // LeaseTime //////////////////////////////////////////////// - - public final static int getLeaseTime(String cacheCont) - { - int equIdx = cacheCont.indexOf('='); - int mx = 0; - try { - String mxStr = new String(cacheCont.getBytes(), equIdx+1, cacheCont.length() - (equIdx+1)); - mx = Integer.parseInt(mxStr); - } - catch (Exception e) {} - return mx; + + public final static int getLeaseTime(String cacheCont){ + /* + * Search for max-age keyword instead of equals sign Found value of + * max-age ends at next comma or end of string + */ + int mx = 0; + int maxAgeIdx = cacheCont.indexOf("max-age"); + if (maxAgeIdx >= 0) { + int endIdx = cacheCont.indexOf(',',maxAgeIdx); + if (endIdx < 0) + endIdx = cacheCont.length(); + try { + maxAgeIdx = cacheCont.indexOf("=",maxAgeIdx); + String mxStr = cacheCont.substring(maxAgeIdx+1,endIdx).trim(); + mx = Integer.parseInt(mxStr); + } catch (Exception e) { + Debug.warning (e); + } + } + return mx; } } - + diff --git a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifyRequest.java b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifyRequest.java index b2fb3c5c0..1df63ff6c 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifyRequest.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifyRequest.java @@ -15,7 +15,7 @@ package org.cybergarage.upnp.ssdp; -import org.cybergarage.http.*; +import org.cybergarage.http.HTTP; public class SSDPNotifyRequest extends SSDPRequest { diff --git a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocket.java b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocket.java index fe67a33fb..1bdf22f0f 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocket.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocket.java @@ -19,18 +19,34 @@ * - Mikael Hakman * - Handle receive() returning null. * - Added close() in stop(). +* 08/23/07 +* - Thanks for Kazuyuki Shudo +* - Changed run() to catch IOException of HTTPMUSocket::receive(). +* 01/31/08 +* - Changed start() not to abort when the interface infomation is null on Android m3-rc37a. * ******************************************************************/ package org.cybergarage.upnp.ssdp; import java.net.*; +import java.io.IOException; import org.cybergarage.net.*; +import org.cybergarage.util.*; import org.cybergarage.http.*; import org.cybergarage.upnp.*; import org.cybergarage.util.Debug; +/** + * + * This class identifies a SSDP socket only for notifing packet.
+ * + * @author Satoshi "skonno" Konno + * @author Stefano "Kismet" Lenzi + * @version 1.8 + * + */ public class SSDPNotifySocket extends HTTPMUSocket implements Runnable { private boolean useIPv6Address; @@ -68,10 +84,13 @@ public class SSDPNotifySocket extends HTTPMUSocket implements Runnable return controlPoint; } - //////////////////////////////////////////////// - // post (SSDPNotifySocket) - //////////////////////////////////////////////// - + /** + * This method send a {@link SSDPNotifyRequest} over {@link SSDPNotifySocket} + * + * @param req the {@link SSDPNotifyRequest} to send + * @return true if and only if the trasmission succeced
+ * Because it rely on UDP doesn't mean that it's also recieved + */ public boolean post(SSDPNotifyRequest req) { String ssdpAddr = SSDP.ADDRESS; @@ -95,7 +114,15 @@ public class SSDPNotifySocket extends HTTPMUSocket implements Runnable while (deviceNotifyThread == thisThread) { Thread.yield(); - SSDPPacket packet = receive(); + + // Thanks for Kazuyuki Shudo (08/23/07) + SSDPPacket packet = null; + try { + packet = receive(); + } + catch (IOException e) { + break; + } // Thanks for Mikael Hakman (04/20/05) if (packet == null) @@ -109,16 +136,23 @@ public class SSDPNotifySocket extends HTTPMUSocket implements Runnable //Debug.warning("Invalidate Multicast Recieved : " + maddr + "," + pmaddr); continue; } - + //TODO Must be performed on a different Thread in order to prevent UDP packet losses. if (ctrlPoint != null) ctrlPoint.notifyReceived(packet); } } - public void start() - { - deviceNotifyThread = new Thread(this, "UPnP-SSDPNotifySocket"); - deviceNotifyThread.setDaemon(true); + public void start(){ + StringBuffer name = new StringBuffer("Cyber.SSDPNotifySocket/"); + String localAddr = this.getLocalAddress(); + // localAddr is null on Android m3-rc37a (01/30/08) + if (localAddr != null && 0 < localAddr.length()) { + name.append(this.getLocalAddress()).append(':'); + name.append(this.getLocalPort()).append(" -> "); + name.append(this.getMulticastAddress()).append(':'); + name.append(this.getMulticastPort()); + } + deviceNotifyThread = new Thread(this,name.toString()); deviceNotifyThread.start(); } diff --git a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocketList.java b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocketList.java index d0541510c..64a264965 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocketList.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/SSDPNotifySocketList.java @@ -1,106 +1,129 @@ -/****************************************************************** -* -* CyberUPnP for Java -* -* Copyright (C) Satoshi Konno 2002-2003 +/****************************************************************** * -* File: HTTPServerList.java -* -* Revision; -* -* 05/11/03 -* - first revision. -* -******************************************************************/ +* CyberUPnP for Java +* +* Copyright (C) Satoshi Konno 2002-2003 +* +* File: HTTPServerList.java +* +* Revision; +* +* 05/11/03 +* - first revision. +* +******************************************************************/ + +package org.cybergarage.upnp.ssdp; + +import java.net.InetAddress; +import java.util.*; + +import org.cybergarage.net.*; + +import org.cybergarage.upnp.*; + +public class SSDPNotifySocketList extends Vector +{ + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + private InetAddress[] binds = null; + + public SSDPNotifySocketList() { + } + + /** + * + * @param binds The host to bind the service null means to bind to default. + * @since 1.8 + */ + public SSDPNotifySocketList(InetAddress[] binds){ + this.binds=binds; + } + + //////////////////////////////////////////////// + // Methods + //////////////////////////////////////////////// + + public SSDPNotifySocket getSSDPNotifySocket(int n) + { + return (SSDPNotifySocket)get(n); + } + + //////////////////////////////////////////////// + // ControlPoint + //////////////////////////////////////////////// + + public void setControlPoint(ControlPoint ctrlPoint) + { + int nSockets = size(); + for (int n=0; nnull for the default behavior + */ + public SSDPSearchResponseSocketList(InetAddress[] binds) { + this.binds = binds; + } + + + + //////////////////////////////////////////////// + // ControlPoint + + //////////////////////////////////////////////// + // ControlPoint + //////////////////////////////////////////////// + + public void setControlPoint(ControlPoint ctrlPoint) + { + int nSockets = size(); + for (int n=0; n * - Added close() in stop(). * - Added test for null return from receive() in run(). +* 08/23/07 +* - Thanks for Kazuyuki Shudo +* - Changed run() to catch IOException of HTTPMUSocket::receive(). +* 01/10/08 +* - Changed start() not to abort when the interface infomation is null on Android m3-rc37a. * ******************************************************************/ - -package org.cybergarage.upnp.ssdp; - + +package org.cybergarage.upnp.ssdp; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.io.IOException; + import org.cybergarage.net.*; import org.cybergarage.util.*; -import org.cybergarage.upnp.device.*; - -public class SSDPSearchSocket extends HTTPMUSocket implements Runnable -{ - public SSDPSearchSocket() - { - } +import org.cybergarage.upnp.device.*; + +public class SSDPSearchSocket extends HTTPMUSocket implements Runnable +{ + private boolean useIPv6Address; - public SSDPSearchSocket(String bindAddr) - { - open(bindAddr); - Debug.message("Opened SSDP search socket at " + bindAddr + ':' + SSDP.PORT); + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + + /** + * + * @param bindAddr The address to bind the service + * @param port The port used for accepting message + * @param multicast The multicast address to use as destination + * @since 1.8 + */ + public SSDPSearchSocket(String bindAddr,int port,String multicast){ + open(bindAddr,multicast); + } + + /** + * + * @param bindAddr the binding address for senging multicast packet + * @since 1.8 + */ + public SSDPSearchSocket(InetAddress bindAddr){ + if(bindAddr.getAddress().length!=4){ + this.open((Inet6Address)bindAddr); + }else{ + this.open((Inet4Address)bindAddr); + } } //////////////////////////////////////////////// // Constructor //////////////////////////////////////////////// + public boolean open(Inet4Address bindAddr){ + useIPv6Address = false; + return open(SSDP.ADDRESS, SSDP.PORT, bindAddr); + } + + public boolean open(Inet6Address bindAddr){ + useIPv6Address = true; + return open(SSDP.getIPv6Address(), SSDP.PORT, bindAddr); + } + + public boolean open(String bind,String multicast){ + if ((HostInterface.isIPv6Address(bind) ) && (HostInterface.isIPv6Address(multicast))){ + useIPv6Address = true; + }else if(HostInterface.isIPv4Address(bind) && (HostInterface.isIPv4Address(multicast))){ + useIPv6Address = false; + }else{ + throw new IllegalArgumentException("Cannot open a UDP Socket for IPv6 address on IPv4 interface or viceversa"); + } + return open(multicast, SSDP.PORT, bind); + } + /** + * + * @param bindAddr the hostname of the interface to use for senfing multicast packet + * @return true if and only if it open the socket + * @see {@link SSDP} for default multicast and port destination of the packtes + */ public boolean open(String bindAddr) { String addr = SSDP.ADDRESS; + useIPv6Address = false; if (HostInterface.isIPv6Address(bindAddr) == true) { addr = SSDP.getIPv6Address(); + useIPv6Address = true; } return open(addr, SSDP.PORT, bindAddr); } - //////////////////////////////////////////////// - // deviceSearch - //////////////////////////////////////////////// - - private ListenerList deviceSearchListenerList = new ListenerList(); - - public void addSearchListener(SearchListener listener) - { - deviceSearchListenerList.add(listener); - } - - public void removeSearchListener(SearchListener listener) - { - deviceSearchListenerList.remove(listener); - } - - public void performSearchListener(SSDPPacket ssdpPacket) - { - int listenerSize = deviceSearchListenerList.size(); - for (int n=0; n "); + name.append(this.getMulticastAddress()).append(':'); + name.append(this.getMulticastPort()); + } + deviceSearchThread = new Thread(this,name.toString()); + deviceSearchThread.start(); + } + + public void stop() { // Thanks for Mikael Hakman (04/20/05) close(); - deviceSearchThread = null; - } + deviceSearchThread = null; + } } - + diff --git a/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocketList.java b/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocketList.java index 7fc372411..185bb15fc 100644 --- a/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocketList.java +++ b/router/java/src/org/cybergarage/upnp/ssdp/SSDPSearchSocketList.java @@ -1,105 +1,151 @@ -/****************************************************************** -* -* CyberUPnP for Java -* -* Copyright (C) Satoshi Konno 2002-2003 +/****************************************************************** * -* File: SSDPSearchSocketList.java -* -* Revision; -* -* 05/08/03 -* - first revision. -* 05/28/03 -* - Moved post() for SSDPSearchRequest to SSDPResponseSocket. -* - Removed open(int). -* -******************************************************************/ +* CyberUPnP for Java +* +* Copyright (C) Satoshi Konno 2002-2003 +* +* File: SSDPSearchSocketList.java +* +* Revision; +* +* 05/08/03 +* - first revision. +* 05/28/03 +* - Moved post() for SSDPSearchRequest to SSDPResponseSocket. +* - Removed open(int). +* +******************************************************************/ + +package org.cybergarage.upnp.ssdp; + +import java.net.InetAddress; +import java.util.Vector; + +import org.cybergarage.net.HostInterface; +import org.cybergarage.upnp.device.SearchListener; + +public class SSDPSearchSocketList extends Vector +{ + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + private InetAddress[] binds = null; + private String multicastIPv4 = SSDP.ADDRESS; + private String multicastIPv6 = SSDP.getIPv6Address(); + private int port = SSDP.PORT; + + public SSDPSearchSocketList() + { + } + /** + * + * @param binds The IP address that we will used for bindind the service + */ + public SSDPSearchSocketList(InetAddress[] binds) { + this.binds = binds; + } + + /** + * + * @param binds The IP address that we will used for bindind the service + * @param port The port that we will used for bindind the service + * @param multicastIPv4 The IPv4 address that we will used for multicast comunication + * @param multicastIPv6 The IPv6 address that we will used for multicast comunication + * @since 1.8 + */ + public SSDPSearchSocketList(InetAddress[] binds,int port, String multicastIPv4, String multicastIPv6) { + this.binds = binds; + this.port = port; + this.multicastIPv4 = multicastIPv4; + this.multicastIPv6 = multicastIPv6; + } + + + + + //////////////////////////////////////////////// + // Methods + //////////////////////////////////////////////// + + public SSDPSearchSocket getSSDPSearchSocket(int n) + { + return (SSDPSearchSocket)get(n); + } + + public void addSearchListener(SearchListener listener) + { + int nServers = size(); + for (int n=0; nInetAddress that will be binded for listing this service. + * Use null for the default behaviur. + * @see {@link UPnP} + * @see {@link USSDP} + * @see {@link HostInterface} + * @since 1.8 + */ + public void setSSDPBindAddress(InetAddress[] inets){ + this.ssdpBinds=inets; + } + + /** + * + * @return inets The InetAddress that will be binded for this service + * null means that defulat behaviur will be used + * @since 1.8 + */ + public InetAddress[] getSSDPBindAddress(){ + return this.ssdpBinds; + } + + /** + * + * @param ip The IPv4 address used as destination address for Multicast comunication + * @since 1.8 + */ + public void setMulticastIPv4Address(String ip){ + this.ssdpMulticastIPv4=ip; + } + + /** + * + * @return The IPv4 address used for Multicast comunication + */ + public String getMulticastIPv4Address(){ + return this.ssdpMulticastIPv4; + } + + /** + * + * @param ip The IPv6 address used as destination address for Multicast comunication + * @since 1.8 + */ + public void setMulticastIPv6Address(String ip){ + this.ssdpMulticastIPv6=ip; + } + + /** + * + * @return The IPv6 address used as destination address for Multicast comunication + * @since 1.8 + */ + public String getMulticastIPv6Address(){ + return this.ssdpMulticastIPv6; + } + + //////////////////////////////////////////////// // SSDPPacket diff --git a/router/java/src/org/cybergarage/upnp/xml/ServiceData.java b/router/java/src/org/cybergarage/upnp/xml/ServiceData.java index bb4dfe979..5f5eeefda 100644 --- a/router/java/src/org/cybergarage/upnp/xml/ServiceData.java +++ b/router/java/src/org/cybergarage/upnp/xml/ServiceData.java @@ -68,6 +68,20 @@ public class ServiceData extends NodeData // SID //////////////////////////////////////////////// + private String descriptionURL = ""; + + public String getDescriptionURL() { + return descriptionURL; + } + + public void setDescriptionURL(String descriptionURL) { + this.descriptionURL = descriptionURL; + } + + //////////////////////////////////////////////// + // SID + //////////////////////////////////////////////// + private String sid = ""; public String getSID() { diff --git a/router/java/src/org/cybergarage/util/FileUtil.java b/router/java/src/org/cybergarage/util/FileUtil.java index bd287ddcc..5d14acd60 100644 --- a/router/java/src/org/cybergarage/util/FileUtil.java +++ b/router/java/src/org/cybergarage/util/FileUtil.java @@ -15,7 +15,9 @@ package org.cybergarage.util; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; import java.util.Locale; public final class FileUtil diff --git a/router/java/src/org/cybergarage/util/ListenerList.java b/router/java/src/org/cybergarage/util/ListenerList.java index b02c0ddc8..19f5901a1 100644 --- a/router/java/src/org/cybergarage/util/ListenerList.java +++ b/router/java/src/org/cybergarage/util/ListenerList.java @@ -3,7 +3,7 @@ * CyberUtil for Java * * Copyright (C) Satoshi Konno 2002 -* +* * File: ListenerList.java * * Revision; @@ -12,16 +12,13 @@ * - first revision. * ******************************************************************/ - + package org.cybergarage.util; -import java.util.*; - +import java.util.Vector; + public class ListenerList extends Vector { - private static final long serialVersionUID = 8039231561720446173L; - - @Override public boolean add(Object obj) { if (0 <= indexOf(obj)) diff --git a/router/java/src/org/cybergarage/util/Mutex.java b/router/java/src/org/cybergarage/util/Mutex.java index aa13afe62..f26351271 100644 --- a/router/java/src/org/cybergarage/util/Mutex.java +++ b/router/java/src/org/cybergarage/util/Mutex.java @@ -40,7 +40,7 @@ public class Mutex } catch (Exception e) { Debug.warning(e); - } + }; } syncLock = true; } diff --git a/router/java/src/org/cybergarage/util/ThreadCore.java b/router/java/src/org/cybergarage/util/ThreadCore.java index f2a49ddbe..5e9fd4598 100644 --- a/router/java/src/org/cybergarage/util/ThreadCore.java +++ b/router/java/src/org/cybergarage/util/ThreadCore.java @@ -10,6 +10,9 @@ * * 01/05/04 * - first revision. +* 08/23/07 +* - Thanks for Kazuyuki Shudo +* - Changed stop() to stop more safety using Thread::interrupt(). * ******************************************************************/ @@ -43,7 +46,7 @@ public class ThreadCore implements Runnable { java.lang.Thread threadObject = getThreadObject(); if (threadObject == null) { - threadObject = new java.lang.Thread(this); + threadObject = new java.lang.Thread(this,"Cyber.ThreadCore"); setThreadObject(threadObject); threadObject.start(); } @@ -64,6 +67,10 @@ public class ThreadCore implements Runnable if (threadObject != null) { //threadObject.destroy(); //threadObject.stop(); + + // Thanks for Kazuyuki Shudo (08/23/07) + threadObject.interrupt(); + setThreadObject(null); // I2P break Disposer out of sleep() threadObject.interrupt(); diff --git a/router/java/src/org/cybergarage/xml/AttributeList.java b/router/java/src/org/cybergarage/xml/AttributeList.java index 8bb85cd01..7a0e67091 100644 --- a/router/java/src/org/cybergarage/xml/AttributeList.java +++ b/router/java/src/org/cybergarage/xml/AttributeList.java @@ -15,12 +15,10 @@ package org.cybergarage.xml; -import java.util.*; +import java.util.Vector; public class AttributeList extends Vector { - private static final long serialVersionUID = -5516389508555401104L; - public AttributeList() { } diff --git a/router/java/src/org/cybergarage/xml/Node.java b/router/java/src/org/cybergarage/xml/Node.java index 4fee0fdee..7e34a084f 100644 --- a/router/java/src/org/cybergarage/xml/Node.java +++ b/router/java/src/org/cybergarage/xml/Node.java @@ -1,415 +1,468 @@ -/****************************************************************** -* -* CyberXML for Java -* -* Copyright (C) Satoshi Konno 2002 -* -* File: Element.java -* -* Revision; -* -* 11/27/02 -* - first revision. -* 11/01/03 -* - Terje Bakken -* - fixed missing escaping of reserved XML characters -* 11/19/04 -* - Theo Beisch -* - Added "&" and "\"" "\\" to toXMLString(). -* 11/19/04 -* - Theo Beisch -* - Changed XML::output() to use short notation when the tag value is null. -* 12/02/04 -* - Brian Owens -* - Fixed toXMLString() to convert from "'" to "'" instead of "\". -* -******************************************************************/ - -package org.cybergarage.xml; - -import java.io.ByteArrayOutputStream; -import java.io.PrintWriter; - -public class Node -{ - - public Node() - { - setUserData(null); - setParentNode(null); - } - - public Node(String name) - { - this(); - setName(name); - } - - public Node(String ns, String name) - { - this(); - setName(ns, name); - } - - //////////////////////////////////////////////// - // parent node - //////////////////////////////////////////////// - - private Node parentNode = null; - - public void setParentNode(Node node) - { - parentNode = node; - } - - public Node getParentNode() - { - return parentNode; - } - - //////////////////////////////////////////////// - // root node - //////////////////////////////////////////////// - - public Node getRootNode() - { - Node rootNode = null; - Node _parentNode = getParentNode(); - while (_parentNode != null) { - rootNode = _parentNode; - _parentNode = rootNode.getParentNode(); - } - return rootNode; - } - - //////////////////////////////////////////////// - // name - //////////////////////////////////////////////// - - private String name = new String(); - - public void setName(String name) - { - this.name = name; - } - - public void setName(String ns, String name) - { - this.name = ns + ":" + name; - } - - public String getName() - { - return name; - } - - public boolean isName(String value) - { - return name.equals(value); - } - - //////////////////////////////////////////////// - // value - //////////////////////////////////////////////// - - private String value = ""; - - public void setValue(String value) - { - this.value = value; - } - - public void setValue(int value) - { - setValue(Integer.toString(value)); - } - - public String getValue() - { - return value; - } - - //////////////////////////////////////////////// - // Attribute (Basic) - //////////////////////////////////////////////// - - private AttributeList attrList = new AttributeList(); - - public int getNAttributes() { - return attrList.size(); - } - - public Attribute getAttribute(int index) { - return attrList.getAttribute(index); - } - - public Attribute getAttribute(String name) - { - return attrList.getAttribute(name); - } - - public void addAttribute(Attribute attr) { - attrList.add(attr); - } - - public void insertAttributeAt(Attribute attr, int index) { - attrList.insertElementAt(attr, index); - } - - public void addAttribute(String name, String value) { - Attribute attr = new Attribute(name, value); - addAttribute(attr); - } - - public boolean removeAttribute(Attribute attr) { - return attrList.remove(attr); - } - - public boolean removeAttribute(String name) { - return removeAttribute(getAttribute(name)); - } - - public boolean hasAttributes() - { - if (0 < getNAttributes()) - return true; - return false; - } - - //////////////////////////////////////////////// - // Attribute (Extention) - //////////////////////////////////////////////// - - public void setAttribute(String name, String value) { - Attribute attr = getAttribute(name); - if (attr != null) { - attr.setValue(value); - return; - } - attr = new Attribute(name, value); - addAttribute(attr); - } - - public void setAttribute(String name, int value) { - setAttribute(name, Integer.toString(value)); - } - - public String getAttributeValue(String name) { - Attribute attr = getAttribute(name); - if (attr != null) - return attr.getValue(); - return ""; - } - - public int getAttributeIntegerValue(String name) { - String val = getAttributeValue(name); - try { - return Integer.parseInt(val); - } - catch (Exception e) {} - return 0; - } - - //////////////////////////////////////////////// - // Attribute (xmlns) - //////////////////////////////////////////////// - - public void setNameSpace(String ns, String value) - { - setAttribute("xmlns:" + ns, value); - } - - //////////////////////////////////////////////// - // Child node - //////////////////////////////////////////////// - - private NodeList nodeList = new NodeList(); - - public int getNNodes() { - return nodeList.size(); - } - - public Node getNode(int index) { - return nodeList.getNode(index); - } - - public Node getNode(String name) - { - return nodeList.getNode(name); - } - - public Node getNodeEndsWith(String name) - { - return nodeList.getEndsWith(name); - } - - public void addNode(Node node) { - node.setParentNode(this); - nodeList.add(node); - } - - public void insertNode(Node node, int index) { - node.setParentNode(this); - nodeList.insertElementAt(node, index); - } - - public boolean removeNode(Node node) { - node.setParentNode(null); - return nodeList.remove(node); - } - - public boolean removeNode(String name) { - return nodeList.remove(getNode(name)); - } - - public void removeAllNodes() - { - nodeList.clear(); - } - - public boolean hasNodes() - { - if (0 < getNNodes()) - return true; - return false; - } - - //////////////////////////////////////////////// - // Element (Child Node) - //////////////////////////////////////////////// - - public void setNode(String name, String value) { - Node node = getNode(name); - if (node != null) { - node.setValue(value); - return; - } - node = new Node(name); - node.setValue(value); - addNode(node); - } - - public String getNodeValue(String name) { - Node node = getNode(name); - if (node != null) - return node.getValue(); - return ""; - } - - //////////////////////////////////////////////// - // userData - //////////////////////////////////////////////// - - private Object userData = null; - - public void setUserData(Object data) - { - userData = data; - } - - public Object getUserData() - { - return userData; - } - - - //////////////////////////////////////////////// - // toString - //////////////////////////////////////////////// - - public String getIndentLevelString(int nIndentLevel) - { - char indentString[] = new char[nIndentLevel]; - for (int n=0; n - ps.println(" />"); - } else { - ps.println(">" + XML.escapeXMLChars(_value) + ""); - } - - return; - } - - ps.print(indentString + "<" + _name); - outputAttributes(ps); - ps.println(">"); - - int nChildNodes = getNNodes(); - for (int n=0; n"); - } - - public String toString(boolean hasChildNode) - { - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - PrintWriter pr = new PrintWriter(byteOut); - output(pr, 0, hasChildNode); - pr.flush(); - return byteOut.toString(); - } - - @Override - public String toString() - { - return toString(true); - } - - public String toXMLString(boolean hasChildNode) - { - String xmlStr = toString(); - xmlStr = xmlStr.replaceAll("<", "<"); - xmlStr = xmlStr.replaceAll(">", ">"); - // Thanks for Theo Beisch (11/09/04) - xmlStr = xmlStr.replaceAll("&", "&"); - xmlStr = xmlStr.replaceAll("\"", """); - // Thanks for Brian Owens (12/02/04) - xmlStr = xmlStr.replaceAll("'", "'"); - return xmlStr; - } - - public String toXMLString() - { - return toXMLString(true); - } - - public void print(boolean hasChildNode) - { - PrintWriter pr = new PrintWriter(System.out); - output(pr, 0, hasChildNode); - pr.flush(); - } - - public void print() - { - print(true); - } -} +/****************************************************************** +* +* CyberXML for Java +* +* Copyright (C) Satoshi Konno 2002 +* +* File: Element.java +* +* Revision; +* +* 11/27/02 +* - first revision. +* 11/01/03 +* - Terje Bakken +* - fixed missing escaping of reserved XML characters +* 11/19/04 +* - Theo Beisch +* - Added "&" and "\"" "\\" to toXMLString(). +* 11/19/04 +* - Theo Beisch +* - Changed XML::output() to use short notation when the tag value is null. +* 12/02/04 +* - Brian Owens +* - Fixed toXMLString() to convert from "'" to "'" instead of "\". +* 11/07/05 +* - Changed toString() to return as utf-8 string. +* 02/08/08 +* - Added addValue(). +* +******************************************************************/ + +package org.cybergarage.xml; + +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.Iterator; + +public class Node +{ + + /** + * Create a Node with empty UserData and no Parent Node + * + */ + public Node() + { + setUserData(null); + setParentNode(null); + } + + public Node(String name) + { + this(); + setName(name); + } + + public Node(String ns, String name) + { + this(); + setName(ns, name); + } + + //////////////////////////////////////////////// + // parent node + //////////////////////////////////////////////// + + private Node parentNode = null; + + public void setParentNode(Node node) + { + parentNode = node; + } + + public Node getParentNode() + { + return parentNode; + } + + //////////////////////////////////////////////// + // root node + //////////////////////////////////////////////// + + public Node getRootNode() + { + Node rootNode = null; + Node parentNode = getParentNode(); + while (parentNode != null) { + rootNode = parentNode; + parentNode = rootNode.getParentNode(); + } + return rootNode; + } + + //////////////////////////////////////////////// + // name + //////////////////////////////////////////////// + + private String name = new String(); + + public void setName(String name) + { + this.name = name; + } + + public void setName(String ns, String name) + { + this.name = ns + ":" + name; + } + + public String getName() + { + return name; + } + + public boolean isName(String value) + { + return name.equals(value); + } + + //////////////////////////////////////////////// + // value + //////////////////////////////////////////////// + + private String value = new String(); + + public void setValue(String value) + { + this.value = value; + } + + public void setValue(int value) + { + setValue(Integer.toString(value)); + } + + public void addValue(String value) + { + if (this.value == null) { + this.value = value; + return; + } + if (value != null) + this.value += value; + } + + public String getValue() + { + return value; + } + + //////////////////////////////////////////////// + // Attribute (Basic) + //////////////////////////////////////////////// + + private AttributeList attrList = new AttributeList(); + + public int getNAttributes() { + return attrList.size(); + } + + public Attribute getAttribute(int index) { + return attrList.getAttribute(index); + } + + public Attribute getAttribute(String name) + { + return attrList.getAttribute(name); + } + + public void addAttribute(Attribute attr) { + attrList.add(attr); + } + + public void insertAttributeAt(Attribute attr, int index) { + attrList.insertElementAt(attr, index); + } + + public void addAttribute(String name, String value) { + Attribute attr = new Attribute(name, value); + addAttribute(attr); + } + + public boolean removeAttribute(Attribute attr) { + return attrList.remove(attr); + } + + public boolean removeAttribute(String name) { + return removeAttribute(getAttribute(name)); + } + + public boolean hasAttributes() + { + if (0 < getNAttributes()) + return true; + return false; + } + + //////////////////////////////////////////////// + // Attribute (Extention) + //////////////////////////////////////////////// + + public void setAttribute(String name, String value) { + Attribute attr = getAttribute(name); + if (attr != null) { + attr.setValue(value); + return; + } + attr = new Attribute(name, value); + addAttribute(attr); + } + + public void setAttribute(String name, int value) { + setAttribute(name, Integer.toString(value)); + } + + public String getAttributeValue(String name) { + Attribute attr = getAttribute(name); + if (attr != null) + return attr.getValue(); + return ""; + } + + public int getAttributeIntegerValue(String name) { + String val = getAttributeValue(name); + try { + return Integer.parseInt(val); + } + catch (Exception e) {} + return 0; + } + + //////////////////////////////////////////////// + // Attribute (xmlns) + //////////////////////////////////////////////// + + public void setNameSpace(String ns, String value) + { + setAttribute("xmlns:" + ns, value); + } + + //////////////////////////////////////////////// + // Child node + //////////////////////////////////////////////// + + private NodeList nodeList = new NodeList(); + + public int getNNodes() { + return nodeList.size(); + } + + public Node getNode(int index) { + return nodeList.getNode(index); + } + + public Node getNode(String name) + { + return nodeList.getNode(name); + } + + public Node getNodeEndsWith(String name) + { + return nodeList.getEndsWith(name); + } + + public void addNode(Node node) { + node.setParentNode(this); + nodeList.add(node); + } + + public void insertNode(Node node, int index) { + node.setParentNode(this); + nodeList.insertElementAt(node, index); + } + + public int getIndex(String name){ + int index = -1; + for (Iterator i = nodeList.iterator(); i.hasNext();) { + index++; + Node n = (Node) i.next(); + if(n.getName().equals(name)) + return index; + } + return index; + } + + public boolean removeNode(Node node) { + node.setParentNode(null); + return nodeList.remove(node); + } + + public boolean removeNode(String name) { + return nodeList.remove(getNode(name)); + } + + public void removeAllNodes() + { + nodeList.clear(); + } + + public boolean hasNodes() + { + if (0 < getNNodes()) + return true; + return false; + } + + //////////////////////////////////////////////// + // Element (Child Node) + //////////////////////////////////////////////// + + public void setNode(String name, String value) { + Node node = getNode(name); + if (node != null) { + node.setValue(value); + return; + } + node = new Node(name); + node.setValue(value); + addNode(node); + } + + public String getNodeValue(String name) { + Node node = getNode(name); + if (node != null) + return node.getValue(); + return ""; + } + + //////////////////////////////////////////////// + // userData + //////////////////////////////////////////////// + + private Object userData = null; + + public void setUserData(Object data) + { + userData = data; + } + + public Object getUserData() + { + return userData; + } + + //////////////////////////////////////////////// + // toString + //////////////////////////////////////////////// + + /** + * Inovoke {@link #getIndentLevelString(int, String)} with " " as String + * + * @see #getIndentLevelString(int, String) + */ + public String getIndentLevelString(int nIndentLevel) + { + return getIndentLevelString(nIndentLevel," "); + } + + /** + * + * @param nIndentLevel the level of indentation to produce + * @param space the String to use for the intendation + * @since 1.8.0 + * @return an indentation String + */ + public String getIndentLevelString(int nIndentLevel,String space) + { + StringBuffer indentString = new StringBuffer(nIndentLevel*space.length()); + for (int n=0; n because it cause compatibility trouble + ps.println(">"); + } else { + ps.println(">" + XML.escapeXMLChars(value) + ""); + } + + return; + } + + ps.print(indentString + "<" + name); + outputAttributes(ps); + ps.println(">"); + + int nChildNodes = getNNodes(); + for (int n=0; n"); + } + + public String toString(String enc, boolean hasChildNode) + { + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + PrintWriter pr = new PrintWriter(byteOut); + output(pr, 0, hasChildNode); + pr.flush(); + try { + if (enc != null && 0 < enc.length()) + return byteOut.toString(enc); + } + catch (UnsupportedEncodingException e) { + } + return byteOut.toString(); + } + + public String toString() + { + return toString(XML.CHARSET_UTF8, true); + } + + public String toXMLString(boolean hasChildNode) + { + String xmlStr = toString(); + xmlStr = xmlStr.replaceAll("<", "<"); + xmlStr = xmlStr.replaceAll(">", ">"); + // Thanks for Theo Beisch (11/09/04) + xmlStr = xmlStr.replaceAll("&", "&"); + xmlStr = xmlStr.replaceAll("\"", """); + // Thanks for Brian Owens (12/02/04) + xmlStr = xmlStr.replaceAll("'", "'"); + return xmlStr; + } + + public String toXMLString() + { + return toXMLString(true); + } + + public void print(boolean hasChildNode) + { + PrintWriter pr = new PrintWriter(System.out); + output(pr, 0, hasChildNode); + pr.flush(); + } + + public void print() + { + print(true); + } +} diff --git a/router/java/src/org/cybergarage/xml/NodeList.java b/router/java/src/org/cybergarage/xml/NodeList.java index 53ac9bce8..806b6f22c 100644 --- a/router/java/src/org/cybergarage/xml/NodeList.java +++ b/router/java/src/org/cybergarage/xml/NodeList.java @@ -15,12 +15,10 @@ package org.cybergarage.xml; -import java.util.*; +import java.util.Vector; public class NodeList extends Vector { - private static final long serialVersionUID = 1528884682346143213L; - public NodeList() { } diff --git a/router/java/src/org/cybergarage/xml/Parser.java b/router/java/src/org/cybergarage/xml/Parser.java index 0268f3e29..6d4d69ac7 100644 --- a/router/java/src/org/cybergarage/xml/Parser.java +++ b/router/java/src/org/cybergarage/xml/Parser.java @@ -1,117 +1,128 @@ -/****************************************************************** -* -* CyberXML for Java -* -* Copyright (C) Satoshi Konno 2002 -* -* File: Parser.java -* -* Revision; -* -* 11/26/03 -* - first revision. -* 03/30/05 -* - Change parse(String) to use StringBufferInputStream instead of URL. -* -******************************************************************/ - -package org.cybergarage.xml; - -import java.net.*; -import java.io.*; - -public abstract class Parser -{ - //////////////////////////////////////////////// - // Constructor - //////////////////////////////////////////////// - - public Parser() - { - } - - //////////////////////////////////////////////// - // parse - //////////////////////////////////////////////// - - public abstract Node parse(InputStream inStream) throws ParserException; - - //////////////////////////////////////////////// - // parse (URL) - //////////////////////////////////////////////// - - public Node parse(URL locationURL) throws ParserException - { - try { - HttpURLConnection urlCon = (HttpURLConnection)locationURL.openConnection(); - // I2P mods to prevent hangs (see HTTPRequest for more info) - // this seems to work, getInputStream actually does the connect(), - // (as shown by a thread dump) - // so we can set these after openConnection() - // Alternative would be foo = new HttpURLConnection(locationURL); foo.set timeouts; foo.connect() - urlCon.setConnectTimeout(2*1000); - urlCon.setReadTimeout(1000); - urlCon.setRequestMethod("GET"); - InputStream urlIn = urlCon.getInputStream(); - - Node rootElem = parse(urlIn); - - urlIn.close(); - urlCon.disconnect(); - - return rootElem; - - } catch (Exception e) { - throw new ParserException(e); - } - /* - String host = locationURL.getHost(); - int port = locationURL.getPort(); - String uri = locationURL.getPath(); - HTTPRequest httpReq = new HTTPRequest(); - httpReq.setMethod(HTTP.GET); - httpReq.setURI(uri); - HTTPResponse httpRes = httpReq.post(host, port); - if (httpRes.isSuccessful() == false) - throw new ParserException(locationURL.toString()); - String content = new String(httpRes.getContent()); - StringBufferInputStream strBuf = new StringBufferInputStream(content); - return parse(strBuf); - */ - } - - //////////////////////////////////////////////// - // parse (File) - //////////////////////////////////////////////// - - public Node parse(File descriptionFile) throws ParserException - { - try { - InputStream fileIn = new FileInputStream(descriptionFile); - Node root = parse(fileIn); - fileIn.close(); - return root; - - } catch (Exception e) { - throw new ParserException(e); - } - } - - //////////////////////////////////////////////// - // parse (Memory) - //////////////////////////////////////////////// - - public Node parse(String descr) throws ParserException - { - try { - InputStream decrIn = new ByteArrayInputStream(descr.getBytes()); - Node root = parse(decrIn); - return root; - } catch (Exception e) { - throw new ParserException(e); - } - } - -} - - +/****************************************************************** +* +* CyberXML for Java +* +* Copyright (C) Satoshi Konno 2002 +* +* File: Parser.java +* +* Revision; +* +* 11/26/2003 +* - first revision. +* 03/30/2005 +* - Change parse(String) to use StringBufferInputStream instead of URL. +* 11/11/2009 +* - Changed Parser::parser() to use ByteArrayInputStream instead of StringBufferInputStream because of bugs in Android v1.6. +* +******************************************************************/ + +package org.cybergarage.xml; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.cybergarage.http.HTTP; +import org.cybergarage.http.HTTPRequest; +import org.cybergarage.http.HTTPResponse; + +public abstract class Parser +{ + //////////////////////////////////////////////// + // Constructor + //////////////////////////////////////////////// + + public Parser() + { + } + + //////////////////////////////////////////////// + // parse + //////////////////////////////////////////////// + + public abstract Node parse(InputStream inStream) throws ParserException; + + //////////////////////////////////////////////// + // parse (URL) + //////////////////////////////////////////////// + + public Node parse(URL locationURL) throws ParserException + { + String host = locationURL.getHost(); + int port = locationURL.getPort(); + // Thanks for Hao Hu + if (port == -1) + port = 80; + String uri = locationURL.getPath(); + + try { + HttpURLConnection urlCon = (HttpURLConnection)locationURL.openConnection(); + urlCon.setRequestMethod("GET"); + urlCon.setRequestProperty(HTTP.CONTENT_LENGTH,"0"); + if (host != null) + urlCon.setRequestProperty(HTTP.HOST, host); + + InputStream urlIn = urlCon.getInputStream(); + + Node rootElem = parse(urlIn); + + urlIn.close(); + urlCon.disconnect(); + + return rootElem; + + } catch (Exception e) { + //throw new ParserException(e); + } + + HTTPRequest httpReq = new HTTPRequest(); + httpReq.setMethod(HTTP.GET); + httpReq.setURI(uri); + HTTPResponse httpRes = httpReq.post(host, port); + if (httpRes.isSuccessful() == false) + throw new ParserException("HTTP comunication failed: no answer from peer." + + "Unable to retrive resoure -> "+locationURL.toString()); + String content = new String(httpRes.getContent()); + ByteArrayInputStream strBuf = new ByteArrayInputStream(content.getBytes()); + return parse(strBuf); + } + + //////////////////////////////////////////////// + // parse (File) + //////////////////////////////////////////////// + + public Node parse(File descriptionFile) throws ParserException + { + try { + InputStream fileIn = new FileInputStream(descriptionFile); + Node root = parse(fileIn); + fileIn.close(); + return root; + + } catch (Exception e) { + throw new ParserException(e); + } + } + + //////////////////////////////////////////////// + // parse (Memory) + //////////////////////////////////////////////// + + public Node parse(String descr) throws ParserException + { + try { + InputStream decrIn = new ByteArrayInputStream(descr.getBytes()); + Node root = parse(decrIn); + return root; + } catch (Exception e) { + throw new ParserException(e); + } + } + +} + + diff --git a/router/java/src/org/cybergarage/xml/ParserException.java b/router/java/src/org/cybergarage/xml/ParserException.java index eba4f6793..87f1553e6 100644 --- a/router/java/src/org/cybergarage/xml/ParserException.java +++ b/router/java/src/org/cybergarage/xml/ParserException.java @@ -19,8 +19,6 @@ package org.cybergarage.xml; public class ParserException extends Exception { - private static final long serialVersionUID = 7443033796560597360L; - public ParserException(Exception e) { super(e); diff --git a/router/java/src/org/cybergarage/xml/XML.java b/router/java/src/org/cybergarage/xml/XML.java index 9f62cb9d7..ce170358c 100644 --- a/router/java/src/org/cybergarage/xml/XML.java +++ b/router/java/src/org/cybergarage/xml/XML.java @@ -21,6 +21,7 @@ package org.cybergarage.xml; public class XML { public final static String CONTENT_TYPE = "text/xml; charset=\"utf-8\""; + public final static String CHARSET_UTF8 = "utf-8"; //////////////////////////////////////////////// // escapeXMLChars @@ -28,9 +29,9 @@ public class XML private final static String escapeXMLChars(String input, boolean quote) { - StringBuilder out = new StringBuilder(); if (input == null) return null; + StringBuffer out = new StringBuffer(); int oldsize=input.length(); char[] old=new char[oldsize]; input.getChars(0,oldsize,old,0); @@ -61,5 +62,25 @@ public class XML { return escapeXMLChars(input, true); } + + //////////////////////////////////////////////// + // unescapeXMLChars + //////////////////////////////////////////////// + + public final static String unescapeXMLChars(String input) + { + if (input == null) + return null; + + String outStr; + + outStr = input.replace("&", "&"); + outStr = outStr.replace("<", "<"); + outStr = outStr.replace(">", ">"); + outStr = outStr.replace("'", "\'"); + outStr = outStr.replace(""", "\""); + + return outStr; + } } diff --git a/router/java/src/org/cybergarage/xml/parser/JaxpParser.java b/router/java/src/org/cybergarage/xml/parser/JaxpParser.java index 7b220ef0c..139f59f48 100644 --- a/router/java/src/org/cybergarage/xml/parser/JaxpParser.java +++ b/router/java/src/org/cybergarage/xml/parser/JaxpParser.java @@ -12,6 +12,10 @@ * * 06/15/04 * - first revision. +* 01/08/08 +* - Fixed parse() not to occur null exception when the NamedNodeMap is null on Android. +* 02/08/08 +* - Change parse() to use Node::addValue() instead of the setValue(). * ******************************************************************/ @@ -52,11 +56,15 @@ public class JaxpParser extends Parser String domNodeName = domNode.getNodeName(); String domNodeValue = domNode.getNodeValue(); + NamedNodeMap attrs = domNode.getAttributes(); + int arrrsLen = (attrs != null) ? attrs.getLength() : 0; // Debug.message("[" + rank + "] ELEM : " + domNodeName + ", " + domNodeValue + ", type = " + domNodeType + ", attrs = " + arrrsLen); if (domNodeType == org.w3c.dom.Node.TEXT_NODE) { - parentNode.setValue(domNodeValue); + // Change to use Node::addValue() instead of the setValue(). (2008/02/07) + //parentNode.setValue(domNodeValue); + parentNode.addValue(domNodeValue); return parentNode; } @@ -71,20 +79,26 @@ public class JaxpParser extends Parser parentNode.addNode(node); NamedNodeMap attrMap = domNode.getAttributes(); - int attrLen = attrMap.getLength(); - //Debug.message("attrLen = " + attrLen); - for (int n = 0; n