forked from I2P_Developers/i2p.i2p
merge of 'c5e201203713f0fefcdef642ca50597f8936c79c'
and 'fbd68f812db1e891f96e212b3a5938beec0233b5'
This commit is contained in:
@@ -21,6 +21,7 @@ package org.cybergarage.http;
|
||||
import java.io.IOException;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.cybergarage.util.Debug;
|
||||
|
||||
@@ -88,7 +89,7 @@ public class HTTPHeader
|
||||
|
||||
public final static String getValue(LineNumberReader reader, String name)
|
||||
{
|
||||
String bigName = name.toUpperCase();
|
||||
String bigName = name.toUpperCase(Locale.US);
|
||||
try {
|
||||
String lineStr = reader.readLine();
|
||||
while (lineStr != null && 0 < lineStr.length()) {
|
||||
@@ -97,7 +98,7 @@ public class HTTPHeader
|
||||
lineStr = reader.readLine();
|
||||
continue;
|
||||
}
|
||||
String bigLineHeaderName = header.getName().toUpperCase();
|
||||
String bigLineHeaderName = header.getName().toUpperCase(Locale.US);
|
||||
// Thanks for Jan Newmarch <jan.newmarch@infotech.monash.edu.au> (05/26/04)
|
||||
if (bigLineHeaderName.equals(bigName) == false) {
|
||||
lineStr = reader.readLine();
|
||||
|
||||
@@ -59,6 +59,7 @@ 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;
|
||||
@@ -401,11 +402,21 @@ public class HTTPRequest extends HTTPPacket
|
||||
InputStream in = null;
|
||||
|
||||
try {
|
||||
if (postSocket == null){
|
||||
// Thanks for Hao Hu
|
||||
if (postSocket == null) {
|
||||
// Mod for I2P
|
||||
// We can't handle the default system soTimeout of 3 minutes or so
|
||||
// as when the device goes away, this hangs the display of peers.jsp
|
||||
// and who knows what else.
|
||||
// Set the timeout to be nice and short, the device should be local and fast.
|
||||
// Yeah, the UPnP standard is a minute or something, too bad.
|
||||
// If he can't get back to us in a few seconds, forget it.
|
||||
// And set the soTimeout to 2 second (for reads).
|
||||
//postSocket = new Socket(host, port);
|
||||
postSocket = new Socket();
|
||||
postSocket.connect(new InetSocketAddress(host, port), HTTPServer.DEFAULT_TIMEOUT);
|
||||
}
|
||||
postSocket.setSoTimeout(2000);
|
||||
SocketAddress sa = new InetSocketAddress(host, port);
|
||||
postSocket.connect(sa, 3000);
|
||||
}
|
||||
|
||||
out = postSocket.getOutputStream();
|
||||
PrintStream pout = new PrintStream(out);
|
||||
@@ -522,6 +533,6 @@ public class HTTPRequest extends HTTPPacket
|
||||
|
||||
public void print()
|
||||
{
|
||||
System.out.println(toString());
|
||||
Debug.message(toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package org.cybergarage.http;
|
||||
|
||||
import java.io.InputStream;
|
||||
import org.cybergarage.util.Debug;
|
||||
|
||||
public class HTTPResponse extends HTTPPacket
|
||||
{
|
||||
@@ -111,6 +112,6 @@ public class HTTPResponse extends HTTPPacket
|
||||
|
||||
public void print()
|
||||
{
|
||||
System.out.println(toString());
|
||||
Debug.message(toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,9 @@ public class HTTPServer implements Runnable
|
||||
* Default timeout connection for HTTP comunication
|
||||
* @since 1.8
|
||||
*/
|
||||
public final static int DEFAULT_TIMEOUT = DEFAULT_PORT * 1000;
|
||||
// I2P fix
|
||||
//public final static int DEFAULT_TIMEOUT = DEFAULT_PORT * 1000;
|
||||
public final static int DEFAULT_TIMEOUT = 10 * 1000;
|
||||
|
||||
public static String getName()
|
||||
{
|
||||
@@ -147,6 +149,7 @@ public class HTTPServer implements Runnable
|
||||
serverSock = new ServerSocket(bindPort, 0, bindAddr);
|
||||
}
|
||||
catch (IOException e) {
|
||||
Debug.warning("HTTP server open failed " + addr + " " + port, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -247,7 +250,8 @@ public class HTTPServer implements Runnable
|
||||
|
||||
public boolean start(){
|
||||
StringBuffer name = new StringBuffer("Cyber.HTTPServer/");
|
||||
name.append(serverSock.getLocalSocketAddress());
|
||||
// I2P hide address from thread dumps
|
||||
//name.append(serverSock.getLocalSocketAddress());
|
||||
httpServerThread = new Thread(this,name.toString());
|
||||
httpServerThread.start();
|
||||
return true;
|
||||
|
||||
@@ -401,7 +401,7 @@ public class Action
|
||||
|
||||
public void print()
|
||||
{
|
||||
System.out.println("Action : " + getName());
|
||||
Debug.message("Action : " + getName());
|
||||
ArgumentList argList = getArgumentList();
|
||||
int nArgs = argList.size();
|
||||
for (int n=0; n<nArgs; n++) {
|
||||
@@ -409,7 +409,7 @@ public class Action
|
||||
String name = arg.getName();
|
||||
String value = arg.getValue();
|
||||
String dir = arg.getDirection();
|
||||
System.out.println(" [" + n + "] = " + dir + ", " + name + ", " + value);
|
||||
Debug.message(" [" + n + "] = " + dir + ", " + name + ", " + value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -257,6 +257,7 @@ public class ControlPoint implements HTTPRequestListener
|
||||
if (rootDev == null)
|
||||
return;
|
||||
rootDev.setSSDPPacket(ssdpPacket);
|
||||
Debug.warning("Add root device", new Exception("received on " + ssdpPacket.getLocalAddress()));
|
||||
addDevice(rootNode);
|
||||
|
||||
// Thanks for Oliver Newell (2004/10/16)
|
||||
@@ -293,18 +294,25 @@ public class ControlPoint implements HTTPRequestListener
|
||||
for (int n=0; n<nRoots; n++) {
|
||||
Node rootNode = devNodeList.getNode(n);
|
||||
Device dev = getDevice(rootNode);
|
||||
if (dev == null)
|
||||
continue;
|
||||
devList.add(dev);
|
||||
}
|
||||
return devList;
|
||||
}
|
||||
|
||||
public Device getDevice(String name)
|
||||
{
|
||||
int nRoots = devNodeList.size();
|
||||
for (int n=0; n<nRoots; n++) {
|
||||
Node rootNode = devNodeList.getNode(n);
|
||||
if (dev == null)
|
||||
continue;
|
||||
devList.add(dev);
|
||||
}
|
||||
return devList;
|
||||
}
|
||||
|
||||
public Device getDevice(String name)
|
||||
{
|
||||
int nRoots = devNodeList.size();
|
||||
for (int n=0; n<nRoots; n++) {
|
||||
// AIOOB was thrown from here, maybe would be better to
|
||||
// copy the list before traversal?
|
||||
Node rootNode;
|
||||
try {
|
||||
rootNode = devNodeList.getNode(n);
|
||||
} catch (ArrayIndexOutOfBoundsException aioob) {
|
||||
break;
|
||||
}
|
||||
Device dev = getDevice(rootNode);
|
||||
if (dev == null)
|
||||
continue;
|
||||
@@ -825,9 +833,13 @@ public class ControlPoint implements HTTPRequestListener
|
||||
HTTPServerList httpServerList = getHTTPServerList();
|
||||
while (httpServerList.open(bindPort) == false) {
|
||||
retryCnt++;
|
||||
if (UPnP.SERVER_RETRY_COUNT < retryCnt)
|
||||
if (UPnP.SERVER_RETRY_COUNT < retryCnt) {
|
||||
Debug.warning("Failed to open HTTP event listener port " + bindPort);
|
||||
// I2P do we really need this, or can we just break ?
|
||||
return false;
|
||||
setHTTPPort(bindPort + 1);
|
||||
}
|
||||
// I2P go down not up so we don't run into other I2P things
|
||||
setHTTPPort(bindPort - 1);
|
||||
bindPort = getHTTPPort();
|
||||
}
|
||||
httpServerList.addRequestListener(this);
|
||||
@@ -838,8 +850,10 @@ public class ControlPoint implements HTTPRequestListener
|
||||
////////////////////////////////////////
|
||||
|
||||
SSDPNotifySocketList ssdpNotifySocketList = getSSDPNotifySocketList();
|
||||
if (ssdpNotifySocketList.open() == false)
|
||||
if (ssdpNotifySocketList.open() == false) {
|
||||
Debug.warning("Failed to open SSDP notify port 1900");
|
||||
return false;
|
||||
}
|
||||
ssdpNotifySocketList.setControlPoint(this);
|
||||
ssdpNotifySocketList.start();
|
||||
|
||||
@@ -852,9 +866,12 @@ public class ControlPoint implements HTTPRequestListener
|
||||
SSDPSearchResponseSocketList ssdpSearchResponseSocketList = getSSDPSearchResponseSocketList();
|
||||
while (ssdpSearchResponseSocketList.open(ssdpPort) == false) {
|
||||
retryCnt++;
|
||||
if (UPnP.SERVER_RETRY_COUNT < retryCnt)
|
||||
if (UPnP.SERVER_RETRY_COUNT < retryCnt) {
|
||||
Debug.warning("Failed to open SSDP search response port " + ssdpPort);
|
||||
return false;
|
||||
setSSDPPort(ssdpPort + 1);
|
||||
}
|
||||
// I2P go down not up so we don't run into other I2P things
|
||||
setSSDPPort(ssdpPort - 1);
|
||||
ssdpPort = getSSDPPort();
|
||||
}
|
||||
ssdpSearchResponseSocketList.setControlPoint(this);
|
||||
@@ -936,6 +953,12 @@ public class ControlPoint implements HTTPRequestListener
|
||||
setRenewSubscriber(null);
|
||||
}
|
||||
|
||||
// I2P so we will re-notify on restart
|
||||
DeviceList dl = getDeviceList();
|
||||
for (int i = 0; i < dl.size(); i++) {
|
||||
removeDevice(dl.getDevice(i));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,8 @@ public class UPnP
|
||||
public final static String NAME = "CyberLinkJava";
|
||||
public final static String VERSION = "3.0";
|
||||
|
||||
public final static int SERVER_RETRY_COUNT = 100;
|
||||
// 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()
|
||||
|
||||
@@ -51,6 +51,7 @@ public class Disposer extends ThreadCore
|
||||
|
||||
public void run()
|
||||
{
|
||||
Thread.currentThread().setName("UPnP-Disposer");
|
||||
ControlPoint ctrlp = getControlPoint();
|
||||
long monitorInterval = ctrlp.getExpiredDeviceMonitoringInterval() * 1000;
|
||||
|
||||
|
||||
@@ -188,6 +188,10 @@ public class NotifyRequest extends SOAPRequest
|
||||
public PropertyList getPropertyList() {
|
||||
PropertyList properties = new PropertyList();
|
||||
Node varSetNode = getEnvelopeNode();
|
||||
// I2P change: ParserException caught in getRootNode() causes
|
||||
// getEnvelopeNode() to return null
|
||||
if (varSetNode == null)
|
||||
return properties;
|
||||
for (int i = 0; i<varSetNode.getNNodes(); i++){
|
||||
Node propNode = varSetNode.getNode(i);
|
||||
if (propNode == null)
|
||||
@@ -198,4 +202,4 @@ public class NotifyRequest extends SOAPRequest
|
||||
return properties;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +219,7 @@ public class HTTPUSocket
|
||||
try {
|
||||
ssdpUniSock.receive(recvPacket.getDatagramPacket());
|
||||
recvPacket.setTimeStamp(System.currentTimeMillis());
|
||||
Debug.message("Received SSDP unicast packet on " + getLocalAddress() + " from " + recvPacket.getRemoteAddress());
|
||||
}
|
||||
catch (Exception e) {
|
||||
//Debug.warning(e);
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.cybergarage.net.*;
|
||||
import org.cybergarage.util.*;
|
||||
import org.cybergarage.http.*;
|
||||
import org.cybergarage.upnp.*;
|
||||
import org.cybergarage.util.Debug;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -63,6 +64,7 @@ public class SSDPNotifySocket extends HTTPMUSocket implements Runnable
|
||||
useIPv6Address = true;
|
||||
}
|
||||
open(addr, SSDP.PORT, bindAddr);
|
||||
Debug.message("Opened SSDP notify socket at " + bindAddr + ':' + SSDP.PORT);
|
||||
setControlPoint(null);
|
||||
}
|
||||
|
||||
@@ -130,7 +132,8 @@ public class SSDPNotifySocket extends HTTPMUSocket implements Runnable
|
||||
InetAddress maddr = getMulticastInetAddress();
|
||||
InetAddress pmaddr = packet.getHostInetAddress();
|
||||
if (maddr.equals(pmaddr) == false) {
|
||||
Debug.warning("Invalidate Multicast Recieved from IP " + maddr + " on " + pmaddr);
|
||||
// I2P
|
||||
//Debug.warning("Invalidate Multicast Recieved : " + maddr + "," + pmaddr);
|
||||
continue;
|
||||
}
|
||||
//TODO Must be performed on a different Thread in order to prevent UDP packet losses.
|
||||
@@ -144,8 +147,9 @@ public class SSDPNotifySocket extends HTTPMUSocket implements Runnable
|
||||
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(" -> ");
|
||||
// I2P hide address from thread dumps
|
||||
//name.append(this.getLocalAddress()).append(':');
|
||||
//name.append(this.getLocalPort()).append(" -> ");
|
||||
name.append(this.getMulticastAddress()).append(':');
|
||||
name.append(this.getMulticastPort());
|
||||
}
|
||||
|
||||
@@ -84,11 +84,12 @@ public class SSDPSearchResponseSocket extends HTTPUSocket implements Runnable
|
||||
StringBuffer name = new StringBuffer("Cyber.SSDPSearchResponseSocket/");
|
||||
DatagramSocket s = getDatagramSocket();
|
||||
// localAddr is null on Android m3-rc37a (01/30/08)
|
||||
InetAddress localAddr = s.getLocalAddress();
|
||||
if (localAddr != null) {
|
||||
name.append(s.getLocalAddress()).append(':');
|
||||
name.append(s.getLocalPort());
|
||||
}
|
||||
// I2P hide address from thread dumps
|
||||
//InetAddress localAddr = s.getLocalAddress();
|
||||
//if (localAddr != null) {
|
||||
// name.append(s.getLocalAddress()).append(':');
|
||||
// name.append(s.getLocalPort());
|
||||
//}
|
||||
deviceSearchResponseThread = new Thread(this,name.toString());
|
||||
deviceSearchResponseThread.start();
|
||||
}
|
||||
|
||||
@@ -174,8 +174,9 @@ public class SSDPSearchSocket extends HTTPMUSocket implements Runnable
|
||||
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(" -> ");
|
||||
// I2P hide address from thread dumps
|
||||
//name.append(this.getLocalAddress()).append(':');
|
||||
//name.append(this.getLocalPort()).append(" -> ");
|
||||
name.append(this.getMulticastAddress()).append(':');
|
||||
name.append(this.getMulticastPort());
|
||||
}
|
||||
|
||||
@@ -1,81 +1,65 @@
|
||||
/******************************************************************
|
||||
*
|
||||
* CyberUtil for Java
|
||||
*
|
||||
* Copyright (C) Satoshi Konno 2002
|
||||
*
|
||||
* File: Debug.java
|
||||
*
|
||||
* Revision;
|
||||
*
|
||||
* 11/18/02
|
||||
* - first revision.
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
package org.cybergarage.util;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
public final class Debug{
|
||||
|
||||
public static Debug debug = new Debug();
|
||||
|
||||
private PrintStream out = System.out;
|
||||
|
||||
|
||||
public Debug(){
|
||||
|
||||
}
|
||||
|
||||
public synchronized PrintStream getOut() {
|
||||
return out;
|
||||
}
|
||||
public synchronized void setOut(PrintStream out) {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
|
||||
public static boolean enabled = false;
|
||||
|
||||
public static Debug getDebug(){
|
||||
return Debug.debug;
|
||||
}
|
||||
|
||||
public static final void on() {
|
||||
enabled = true;
|
||||
}
|
||||
public static final void off() {
|
||||
enabled = false;
|
||||
}
|
||||
public static boolean isOn() {
|
||||
return enabled;
|
||||
}
|
||||
public static final void message(String s) {
|
||||
if (enabled == true)
|
||||
Debug.debug.getOut().println("CyberGarage message : " + s);
|
||||
}
|
||||
public static final void message(String m1, String m2) {
|
||||
if (enabled == true)
|
||||
Debug.debug.getOut().println("CyberGarage message : ");
|
||||
Debug.debug.getOut().println(m1);
|
||||
Debug.debug.getOut().println(m2);
|
||||
}
|
||||
public static final void warning(String s) {
|
||||
Debug.debug.getOut().println("CyberGarage warning : " + s);
|
||||
}
|
||||
public static final void warning(String m, Exception e) {
|
||||
if(e.getMessage()==null){
|
||||
Debug.debug.getOut().println("CyberGarage warning : " + m + " START");
|
||||
e.printStackTrace(Debug.debug.getOut());
|
||||
Debug.debug.getOut().println("CyberGarage warning : " + m + " END");
|
||||
}else{
|
||||
Debug.debug.getOut().println("CyberGarage warning : " + m + " (" + e.getMessage() + ")");
|
||||
e.printStackTrace(Debug.debug.getOut());
|
||||
}
|
||||
}
|
||||
public static final void warning(Exception e) {
|
||||
warning(e.getMessage());
|
||||
e.printStackTrace(Debug.debug.getOut());
|
||||
}
|
||||
}
|
||||
/******************************************************************
|
||||
*
|
||||
* CyberUtil for Java
|
||||
*
|
||||
* Copyright (C) Satoshi Konno 2002
|
||||
*
|
||||
* File: Debug.java
|
||||
*
|
||||
* Revision;
|
||||
*
|
||||
* 11/18/02
|
||||
* - first revision.
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
package org.cybergarage.util;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
public final class Debug
|
||||
{
|
||||
private static Log _log;
|
||||
|
||||
/** I2P this is all static so have the UPnPManager call this */
|
||||
public static void initialize(I2PAppContext ctx) {
|
||||
_log = ctx.logManager().getLog(Debug.class);
|
||||
// org.cybergarage.util.Debug=DEBUG at startup
|
||||
enabled = _log.shouldLog(Log.DEBUG);
|
||||
}
|
||||
|
||||
public static boolean enabled = false;
|
||||
|
||||
public static final void on() {
|
||||
enabled = true;
|
||||
}
|
||||
public static final void off() {
|
||||
enabled = false;
|
||||
}
|
||||
public static boolean isOn() {
|
||||
return enabled;
|
||||
}
|
||||
public static final void message(String s) {
|
||||
if (_log != null)
|
||||
_log.debug(s);
|
||||
}
|
||||
public static final void message(String m1, String m2) {
|
||||
if (_log != null) {
|
||||
_log.debug(m1);
|
||||
_log.debug(m2);
|
||||
}
|
||||
}
|
||||
public static final void warning(String s) {
|
||||
if (_log != null)
|
||||
_log.warn(s);
|
||||
}
|
||||
public static final void warning(String m, Exception e) {
|
||||
if (_log != null)
|
||||
_log.warn(m, e);
|
||||
}
|
||||
public static final void warning(Exception e) {
|
||||
if (_log != null)
|
||||
_log.warn("", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,8 @@ public class ThreadCore implements Runnable
|
||||
threadObject.interrupt();
|
||||
|
||||
setThreadObject(null);
|
||||
// I2P break Disposer out of sleep()
|
||||
threadObject.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,13 @@ public abstract class Parser
|
||||
|
||||
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");
|
||||
urlCon.setRequestProperty(HTTP.CONTENT_LENGTH,"0");
|
||||
if (host != null)
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
package org.cybergarage.xml.parser;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
@@ -116,7 +118,7 @@ public class JaxpParser extends Parser
|
||||
try {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
InputSource inSrc = new InputSource(inStream);
|
||||
InputSource inSrc = new InputSource(new NullFilterInputStream(inStream));
|
||||
Document doc = builder.parse(inSrc);
|
||||
|
||||
org.w3c.dom.Element docElem = doc.getDocumentElement();
|
||||
@@ -138,4 +140,28 @@ public class JaxpParser extends Parser
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* I2P -
|
||||
* Filter out nulls, hopefully to avoid
|
||||
* SAXParserException "Content not allowed in trailing section",
|
||||
* which is apparently caused by nulls.
|
||||
* Alternative is to remove all stuff between '>' and '<',
|
||||
* which isn't so hard if we assume no CDATA.
|
||||
*/
|
||||
private static class NullFilterInputStream extends FilterInputStream {
|
||||
|
||||
public NullFilterInputStream(InputStream is) {
|
||||
super(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int rv;
|
||||
while ((rv = super.read()) == 0) {
|
||||
// try again
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
* import java.io.IOException;
|
||||
* import java.io.StringReader;
|
||||
* import plugins.JabberLinker.org.xmlpull.v1.<a href="XmlPullParserException.html">XmlPullParserException.html</a>;
|
||||
* import plugins.JabberLinker.org.xmlpull.v1.<a href="XmlPullParserFactory.html">XmlPullParserFactory</a>;
|
||||
* import plugins.JabberLinker.org.xmlpull.v1.XmlPullParser;
|
||||
//import plugins.UPnP.org.cybergarage.util.*;
|
||||
import java.io.*;
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.net.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.*;
|
||||
import java.util.Calendar;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Vector;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.xml.sax.InputSource;
|
||||
import plugins.UPnP.org.cybergarage.http.*;
|
||||
import plugins.UPnP.org.cybergarage.http.*;
|
||||
import plugins.UPnP.org.cybergarage.net.*;
|
||||
import plugins.UPnP.org.cybergarage.net.*;
|
||||
import plugins.UPnP.org.cybergarage.soap.*;
|
||||
import plugins.UPnP.org.cybergarage.soap.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.Device;
|
||||
import plugins.UPnP.org.cybergarage.upnp.control.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.control.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.device.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.device.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.event.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.event.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.ssdp.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.ssdp.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.xml.*;
|
||||
import plugins.UPnP.org.cybergarage.upnp.xml.*;
|
||||
import plugins.UPnP.org.cybergarage.util.*;
|
||||
import plugins.UPnP.org.cybergarage.util.*;
|
||||
import plugins.UPnP.org.cybergarage.xml.*;
|
||||
import plugins.UPnP.org.cybergarage.xml.*;
|
||||
import plugins.UPnP.org.cybergarage.xml.Node;
|
||||
import plugins.UPnP.org.cybergarage.xml.Parser;
|
||||
import plugins.UPnP.org.cybergarage.xml.ParserException;
|
||||
import plugins.UPnP.org.cybergarage.xml.parser.*;
|
||||
343
router/java/src/org/xlattice/crypto/filters/BloomSHA1.java
Normal file
343
router/java/src/org/xlattice/crypto/filters/BloomSHA1.java
Normal file
@@ -0,0 +1,343 @@
|
||||
package org.xlattice.crypto.filters;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* A Bloom filter for sets of SHA1 digests. A Bloom filter uses a set
|
||||
* of k hash functions to determine set membership. Each hash function
|
||||
* produces a value in the range 0..M-1. The filter is of size M. To
|
||||
* add a member to the set, apply each function to the new member and
|
||||
* set the corresponding bit in the filter. For M very large relative
|
||||
* to k, this will normally set k bits in the filter. To check whether
|
||||
* x is a member of the set, apply each of the k hash functions to x
|
||||
* and check whether the corresponding bits are set in the filter. If
|
||||
* any are not set, x is definitely not a member. If all are set, x
|
||||
* may be a member. The probability of error (the false positive rate)
|
||||
* is f = (1 - e^(-kN/M))^k, where N is the number of set members.
|
||||
*
|
||||
* This class takes advantage of the fact that SHA1 digests are good-
|
||||
* quality pseudo-random numbers. The k hash functions are the values
|
||||
* of distinct sets of bits taken from the 20-byte SHA1 hash. The
|
||||
* number of bits in the filter, M, is constrained to be a power of
|
||||
* 2; M == 2^m. The number of bits in each hash function may not
|
||||
* exceed floor(m/k).
|
||||
*
|
||||
* This class is designed to be thread-safe, but this has not been
|
||||
* exhaustively tested.
|
||||
*
|
||||
* @author < A HREF="mailto:jddixon@users.sourceforge.net">Jim Dixon</A>
|
||||
*
|
||||
* BloomSHA1.java and KeySelector.java are BSD licensed from the xlattice
|
||||
* app - http://xlattice.sourceforge.net/
|
||||
*
|
||||
* minor tweaks by jrandom, exposing unsynchronized access and
|
||||
* allowing larger M and K. changes released into the public domain.
|
||||
*
|
||||
* Note that this is used only by DecayingBloomFilter, which uses only
|
||||
* the unsynchronized locked_foo() methods.
|
||||
* Deprecated for use outside of the router; to be moved to router.jar.
|
||||
*
|
||||
* As of 0.8.11, the locked_foo() methods are thread-safe, in that they work,
|
||||
* but there is a minor risk of false-negatives if two threads are
|
||||
* accessing the same bloom filter integer.
|
||||
*/
|
||||
|
||||
public class BloomSHA1 {
|
||||
protected final int m;
|
||||
protected final int k;
|
||||
protected int count;
|
||||
|
||||
protected final int[] filter;
|
||||
protected final KeySelector ks;
|
||||
|
||||
// convenience variables
|
||||
protected final int filterBits;
|
||||
protected final int filterWords;
|
||||
|
||||
private final BlockingQueue<int[]> buf;
|
||||
|
||||
/* (24,11) too big - see KeySelector
|
||||
|
||||
public static void main(String args[]) {
|
||||
BloomSHA1 b = new BloomSHA1(24, 11);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
byte v[] = new byte[32];
|
||||
v[0] = (byte)i;
|
||||
b.insert(v);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Creates a filter with 2^m bits and k 'hash functions', where
|
||||
* each hash function is portion of the 160-bit SHA1 hash.
|
||||
|
||||
* @param m determines number of bits in filter
|
||||
* @param k number of hash functionsx
|
||||
*
|
||||
* See KeySelector for important restriction on max m and k
|
||||
*/
|
||||
public BloomSHA1( int m, int k) {
|
||||
// XXX need to devise more reasonable set of checks
|
||||
//if ( m < 2 || m > 20) {
|
||||
// throw new IllegalArgumentException("m out of range");
|
||||
//}
|
||||
//if ( k < 1 || ( k * m > 160 )) {
|
||||
// throw new IllegalArgumentException(
|
||||
// "too many hash functions for filter size");
|
||||
//}
|
||||
this.m = m;
|
||||
this.k = k;
|
||||
filterBits = 1 << m;
|
||||
filterWords = (filterBits + 31)/32; // round up
|
||||
filter = new int[filterWords];
|
||||
ks = new KeySelector(m, k);
|
||||
buf = new LinkedBlockingQueue(16);
|
||||
|
||||
// DEBUG
|
||||
//System.out.println("Bloom constructor: m = " + m + ", k = " + k
|
||||
// + "\n filterBits = " + filterBits
|
||||
// + ", filterWords = " + filterWords);
|
||||
// END
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a filter of 2^m bits, with the number of 'hash functions"
|
||||
* k defaulting to 8.
|
||||
* @param m determines size of filter
|
||||
*/
|
||||
public BloomSHA1 (int m) {
|
||||
this(m, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a filter of 2^20 bits with k defaulting to 8.
|
||||
*/
|
||||
public BloomSHA1 () {
|
||||
this (20, 8);
|
||||
}
|
||||
/** Clear the filter, unsynchronized */
|
||||
protected void doClear() {
|
||||
Arrays.fill(filter, 0);
|
||||
count = 0;
|
||||
}
|
||||
/** Synchronized version */
|
||||
public void clear() {
|
||||
synchronized (this) {
|
||||
doClear();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the number of keys which have been inserted. This
|
||||
* class (BloomSHA1) does not guarantee uniqueness in any sense; if the
|
||||
* same key is added N times, the number of set members reported
|
||||
* will increase by N.
|
||||
*
|
||||
* @return number of set members
|
||||
*/
|
||||
public final int size() {
|
||||
synchronized (this) {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return number of bits in filter
|
||||
*/
|
||||
public final int capacity () {
|
||||
return filterBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a key to the set represented by the filter.
|
||||
*
|
||||
* XXX This version does not maintain 4-bit counters, it is not
|
||||
* a counting Bloom filter.
|
||||
*
|
||||
* @param b byte array representing a key (SHA1 digest)
|
||||
*/
|
||||
public void insert (byte[]b) { insert(b, 0, b.length); }
|
||||
|
||||
public void insert (byte[]b, int offset, int len) {
|
||||
synchronized(this) {
|
||||
locked_insert(b, offset, len);
|
||||
}
|
||||
}
|
||||
|
||||
public final void locked_insert(byte[]b) { locked_insert(b, 0, b.length); }
|
||||
|
||||
public final void locked_insert(byte[]b, int offset, int len) {
|
||||
int[] bitOffset = acquire();
|
||||
int[] wordOffset = acquire();
|
||||
ks.getOffsets(b, offset, len, bitOffset, wordOffset);
|
||||
for (int i = 0; i < k; i++) {
|
||||
filter[wordOffset[i]] |= 1 << bitOffset[i];
|
||||
}
|
||||
count++;
|
||||
buf.offer(bitOffset);
|
||||
buf.offer(wordOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a key in the filter. Sets up the bit and word offset arrays.
|
||||
*
|
||||
* @param b byte array representing a key (SHA1 digest)
|
||||
* @return true if b is in the filter
|
||||
*/
|
||||
protected final boolean isMember(byte[] b) { return isMember(b, 0, b.length); }
|
||||
|
||||
protected final boolean isMember(byte[] b, int offset, int len) {
|
||||
int[] bitOffset = acquire();
|
||||
int[] wordOffset = acquire();
|
||||
ks.getOffsets(b, offset, len, bitOffset, wordOffset);
|
||||
for (int i = 0; i < k; i++) {
|
||||
if (! ((filter[wordOffset[i]] & (1 << bitOffset[i])) != 0) ) {
|
||||
buf.offer(bitOffset);
|
||||
buf.offer(wordOffset);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
buf.offer(bitOffset);
|
||||
buf.offer(wordOffset);
|
||||
return true;
|
||||
}
|
||||
|
||||
public final boolean locked_member(byte[]b) { return isMember(b); }
|
||||
public final boolean locked_member(byte[]b, int offset, int len) { return isMember(b, offset, len); }
|
||||
|
||||
/**
|
||||
* Is a key in the filter. External interface, internally synchronized.
|
||||
*
|
||||
* @param b byte array representing a key (SHA1 digest)
|
||||
* @return true if b is in the filter
|
||||
*/
|
||||
public final boolean member(byte[]b) { return member(b, 0, b.length); }
|
||||
public final boolean member(byte[]b, int offset, int len) {
|
||||
synchronized (this) {
|
||||
return isMember(b, offset, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bloom filter offsets for reuse.
|
||||
* Caller should call release(rv) when done with it.
|
||||
* @since 0.8.11
|
||||
*/
|
||||
public FilterKey getFilterKey(byte[] b, int offset, int len) {
|
||||
int[] bitOffset = acquire();
|
||||
int[] wordOffset = acquire();
|
||||
ks.getOffsets(b, offset, len, bitOffset, wordOffset);
|
||||
return new FilterKey(bitOffset, wordOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the key to the filter.
|
||||
* @since 0.8.11
|
||||
*/
|
||||
public void locked_insert(FilterKey fk) {
|
||||
for (int i = 0; i < k; i++) {
|
||||
filter[fk.wordOffset[i]] |= 1 << fk.bitOffset[i];
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is the key in the filter.
|
||||
* @since 0.8.11
|
||||
*/
|
||||
public boolean locked_member(FilterKey fk) {
|
||||
for (int i = 0; i < k; i++) {
|
||||
if (! ((filter[fk.wordOffset[i]] & (1 << fk.bitOffset[i])) != 0) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.8.11
|
||||
*/
|
||||
private int[] acquire() {
|
||||
int[] rv = buf.poll();
|
||||
if (rv != null)
|
||||
return rv;
|
||||
return new int[k];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.8.11
|
||||
*/
|
||||
public void release(FilterKey fk) {
|
||||
buf.offer(fk.bitOffset);
|
||||
buf.offer(fk.wordOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the (opaque) bloom filter offsets for reuse.
|
||||
* @since 0.8.11
|
||||
*/
|
||||
public static class FilterKey {
|
||||
|
||||
private final int[] bitOffset;
|
||||
private final int[] wordOffset;
|
||||
|
||||
private FilterKey(int[] bitOffset, int[] wordOffset) {
|
||||
this.bitOffset = bitOffset;
|
||||
this.wordOffset = wordOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param n number of set members
|
||||
* @return approximate false positive rate
|
||||
*/
|
||||
public final double falsePositives(int n) {
|
||||
// (1 - e(-kN/M))^k
|
||||
return java.lang.Math.pow (
|
||||
(1l - java.lang.Math.exp(0d- ((double)k) * (long)n / filterBits)), k);
|
||||
}
|
||||
|
||||
public final double falsePositives() {
|
||||
return falsePositives(count);
|
||||
}
|
||||
|
||||
/*****
|
||||
// DEBUG METHODS
|
||||
public static String keyToString(byte[] key) {
|
||||
StringBuilder sb = new StringBuilder().append(key[0]);
|
||||
for (int i = 1; i < key.length; i++) {
|
||||
sb.append(".").append(Integer.toString(key[i], 16));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
*****/
|
||||
|
||||
/** convert 64-bit integer to hex String */
|
||||
/*****
|
||||
public static String ltoh (long i) {
|
||||
StringBuilder sb = new StringBuilder().append("#")
|
||||
.append(Long.toString(i, 16));
|
||||
return sb.toString();
|
||||
}
|
||||
*****/
|
||||
|
||||
/** convert 32-bit integer to String */
|
||||
/*****
|
||||
public static String itoh (int i) {
|
||||
StringBuilder sb = new StringBuilder().append("#")
|
||||
.append(Integer.toString(i, 16));
|
||||
return sb.toString();
|
||||
}
|
||||
*****/
|
||||
|
||||
/** convert single byte to String */
|
||||
/*****
|
||||
public static String btoh (byte b) {
|
||||
int i = 0xff & b;
|
||||
return itoh(i);
|
||||
}
|
||||
*****/
|
||||
}
|
||||
|
||||
279
router/java/src/org/xlattice/crypto/filters/KeySelector.java
Normal file
279
router/java/src/org/xlattice/crypto/filters/KeySelector.java
Normal file
@@ -0,0 +1,279 @@
|
||||
package org.xlattice.crypto.filters;
|
||||
|
||||
/**
|
||||
* Given a key, populates arrays determining word and bit offsets into
|
||||
* a Bloom filter.
|
||||
*
|
||||
* @author <A HREF="mailto:jddixon@users.sourceforge.net">Jim Dixon</A>
|
||||
*
|
||||
* BloomSHA1.java and KeySelector.java are BSD licensed from the xlattice
|
||||
* app - http://xlattice.sourceforge.net/
|
||||
*
|
||||
* minor tweaks by jrandom, exposing unsynchronized access and
|
||||
* allowing larger M and K. changes released into the public domain.
|
||||
*
|
||||
* As of 0.8.11, bitoffset and wordoffset out parameters moved from fields
|
||||
* to selector arguments, to allow concurrency.
|
||||
* ALl methods are now thread-safe.
|
||||
*/
|
||||
public class KeySelector {
|
||||
|
||||
private final int m;
|
||||
private final int k;
|
||||
private final BitSelector bitSel;
|
||||
private final WordSelector wordSel;
|
||||
|
||||
public interface BitSelector {
|
||||
/**
|
||||
* @param bitOffset Out parameter of length k
|
||||
* @since 0.8.11 out parameter added
|
||||
*/
|
||||
public void getBitSelectors(byte[] b, int offset, int length, int[] bitOffset);
|
||||
}
|
||||
|
||||
public interface WordSelector {
|
||||
/**
|
||||
* @param wordOffset Out parameter of length k
|
||||
* @since 0.8.11 out parameter added
|
||||
*/
|
||||
public void getWordSelectors(byte[] b, int offset, int length, int[] wordOffset);
|
||||
}
|
||||
|
||||
/** AND with byte to expose index-many bits */
|
||||
public final static int[] UNMASK = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767};
|
||||
/** AND with byte to zero out index-many bits */
|
||||
public final static int[] MASK = {
|
||||
~0,~1,~3,~7,~15,~31,~63,~127,~255,~511,~1023,~2047,~4095,~8191,~16383,~32767};
|
||||
|
||||
public final static int TWO_UP_15 = 32 * 1024;
|
||||
|
||||
/**
|
||||
* Creates a key selector for a Bloom filter. When a key is presented
|
||||
* to the getOffsets() method, the k 'hash function' values are
|
||||
* extracted and used to populate bitOffset and wordOffset arrays which
|
||||
* specify the k flags to be set or examined in the filter.
|
||||
*
|
||||
* @param m size of the filter as a power of 2
|
||||
* @param k number of 'hash functions'
|
||||
*
|
||||
* Note that if k and m are too big, the GenericWordSelector blows up -
|
||||
* The max for 32-byte keys is m=23 and k=11.
|
||||
* The precise restriction appears to be:
|
||||
* ((5k + (k-1)(m-5)) / 8) + 2 < keySizeInBytes
|
||||
*
|
||||
* It isn't clear how to fix this.
|
||||
*/
|
||||
public KeySelector (int m, int k) {
|
||||
//if ( (m < 2) || (m > 20)|| (k < 1)
|
||||
// || (bitOffset == null) || (wordOffset == null)) {
|
||||
// throw new IllegalArgumentException();
|
||||
//}
|
||||
this.m = m;
|
||||
this.k = k;
|
||||
bitSel = new GenericBitSelector();
|
||||
wordSel = new GenericWordSelector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the k bit offsets from a key, suitable for general values
|
||||
* of m and k.
|
||||
*/
|
||||
public class GenericBitSelector implements BitSelector {
|
||||
/** Do the extraction */
|
||||
public void getBitSelectors(byte[] b, int offset, int length, int[] bitOffset) {
|
||||
int curBit = 8 * offset;
|
||||
int curByte;
|
||||
for (int j = 0; j < k; j++) {
|
||||
curByte = curBit / 8;
|
||||
int bitsUnused = ((curByte + 1) * 8) - curBit; // left in byte
|
||||
|
||||
// // DEBUG
|
||||
// System.out.println (
|
||||
// "this byte = " + btoh(b[curByte])
|
||||
// + ", next byte = " + btoh(b[curByte + 1])
|
||||
// + "; curBit=" + curBit + ", curByte= " + curByte
|
||||
// + ", bitsUnused=" + bitsUnused);
|
||||
// // END
|
||||
if (bitsUnused > 5) {
|
||||
bitOffset[j] = ((0xff & b[curByte])
|
||||
>> (bitsUnused - 5)) & UNMASK[5];
|
||||
// // DEBUG
|
||||
// System.out.println(
|
||||
// " before shifting: " + btoh(b[curByte])
|
||||
// + "\n after shifting: "
|
||||
// + itoh( (0xff & b[curByte]) >> (bitsUnused - 5))
|
||||
// + "\n mask: " + itoh(UNMASK[5]) );
|
||||
// // END
|
||||
} else if (bitsUnused == 5) {
|
||||
bitOffset[j] = b[curByte] & UNMASK[5];
|
||||
} else {
|
||||
bitOffset[j] = (b[curByte] & UNMASK[bitsUnused])
|
||||
| (((0xff & b[curByte + 1]) >> 3)
|
||||
& MASK[bitsUnused]);
|
||||
// // DEBUG
|
||||
// System.out.println(
|
||||
// " contribution from first byte: "
|
||||
// + itoh(b[curByte] & UNMASK[bitsUnused])
|
||||
// + "\n second byte: " + btoh(b[curByte + 1])
|
||||
// + "\n shifted: " + itoh((0xff & b[curByte + 1]) >> 3)
|
||||
// + "\n mask: " + itoh(MASK[bitsUnused])
|
||||
// + "\n contribution from second byte: "
|
||||
// + itoh((0xff & b[curByte + 1] >> 3) & MASK[bitsUnused]));
|
||||
// // END
|
||||
}
|
||||
// // DEBUG
|
||||
// System.out.println (" bitOffset[j] = " + bitOffset[j]);
|
||||
// // END
|
||||
curBit += 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Extracts the k word offsets from a key. Suitable for general
|
||||
* values of m and k. See above for formula for max m and k.
|
||||
*/
|
||||
public class GenericWordSelector implements WordSelector {
|
||||
/** Extract the k offsets into the word offset array */
|
||||
public void getWordSelectors(byte[] b, int offset, int length, int[] wordOffset) {
|
||||
int stride = m - 5;
|
||||
//assert true: stride<16;
|
||||
int curBit = (k * 5) + (offset * 8);
|
||||
int curByte;
|
||||
for (int j = 0; j < k; j++) {
|
||||
curByte = curBit / 8;
|
||||
int bitsUnused = ((curByte + 1) * 8) - curBit; // left in byte
|
||||
|
||||
// // DEBUG
|
||||
// System.out.println (
|
||||
// "curr 3 bytes: " + btoh(b[curByte])
|
||||
// + (curByte < 19 ?
|
||||
// " " + btoh(b[curByte + 1]) : "")
|
||||
// + (curByte < 18 ?
|
||||
// " " + btoh(b[curByte + 2]) : "")
|
||||
// + "; curBit=" + curBit + ", curByte= " + curByte
|
||||
// + ", bitsUnused=" + bitsUnused);
|
||||
// // END
|
||||
|
||||
if (bitsUnused > stride) {
|
||||
// the value is entirely within the current byte
|
||||
wordOffset[j] = ((0xff & b[curByte])
|
||||
>> (bitsUnused - stride))
|
||||
& UNMASK[stride];
|
||||
} else if (bitsUnused == stride) {
|
||||
// the value fills the current byte
|
||||
wordOffset[j] = b[curByte] & UNMASK[stride];
|
||||
} else { // bitsUnused < stride
|
||||
// value occupies more than one byte
|
||||
// bits from first byte, right-aligned in result
|
||||
wordOffset[j] = b[curByte] & UNMASK[bitsUnused];
|
||||
// // DEBUG
|
||||
// System.out.println(" first byte contributes "
|
||||
// + itoh(wordOffset[j]));
|
||||
// // END
|
||||
// bits from second byte
|
||||
int bitsToGet = stride - bitsUnused;
|
||||
if (bitsToGet >= 8) {
|
||||
// 8 bits from second byte
|
||||
wordOffset[j] |= (0xff & b[curByte + 1]) << bitsUnused;
|
||||
// // DEBUG
|
||||
// System.out.println(" second byte contributes "
|
||||
// + itoh(
|
||||
// (0xff & b[curByte + 1]) << bitsUnused
|
||||
// ));
|
||||
// // END
|
||||
|
||||
// bits from third byte
|
||||
bitsToGet -= 8;
|
||||
if (bitsToGet > 0) {
|
||||
// AIOOBE here if m and k too big (23,11 is the max)
|
||||
// for a 32-byte key - see above
|
||||
wordOffset[j] |=
|
||||
((0xff & b[curByte + 2]) >> (8 - bitsToGet))
|
||||
<< (stride - bitsToGet) ;
|
||||
// // DEBUG
|
||||
// System.out.println(" third byte contributes "
|
||||
// + itoh(
|
||||
// (((0xff & b[curByte + 2]) >> (8 - bitsToGet))
|
||||
// << (stride - bitsToGet))
|
||||
// ));
|
||||
// // END
|
||||
}
|
||||
} else {
|
||||
// all remaining bits are within second byte
|
||||
wordOffset[j] |= ((b[curByte + 1] >> (8 - bitsToGet))
|
||||
& UNMASK[bitsToGet])
|
||||
<< bitsUnused;
|
||||
// // DEBUG
|
||||
// System.out.println(" second byte contributes "
|
||||
// + itoh(
|
||||
// ((b[curByte + 1] >> (8 - bitsToGet))
|
||||
// & UNMASK[bitsToGet])
|
||||
// << bitsUnused
|
||||
// ));
|
||||
// // END
|
||||
}
|
||||
}
|
||||
// // DEBUG
|
||||
// System.out.println (
|
||||
// " wordOffset[" + j + "] = " + wordOffset[j]
|
||||
// + ", " + itoh(wordOffset[j])
|
||||
// );
|
||||
// // END
|
||||
curBit += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a key, populate the word and bit offset arrays, each
|
||||
* of which has k elements.
|
||||
*
|
||||
* @param key cryptographic key used in populating the arrays
|
||||
* @param bitOffset Out parameter of length k
|
||||
* @param wordOffset Out parameter of length k
|
||||
* @since 0.8.11 out parameters added
|
||||
*/
|
||||
public void getOffsets (byte[] key, int[] bitOffset, int[] wordOffset) {
|
||||
getOffsets(key, 0, key.length, bitOffset, wordOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a key, populate the word and bit offset arrays, each
|
||||
* of which has k elements.
|
||||
*
|
||||
* @param key cryptographic key used in populating the arrays
|
||||
* @param bitOffset Out parameter of length k
|
||||
* @param wordOffset Out parameter of length k
|
||||
* @since 0.8.11 out parameters added
|
||||
*/
|
||||
public void getOffsets (byte[] key, int off, int len, int[] bitOffset, int[] wordOffset) {
|
||||
// skip these checks for speed
|
||||
//if (key == null) {
|
||||
// throw new IllegalArgumentException("null key");
|
||||
//}
|
||||
//if (len < 20) {
|
||||
// throw new IllegalArgumentException(
|
||||
// "key must be at least 20 bytes long");
|
||||
//}
|
||||
// // DEBUG
|
||||
// System.out.println("KeySelector.getOffsets for "
|
||||
// + BloomSHA1.keyToString(b));
|
||||
// // END
|
||||
bitSel.getBitSelectors(key, off, len, bitOffset);
|
||||
wordSel.getWordSelectors(key, off, len, wordOffset);
|
||||
}
|
||||
|
||||
/*****
|
||||
// DEBUG METHODS ////////////////////////////////////////////////
|
||||
String itoh(int i) {
|
||||
return BloomSHA1.itoh(i);
|
||||
}
|
||||
String btoh(byte b) {
|
||||
return BloomSHA1.btoh(b);
|
||||
}
|
||||
*****/
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,80 +0,0 @@
|
||||
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
|
||||
// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
|
||||
|
||||
package org.xmlpull.v1;
|
||||
|
||||
/**
|
||||
* This exception is thrown to signal XML Pull Parser related faults.
|
||||
*
|
||||
* @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
|
||||
*/
|
||||
public class XmlPullParserException extends Exception {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
protected Throwable detail;
|
||||
protected int row = -1;
|
||||
protected int column = -1;
|
||||
|
||||
/* public XmlPullParserException() {
|
||||
}*/
|
||||
|
||||
public XmlPullParserException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
/*
|
||||
public XmlPullParserException(String s, Throwable thrwble) {
|
||||
super(s);
|
||||
this.detail = thrwble;
|
||||
}
|
||||
|
||||
public XmlPullParserException(String s, int row, int column) {
|
||||
super(s);
|
||||
this.row = row;
|
||||
this.column = column;
|
||||
}
|
||||
*/
|
||||
|
||||
public XmlPullParserException(String msg, XmlPullParser parser, Throwable chain) {
|
||||
super ((msg == null ? "" : msg+" ")
|
||||
+ (parser == null ? "" : "(position:"+parser.getPositionDescription()+") ")
|
||||
+ (chain == null ? "" : "caused by: "+chain));
|
||||
|
||||
if (parser != null) {
|
||||
this.row = parser.getLineNumber();
|
||||
this.column = parser.getColumnNumber();
|
||||
}
|
||||
this.detail = chain;
|
||||
}
|
||||
|
||||
public Throwable getDetail() { return detail; }
|
||||
// public void setDetail(Throwable cause) { this.detail = cause; }
|
||||
public int getLineNumber() { return row; }
|
||||
public int getColumnNumber() { return column; }
|
||||
|
||||
/*
|
||||
public String getMessage() {
|
||||
if(detail == null)
|
||||
return super.getMessage();
|
||||
else
|
||||
return super.getMessage() + "; nested exception is: \n\t"
|
||||
+ detail.getMessage();
|
||||
}
|
||||
*/
|
||||
|
||||
//NOTE: code that prints this and detail is difficult in J2ME
|
||||
public void printStackTrace() {
|
||||
if (detail == null) {
|
||||
super.printStackTrace();
|
||||
} else {
|
||||
synchronized(System.err) {
|
||||
System.err.println(super.getMessage() + "; nested exception is:");
|
||||
detail.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
|
||||
// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
|
||||
|
||||
package org.xmlpull.v1;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* This class is used to create implementations of XML Pull Parser defined in XMPULL V1 API.
|
||||
* The name of actual factory class will be determined based on several parameters.
|
||||
* It works similar to JAXP but tailored to work in J2ME environments
|
||||
* (no access to system properties or file system) so name of parser class factory to use
|
||||
* and its class used for loading (no class loader - on J2ME no access to context class loaders)
|
||||
* must be passed explicitly. If no name of parser factory was passed (or is null)
|
||||
* it will try to find name by searching in CLASSPATH for
|
||||
* META-INF/services/plugins.JabberLinker.org.xmlpull.v1.XmlPullParserFactory resource that should contain
|
||||
* a comma separated list of class names of factories or parsers to try (in order from
|
||||
* left to the right). If none found, it will throw an exception.
|
||||
*
|
||||
* <br /><strong>NOTE:</strong>In J2SE or J2EE environments, you may want to use
|
||||
* <code>newInstance(property, classLoaderCtx)</code>
|
||||
* where first argument is
|
||||
* <code>System.getProperty(XmlPullParserFactory.PROPERTY_NAME)</code>
|
||||
* and second is <code>Thread.getContextClassLoader().getClass()</code> .
|
||||
*
|
||||
* @see XmlPullParser
|
||||
*
|
||||
* @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
|
||||
* @author Stefan Haustein
|
||||
*/
|
||||
|
||||
public class XmlPullParserFactory {
|
||||
/** used as default class to server as context class in newInstance() */
|
||||
final static Class referenceContextClass;
|
||||
|
||||
static {
|
||||
XmlPullParserFactory f = new XmlPullParserFactory();
|
||||
referenceContextClass = f.getClass();
|
||||
}
|
||||
|
||||
/** Name of the system or midlet property that should be used for
|
||||
a system property containing a comma separated list of factory
|
||||
or parser class names (value:
|
||||
plugins.JabberLinker.org.xmlpull.v1.XmlPullParserFactory). */
|
||||
|
||||
|
||||
public static final String PROPERTY_NAME =
|
||||
"plugins.JabberLinker.org.xmlpull.v1.XmlPullParserFactory";
|
||||
|
||||
private static final String RESOURCE_NAME =
|
||||
"/META-INF/services/" + PROPERTY_NAME;
|
||||
|
||||
|
||||
// public static final String DEFAULT_PROPERTY =
|
||||
// "plugins.JabberLinker.org.xmlpull.xpp3.XmlPullParser,org.kxml2.io.KXmlParser";
|
||||
|
||||
|
||||
protected Vector parserClasses;
|
||||
protected String classNamesLocation;
|
||||
|
||||
protected Vector serializerClasses;
|
||||
|
||||
|
||||
// features are kept there
|
||||
protected Hashtable features = new Hashtable();
|
||||
|
||||
|
||||
/**
|
||||
* Protected constructor to be called by factory implementations.
|
||||
*/
|
||||
|
||||
protected XmlPullParserFactory() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the features to be set when XML Pull Parser is created by this factory.
|
||||
* <p><b>NOTE:</b> factory features are not used for XML Serializer.
|
||||
*
|
||||
* @param name string with URI identifying feature
|
||||
* @param state if true feature will be set; if false will be ignored
|
||||
*/
|
||||
|
||||
public void setFeature(String name,
|
||||
boolean state) throws XmlPullParserException {
|
||||
|
||||
features.put(name, new Boolean(state));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the current value of the feature with given name.
|
||||
* <p><b>NOTE:</b> factory features are not used for XML Serializer.
|
||||
*
|
||||
* @param name The name of feature to be retrieved.
|
||||
* @return The value of named feature.
|
||||
* Unknown features are <string>always</strong> returned as false
|
||||
*/
|
||||
|
||||
public boolean getFeature (String name) {
|
||||
Boolean value = (Boolean) features.get(name);
|
||||
return value != null ? value.booleanValue() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that the parser produced by this factory will provide
|
||||
* support for XML namespaces.
|
||||
* By default the value of this is set to false.
|
||||
*
|
||||
* @param awareness true if the parser produced by this code
|
||||
* will provide support for XML namespaces; false otherwise.
|
||||
*/
|
||||
|
||||
public void setNamespaceAware(boolean awareness) {
|
||||
features.put (XmlPullParser.FEATURE_PROCESS_NAMESPACES, new Boolean (awareness));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the factory is configured to produce
|
||||
* parsers which are namespace aware
|
||||
* (it simply set feature XmlPullParser.FEATURE_PROCESS_NAMESPACES to true or false).
|
||||
*
|
||||
* @return true if the factory is configured to produce parsers
|
||||
* which are namespace aware; false otherwise.
|
||||
*/
|
||||
|
||||
public boolean isNamespaceAware() {
|
||||
return getFeature (XmlPullParser.FEATURE_PROCESS_NAMESPACES);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies that the parser produced by this factory will be validating
|
||||
* (it simply set feature XmlPullParser.FEATURE_VALIDATION to true or false).
|
||||
*
|
||||
* By default the value of this is set to false.
|
||||
*
|
||||
* @param validating - if true the parsers created by this factory must be validating.
|
||||
*/
|
||||
|
||||
public void setValidating(boolean validating) {
|
||||
features.put (XmlPullParser.FEATURE_VALIDATION, new Boolean (validating));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the factory is configured to produce parsers
|
||||
* which validate the XML content during parse.
|
||||
*
|
||||
* @return true if the factory is configured to produce parsers
|
||||
* which validate the XML content during parse; false otherwise.
|
||||
*/
|
||||
|
||||
public boolean isValidating() {
|
||||
return getFeature (XmlPullParser.FEATURE_VALIDATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a XML Pull Parser
|
||||
* using the currently configured factory features.
|
||||
*
|
||||
* @return A new instance of a XML Pull Parser.
|
||||
* @throws XmlPullParserException if a parser cannot be created which satisfies the
|
||||
* requested configuration.
|
||||
*/
|
||||
|
||||
public XmlPullParser newPullParser() throws XmlPullParserException {
|
||||
|
||||
if (parserClasses == null) throw new XmlPullParserException
|
||||
("Factory initialization was incomplete - has not tried "+classNamesLocation);
|
||||
|
||||
if (parserClasses.size() == 0) throw new XmlPullParserException
|
||||
("No valid parser classes found in "+classNamesLocation);
|
||||
|
||||
final StringBuilder issues = new StringBuilder ();
|
||||
|
||||
for (int i = 0; i < parserClasses.size (); i++) {
|
||||
final Class ppClass = (Class) parserClasses.elementAt (i);
|
||||
try {
|
||||
final XmlPullParser pp = (XmlPullParser) ppClass.newInstance();
|
||||
// if( ! features.isEmpty() ) {
|
||||
//Enumeration keys = features.keys();
|
||||
// while(keys.hasMoreElements()) {
|
||||
|
||||
for (Enumeration e = features.keys (); e.hasMoreElements ();) {
|
||||
final String key = (String) e.nextElement();
|
||||
final Boolean value = (Boolean) features.get(key);
|
||||
if(value != null && value.booleanValue()) {
|
||||
pp.setFeature(key, true);
|
||||
}
|
||||
}
|
||||
return pp;
|
||||
|
||||
} catch(Exception ex) {
|
||||
issues.append (ppClass.getName () + ": "+ ex.toString ()+"; ");
|
||||
}
|
||||
}
|
||||
|
||||
throw new XmlPullParserException ("could not create parser: "+issues);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of a XML Serializer.
|
||||
*
|
||||
* <p><b>NOTE:</b> factory features are not used for XML Serializer.
|
||||
*
|
||||
* @return A new instance of a XML Serializer.
|
||||
* @throws XmlPullParserException if a parser cannot be created which satisfies the
|
||||
* requested configuration.
|
||||
*/
|
||||
|
||||
public XmlSerializer newSerializer() throws XmlPullParserException {
|
||||
|
||||
if (serializerClasses == null) {
|
||||
throw new XmlPullParserException
|
||||
("Factory initialization incomplete - has not tried "+classNamesLocation);
|
||||
}
|
||||
if(serializerClasses.size() == 0) {
|
||||
throw new XmlPullParserException
|
||||
("No valid serializer classes found in "+classNamesLocation);
|
||||
}
|
||||
|
||||
final StringBuilder issues = new StringBuilder ();
|
||||
|
||||
for (int i = 0; i < serializerClasses.size (); i++) {
|
||||
final Class ppClass = (Class) serializerClasses.elementAt (i);
|
||||
try {
|
||||
final XmlSerializer ser = (XmlSerializer) ppClass.newInstance();
|
||||
|
||||
// for (Enumeration e = features.keys (); e.hasMoreElements ();) {
|
||||
// String key = (String) e.nextElement();
|
||||
// Boolean value = (Boolean) features.get(key);
|
||||
// if(value != null && value.booleanValue()) {
|
||||
// ser.setFeature(key, true);
|
||||
// }
|
||||
// }
|
||||
return ser;
|
||||
|
||||
} catch(Exception ex) {
|
||||
issues.append (ppClass.getName () + ": "+ ex.toString ()+"; ");
|
||||
}
|
||||
}
|
||||
|
||||
throw new XmlPullParserException ("could not create serializer: "+issues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of a PullParserFactory that can be used
|
||||
* to create XML pull parsers (see class description for more
|
||||
* details).
|
||||
*
|
||||
* @return a new instance of a PullParserFactory, as returned by newInstance (null, null);
|
||||
*/
|
||||
public static XmlPullParserFactory newInstance () throws XmlPullParserException {
|
||||
return newInstance(null, null);
|
||||
}
|
||||
|
||||
public static XmlPullParserFactory newInstance (String classNames, Class context)
|
||||
throws XmlPullParserException {
|
||||
|
||||
if (context == null) {
|
||||
//NOTE: make sure context uses the same class loader as API classes
|
||||
// this is the best we can do without having access to context classloader in J2ME
|
||||
// if API is in the same classloader as implementation then this will work
|
||||
context = referenceContextClass;
|
||||
}
|
||||
|
||||
String classNamesLocation = null;
|
||||
|
||||
if (classNames == null || classNames.length() == 0 || "DEFAULT".equals(classNames)) {
|
||||
try {
|
||||
InputStream is = context.getResourceAsStream (RESOURCE_NAME);
|
||||
|
||||
if (is == null) throw new XmlPullParserException
|
||||
("resource not found: "+RESOURCE_NAME
|
||||
+" make sure that parser implementing XmlPull API is available");
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
while (true) {
|
||||
final int ch = is.read();
|
||||
if (ch < 0) break;
|
||||
else if (ch > ' ')
|
||||
sb.append((char) ch);
|
||||
}
|
||||
is.close ();
|
||||
|
||||
classNames = sb.toString ();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new XmlPullParserException (null, null, e);
|
||||
}
|
||||
classNamesLocation = "resource "+RESOURCE_NAME+" that contained '"+classNames+"'";
|
||||
} else {
|
||||
classNamesLocation =
|
||||
"parameter classNames to newInstance() that contained '"+classNames+"'";
|
||||
}
|
||||
|
||||
XmlPullParserFactory factory = null;
|
||||
final Vector parserClasses = new Vector ();
|
||||
final Vector serializerClasses = new Vector ();
|
||||
int pos = 0;
|
||||
|
||||
while (pos < classNames.length ()) {
|
||||
int cut = classNames.indexOf (',', pos);
|
||||
|
||||
if (cut == -1) cut = classNames.length ();
|
||||
final String name = classNames.substring (pos, cut);
|
||||
|
||||
Class candidate = null;
|
||||
Object instance = null;
|
||||
|
||||
try {
|
||||
candidate = Class.forName (name);
|
||||
// necessary because of J2ME .class issue
|
||||
instance = candidate.newInstance ();
|
||||
}
|
||||
catch (Exception e) {}
|
||||
|
||||
if (candidate != null) {
|
||||
boolean recognized = false;
|
||||
if (instance instanceof XmlPullParser) {
|
||||
parserClasses.addElement (candidate);
|
||||
recognized = true;
|
||||
}
|
||||
if (instance instanceof XmlSerializer) {
|
||||
serializerClasses.addElement (candidate);
|
||||
recognized = true;
|
||||
}
|
||||
if (instance instanceof XmlPullParserFactory) {
|
||||
if (factory == null) {
|
||||
factory = (XmlPullParserFactory) instance;
|
||||
}
|
||||
recognized = true;
|
||||
}
|
||||
if (!recognized) {
|
||||
throw new XmlPullParserException ("incompatible class: "+name);
|
||||
}
|
||||
}
|
||||
pos = cut + 1;
|
||||
}
|
||||
|
||||
if (factory == null) {
|
||||
factory = new XmlPullParserFactory ();
|
||||
}
|
||||
factory.parserClasses = parserClasses;
|
||||
factory.serializerClasses = serializerClasses;
|
||||
factory.classNamesLocation = classNamesLocation;
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,326 +0,0 @@
|
||||
package org.xmlpull.v1;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* Define an interface to serialziation of XML Infoset.
|
||||
* This interface abstracts away if serialized XML is XML 1.0 comaptible text or
|
||||
* other formats of XML 1.0 serializations (such as binary XML for example with WBXML).
|
||||
*
|
||||
* <p><b>PLEASE NOTE:</b> This interface will be part of XmlPull 1.2 API.
|
||||
* It is included as basis for discussion. It may change in any way.
|
||||
*
|
||||
* <p>Exceptions that may be thrown are: IOException or runtime exception
|
||||
* (more runtime exceptions can be thrown but are not declared and as such
|
||||
* have no semantics defined for this interface):
|
||||
* <ul>
|
||||
* <li><em>IllegalArgumentException</em> - for almost all methods to signal that
|
||||
* argument is illegal
|
||||
* <li><em>IllegalStateException</em> - to signal that call has good arguments but
|
||||
* is not expected here (violation of contract) and for features/properties
|
||||
* when requesting setting unimplemented feature/property
|
||||
* (UnsupportedOperationException would be better but it is not in MIDP)
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>NOTE:</b> writing CDSECT, ENTITY_REF, IGNORABLE_WHITESPACE,
|
||||
* PROCESSING_INSTRUCTION, COMMENT, and DOCDECL in some implementations
|
||||
* may not be supported (for example when serializing to WBXML).
|
||||
* In such case IllegalStateException will be thrown and it is recommened
|
||||
* to use an optional feature to signal that implementation is not
|
||||
* supporting this kind of output.
|
||||
*/
|
||||
|
||||
public interface XmlSerializer {
|
||||
|
||||
/**
|
||||
* Set feature identified by name (recommended to be URI for uniqueness).
|
||||
* Some well known optional features are defined in
|
||||
* <a href="http://www.xmlpull.org/v1/doc/features.html">
|
||||
* http://www.xmlpull.org/v1/doc/features.html</a>.
|
||||
*
|
||||
* If feature is not recocgnized or can not be set
|
||||
* then IllegalStateException MUST be thrown.
|
||||
*
|
||||
* @exception IllegalStateException If the feature is not supported or can not be set
|
||||
*/
|
||||
void setFeature(String name,
|
||||
boolean state)
|
||||
throws IllegalArgumentException, IllegalStateException;
|
||||
|
||||
|
||||
/**
|
||||
* Return the current value of the feature with given name.
|
||||
* <p><strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null
|
||||
*
|
||||
* @param name The name of feature to be retrieved.
|
||||
* @return The value of named feature.
|
||||
* @exception IllegalArgumentException if feature string is null
|
||||
*/
|
||||
boolean getFeature(String name);
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of a property.
|
||||
* (the property name is recommened to be URI for uniqueness).
|
||||
* Some well known optional properties are defined in
|
||||
* <a href="http://www.xmlpull.org/v1/doc/properties.html">
|
||||
* http://www.xmlpull.org/v1/doc/properties.html</a>.
|
||||
*
|
||||
* If property is not recocgnized or can not be set
|
||||
* then IllegalStateException MUST be thrown.
|
||||
*
|
||||
* @exception IllegalStateException if the property is not supported or can not be set
|
||||
*/
|
||||
void setProperty(String name,
|
||||
Object value)
|
||||
throws IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Look up the value of a property.
|
||||
*
|
||||
* The property name is any fully-qualified URI. I
|
||||
* <p><strong>NOTE:</strong> unknown properties are <string>always</strong> returned as null
|
||||
*
|
||||
* @param name The name of property to be retrieved.
|
||||
* @return The value of named property.
|
||||
*/
|
||||
Object getProperty(String name);
|
||||
|
||||
/**
|
||||
* Set to use binary output stream with given encoding.
|
||||
*/
|
||||
void setOutput (OutputStream os, String encoding)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Set the output to the given writer.
|
||||
* <p><b>WARNING</b> no information about encoding is available!
|
||||
*/
|
||||
void setOutput (Writer writer)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Write <?xml declaration with encoding (if encoding not null)
|
||||
* and standalone flag (if standalone not null)
|
||||
* This method can only be called just after setOutput.
|
||||
*/
|
||||
void startDocument (String encoding, Boolean standalone)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Finish writing. All unclosed start tags will be closed and output
|
||||
* will be flushed. After calling this method no more output can be
|
||||
* serialized until next call to setOutput()
|
||||
*/
|
||||
void endDocument ()
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Binds the given prefix to the given namespace.
|
||||
* This call is valid for the next element including child elements.
|
||||
* The prefix and namespace MUST be always declared even if prefix
|
||||
* is not used in element (startTag() or attribute()) - for XML 1.0
|
||||
* it must result in declaring <code>xmlns:prefix='namespace'</code>
|
||||
* (or <code>xmlns:prefix="namespace"</code> depending what character is used
|
||||
* to quote attribute value).
|
||||
*
|
||||
* <p><b>NOTE:</b> this method MUST be called directly before startTag()
|
||||
* and if anything but startTag() or setPrefix() is called next there will be exception.
|
||||
* <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound
|
||||
* and can not be redefined see:
|
||||
* <a href="http://www.w3.org/XML/xml-names-19990114-errata#NE05">Namespaces in XML Errata</a>.
|
||||
* <p><b>NOTE:</b> to set default namespace use as prefix empty string.
|
||||
*
|
||||
* @param prefix must be not null (or IllegalArgumentException is thrown)
|
||||
* @param namespace must be not null
|
||||
*/
|
||||
void setPrefix (String prefix, String namespace)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Return namespace that corresponds to given prefix
|
||||
* If there is no prefix bound to this namespace return null
|
||||
* but if generatePrefix is false then return generated prefix.
|
||||
*
|
||||
* <p><b>NOTE:</b> if the prefix is empty string "" and defualt namespace is bound
|
||||
* to this prefix then empty string ("") is returned.
|
||||
*
|
||||
* <p><b>NOTE:</b> prefixes "xml" and "xmlns" are already bound
|
||||
* will have values as defined
|
||||
* <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML specification</a>
|
||||
*/
|
||||
String getPrefix (String namespace, boolean generatePrefix)
|
||||
throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the current depth of the element.
|
||||
* Outside the root element, the depth is 0. The
|
||||
* depth is incremented by 1 when startTag() is called.
|
||||
* The depth is decremented after the call to endTag()
|
||||
* event was observed.
|
||||
*
|
||||
* <pre>
|
||||
* <!-- outside --> 0
|
||||
* <root> 1
|
||||
* sometext 1
|
||||
* <foobar> 2
|
||||
* </foobar> 2
|
||||
* </root> 1
|
||||
* <!-- outside --> 0
|
||||
* </pre>
|
||||
*/
|
||||
int getDepth();
|
||||
|
||||
/**
|
||||
* Returns the namespace URI of the current element as set by startTag().
|
||||
*
|
||||
* <p><b>NOTE:</b> that measn in particaulr that: <ul>
|
||||
* <li>if there was startTag("", ...) then getNamespace() returns ""
|
||||
* <li>if there was startTag(null, ...) then getNamespace() returns null
|
||||
* </ul>
|
||||
*
|
||||
* @return namespace set by startTag() that is currently in scope
|
||||
*/
|
||||
String getNamespace ();
|
||||
|
||||
/**
|
||||
* Returns the name of the current element as set by startTag().
|
||||
* It can only be null before first call to startTag()
|
||||
* or when last endTag() is called to close first startTag().
|
||||
*
|
||||
* @return namespace set by startTag() that is currently in scope
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Writes a start tag with the given namespace and name.
|
||||
* If there is no prefix defined for the given namespace,
|
||||
* a prefix will be defined automatically.
|
||||
* The explicit prefixes for namespaces can be established by calling setPrefix()
|
||||
* immediately before this method.
|
||||
* If namespace is null no namespace prefix is printed but just name.
|
||||
* If namespace is empty string then serialzier will make sure that
|
||||
* default empty namespace is declared (in XML 1.0 xmlns='')
|
||||
* or throw IllegalStateException if default namespace is already bound
|
||||
* to non-empty string.
|
||||
*/
|
||||
XmlSerializer startTag (String namespace, String name)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Write an attribute. Calls to attribute() MUST follow a call to
|
||||
* startTag() immediately. If there is no prefix defined for the
|
||||
* given namespace, a prefix will be defined automatically.
|
||||
* If namespace is null or empty string
|
||||
* no namespace prefix is printed but just name.
|
||||
*/
|
||||
XmlSerializer attribute (String namespace, String name, String value)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Write end tag. Repetition of namespace and name is just for avoiding errors.
|
||||
* <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were
|
||||
* very difficult to find...
|
||||
* If namespace is null no namespace prefix is printed but just name.
|
||||
* If namespace is empty string then serialzier will make sure that
|
||||
* default empty namespace is declared (in XML 1.0 xmlns='').
|
||||
*/
|
||||
XmlSerializer endTag (String namespace, String name)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
|
||||
// /**
|
||||
// * Writes a start tag with the given namespace and name.
|
||||
// * <br />If there is no prefix defined (prefix == null) for the given namespace,
|
||||
// * a prefix will be defined automatically.
|
||||
// * <br />If explicit prefixes is passed (prefix != null) then it will be used
|
||||
// *and namespace declared if not already declared or
|
||||
// * throw IllegalStateException the same prefix was already set on this
|
||||
// * element (setPrefix()) and was bound to different namespace.
|
||||
// * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
|
||||
// * <br />If namespace is null then no namespace prefix is printed but just name.
|
||||
// * <br />If namespace is empty string then serializer will make sure that
|
||||
// * default empty namespace is declared (in XML 1.0 xmlns='')
|
||||
// * or throw IllegalStateException if default namespace is already bound
|
||||
// * to non-empty string.
|
||||
// */
|
||||
// XmlSerializer startTag (String prefix, String namespace, String name)
|
||||
// throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
//
|
||||
// /**
|
||||
// * Write an attribute. Calls to attribute() MUST follow a call to
|
||||
// * startTag() immediately.
|
||||
// * <br />If there is no prefix defined (prefix == null) for the given namespace,
|
||||
// * a prefix will be defined automatically.
|
||||
// * <br />If explicit prefixes is passed (prefix != null) then it will be used
|
||||
// * and namespace declared if not already declared or
|
||||
// * throw IllegalStateException the same prefix was already set on this
|
||||
// * element (setPrefix()) and was bound to different namespace.
|
||||
// * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
|
||||
// * <br />If namespace is null then no namespace prefix is printed but just name.
|
||||
// * <br />If namespace is empty string then serializer will make sure that
|
||||
// * default empty namespace is declared (in XML 1.0 xmlns='')
|
||||
// * or throw IllegalStateException if default namespace is already bound
|
||||
// * to non-empty string.
|
||||
// */
|
||||
// XmlSerializer attribute (String prefix, String namespace, String name, String value)
|
||||
// throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
//
|
||||
// /**
|
||||
// * Write end tag. Repetition of namespace, prefix, and name is just for avoiding errors.
|
||||
// * <br />If namespace or name arguments are different from corresponding startTag call
|
||||
// * then IllegalArgumentException is thrown, if prefix argument is not null and is different
|
||||
// * from corresponding starTag then IllegalArgumentException is thrown.
|
||||
// * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
|
||||
// * <br />If namespace is null then no namespace prefix is printed but just name.
|
||||
// * <br />If namespace is empty string then serializer will make sure that
|
||||
// * default empty namespace is declared (in XML 1.0 xmlns='').
|
||||
// * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were
|
||||
// * very difficult to find...</p>
|
||||
// */
|
||||
// ALEK: This is really optional as prefix in end tag MUST correspond to start tag but good for error checking
|
||||
// XmlSerializer endTag (String prefix, String namespace, String name)
|
||||
// throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Writes text, where special XML chars are escaped automatically
|
||||
*/
|
||||
XmlSerializer text (String text)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Writes text, where special XML chars are escaped automatically
|
||||
*/
|
||||
XmlSerializer text (char [] buf, int start, int len)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
void cdsect (String text)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
void entityRef (String text) throws IOException,
|
||||
IllegalArgumentException, IllegalStateException;
|
||||
void processingInstruction (String text)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
void comment (String text)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
void docdecl (String text)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
void ignorableWhitespace (String text)
|
||||
throws IOException, IllegalArgumentException, IllegalStateException;
|
||||
|
||||
/**
|
||||
* Write all pending output to the stream.
|
||||
* If method startTag() or attribute() was called then start tag is closed (final >)
|
||||
* before flush() is called on underlying output stream.
|
||||
*
|
||||
* <p><b>NOTE:</b> if there is need to close start tag
|
||||
* (so no more attribute() calls are allowed) but without flushinging output
|
||||
* call method text() with empty string (text("")).
|
||||
*
|
||||
*/
|
||||
void flush ()
|
||||
throws IOException;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user