summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Hudson <nick.hudson@isode.com>2013-10-18 15:07:53 (GMT)
committerNick Hudson <nick.hudson@isode.com>2013-10-30 14:30:24 (GMT)
commit14a773c38050d4af9c34c24e426b7a5460ad9735 (patch)
tree5af61e194487903f9266c88dcfe83eb5d31e3231
parentb2f5e0d7c7409ef78ff83708e9ba068f6f0ad535 (diff)
downloadstroke-14a773c38050d4af9c34c24e426b7a5460ad9735.zip
stroke-14a773c38050d4af9c34c24e426b7a5460ad9735.tar.bz2
Re-implement DNS lookup to use dnsjava rather than JNDI
There are limitations when using JNDI for DNS lookups, including that it does not properly handle the situation when resolv.conf contains IPv6 addresses (Isode bug #44832) - see e.g. http://java.net/jira/browse/JITSI-295 JNDI is also not readily available on Android, which makes it slightly more awkward to use Stroke on that platform. This patch changes the PlatformDomainName classes so that they use classes from dnsjava rather than JNDI. The patch also updates the build scripts so that dnsjava.jar is fetched (if necessary) and included in the build. Indentation in build.xml has been tidied up Test-information: Ran unit tests - ok Ran MLC - works OK and no longer throws NumberFormatExceptions when resolve.conf contains "nameserver 2001:470:f052::2" Change-Id: Iacf1105c52c281f9e59b60ea6caa011914b588dc
-rw-r--r--Makefile8
-rw-r--r--README2
-rw-r--r--build.xml79
-rw-r--r--src/com/isode/stroke/network/PlatformDomainNameResolver.java15
-rw-r--r--src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java88
5 files changed, 96 insertions, 96 deletions
diff --git a/Makefile b/Makefile
index 778e5ca..770e231 100644
--- a/Makefile
+++ b/Makefile
@@ -1,63 +1,67 @@
all: dist/lib/stroke.jar
-DEFINES = -Dxpp-dir=third-party/xpp -Djzlib-dir=third-party/jzlib -Dicu4j-dir=third-party/ -Dstax2-dir=third-party/stax2/ -Daalto-dir=third-party/aalto/
+DEFINES = -Dxpp-dir=third-party/xpp -Djzlib-dir=third-party/jzlib -Dicu4j-dir=third-party/ -Dstax2-dir=third-party/stax2/ -Daalto-dir=third-party/aalto/ -Ddnsjava-dir=third-party/dnsjava
JUNIT ?= /usr/share/junit/junit.jar
.PHONY : clean
clean:
ant clean
.PHONY : distclean
distclean: clean
ant distclean
rm -rf third-party
.PHONY : dist/lib/stroke.jar
-dist/lib/stroke.jar: third-party/jzlib/jzlib.jar third-party/icu4j.jar third-party/aalto/aalto-xml.jar third-party/stax2/stax2-api.jar
+dist/lib/stroke.jar: third-party/jzlib/jzlib.jar third-party/icu4j.jar third-party/aalto/aalto-xml.jar third-party/stax2/stax2-api.jar third-party/dnsjava/dnsjava.jar
ant ${DEFINES}
.PHONY : test
test: dist/lib/stroke.jar third-party/cobertura/cobertura.jar third-party/findbugs/lib/findbugs.jar third-party/pmd/lib/pmd-5.0.0.jar
ant ${DEFINES} -DJUNIT_JAR=${JUNIT} -Dcobertura-jar=third-party/cobertura/cobertura.jar -Djakarta-oro-jar=third-party/cobertura/lib/jakarta-oro-2.0.8.jar -Dlog4j-jar=third-party/cobertura/lib/log4j-1.2.9.jar -Dasm-jar=third-party/cobertura/lib/asm-3.0.jar -Dasm-tree-jar=third-party/cobertura/lib/asm-tree-3.0.jar -Dfindbugs.home=third-party/findbugs -Dpmd.home=third-party/pmd test
third-party/aalto/aalto-xml.jar:
mkdir -p third-party/aalto
curl http://repo2.maven.org/maven2/com/fasterxml/aalto-xml/0.9.8/aalto-xml-0.9.8.jar -o third-party/aalto/aalto-xml.jar
third-party/stax2/stax2-api.jar:
mkdir -p third-party/stax2
curl http://repository.codehaus.org/org/codehaus/woodstox/stax2-api/3.0.3/stax2-api-3.0.3.jar -o third-party/stax2/stax2-api.jar
third-party/jzlib/jzlib.jar:
mkdir -p third-party
curl http://www.jcraft.com/jzlib/jzlib-1.0.7.tar.gz -o third-party/jzlib-1.0.7.tar.gz
tar -xvzf third-party/jzlib-1.0.7.tar.gz -C third-party/
mv third-party/jzlib-1.0.7 third-party/jzlib
cp build-jzlib.xml third-party/jzlib/build.xml
ant -f third-party/jzlib/build.xml
third-party/icu4j.jar:
mkdir -p third-party
curl http://download.icu-project.org/files/icu4j/4.8.1/icu4j-4_8_1.jar -o third-party/icu4j.jar
+third-party/dnsjava/dnsjava.jar:
+ mkdir -p third-party/dnsjava
+ curl http://www.dnsjava.org/download/dnsjava-2.1.6.jar -o third-party/dnsjava/dnsjava.jar
+
third-party/cobertura/cobertura.jar:
mkdir -p third-party
curl -L 'http://sourceforge.net/projects/cobertura/files/cobertura/1.9.4.1/cobertura-1.9.4.1-bin.tar.bz2/download' -o third-party/cobertura-1.9.4.1-bin.tar.bz2
tar -xvjf third-party/cobertura-1.9.4.1-bin.tar.bz2 -C third-party/
mv third-party/cobertura-1.9.4.1 third-party/cobertura
third-party/findbugs/lib/findbugs.jar:
mkdir -p third-party
curl -L 'http://prdownloads.sourceforge.net/findbugs/findbugs-2.0.1.tar.gz?download' -o third-party/findbugs-2.0.1.tar.gz
tar -xvzf third-party/findbugs-2.0.1.tar.gz -C third-party/
mv third-party/findbugs-2.0.1 third-party/findbugs
third-party/pmd/lib/pmd-5.0.0.jar:
mkdir -p third-party
curl -L 'http://sourceforge.net/projects/pmd/files/pmd/5.0.0/pmd-bin-5.0.0.zip/download' -o third-party/pmd-bin-5.0.0.zip
unzip third-party/pmd-bin-5.0.0.zip -d third-party
mv third-party/pmd-bin-5.0.0 third-party/pmd
.git/hooks/commit-msg:
curl -k https://git.swift.im/review/tools/hooks/commit-msg -o .git/hooks/commit-msg
chmod u+x .git/hooks/commit-msg
diff --git a/README b/README
index 3aa671e..0574db7 100644
--- a/README
+++ b/README
@@ -1,22 +1,24 @@
Stroke
Stroke is a port of the C++ Swift library ( http://swift.im/swiften/ )
The source is available from the Git repository at http://swift.im/git/stroke/
For XML parsing, Stroke depends on the Aalto XML Parser and the STAX2 API, from http://wiki.fasterxml.com/AaltoHome
It also depends upon http://www.jcraft.com/jzlib/, which is passed to ant in the jzlib-dir parameter. The passed folder should contain a jar called jzlib.jar.
It also depends upon icu4j from http://site.icu-project.org/
+It also depends upon dnsjava from http://www.dnsjava.org/
+
To build, run:
ant -Dxpp-dir=third-party/xpp -Djzlib-dir=third-party/jzlib -Dicu4j-dir=third-party/ -Dstax2-dir=third-party/stax2/ -Daalto-dir=third-party/aalto/
Changing the paths to the relevant paths for the dependencies on your system
Easy version:
The included Makefile should, on Unixes with make/curl installed, grab the dependencies (once only) and build.
For development:
If you want to commit changes to Stroke, first run `make .git/hooks/commit-msg` to download a script that will generate change-ids needed by our review system.
diff --git a/build.xml b/build.xml
index 7fe424c..6c4058f 100644
--- a/build.xml
+++ b/build.xml
@@ -1,227 +1,228 @@
<!--
- * Copyright (c) 2010, Isode Limited, London, England.
+ * Copyright (c) 2010-2013, Isode Limited, London, England.
* All rights reserved.
-->
<project name="Stroke" default="dist" basedir=".">
<description>
XMPP Library porting Swiften to Java.
</description>
<property name="src" location="src"/>
<property name="doc" location="doc"/>
<property name="src.tests" location="test"/>
<property name="test.results" location="test-results"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<property name="jar" value="${dist}/lib/stroke.jar"/>
<property name="main-class" value="com.isode.stroke.examples.gui.StrokeGUI"/>
<property name="compile.debug" value="true"/>
<property name="testsuiteclass" value="com.isode.stroke.unittest.StrokeTestSuite" />
<property name="aalto-dir" value="../third-party/aalto"/>
<property name="stax2-dir" value="../third-party/stax2"/>
<property name="jzlib-dir" value="../third-party/jzlib"/>
<property name="icu4j-dir" value="../third-party/icu4j"/>
+ <property name="dnsjava-dir" value="../third-party/dnsjava"/>
<property name="cobertura.dir" value="instrumented"/>
<property name="coveragereport.dir" value="coverage"/>
<path id="cobertura.classpath">
- <pathelement path="${cobertura-jar}"/>
- <pathelement path="${jakarta-oro-jar}"/>
- <pathelement path="${log4j-jar}"/>
- <pathelement path="${asm-jar}"/>
- <pathelement path="${asm-tree-jar}"/>
+ <pathelement path="${cobertura-jar}"/>
+ <pathelement path="${jakarta-oro-jar}"/>
+ <pathelement path="${log4j-jar}"/>
+ <pathelement path="${asm-jar}"/>
+ <pathelement path="${asm-tree-jar}"/>
</path>
<taskdef classpathref="cobertura.classpath" resource="tasks.properties"/>
<path id="classpath">
<fileset dir="${aalto-dir}" includes="aalto-xml.jar"/>
<fileset dir="${stax2-dir}" includes="stax2-api.jar"/>
<fileset dir="${jzlib-dir}" includes="jzlib.jar"/>
<fileset dir="${icu4j-dir}" includes="icu4j.jar"/>
+ <fileset dir="${dnsjava-dir}" includes="dnsjava.jar"/>
</path>
<target name="init">
<tstamp/>
<mkdir dir="${build}"/>
</target>
<target name="-compile-with-examples" depends="init"
description="compile the source, including examples "
unless="noexamples">
<javac srcdir="${src}" destdir="${build}" classpathref="classpath"
debug="${compile.debug}"
source="1.6"
target="1.6">
<compilerarg line="-encoding utf-8"/>
</javac>
</target>
<target name="-compile-without-examples" depends="init"
description="compile the source, excluding examples "
if="noexamples">
<javac srcdir="${src}" destdir="${build}" classpathref="classpath"
debug="${compile.debug}"
source="1.6"
target="1.6">
<exclude name="com/isode/stroke/examples/**"/>
<compilerarg line="-encoding utf-8"/>
</javac>
</target>
<target name="dist" depends="-dist-with-examples,-dist-without-examples"/>
<target name="-dist-with-examples" depends="-compile-with-examples"
description="generate the distribution including examples"
unless="noexamples">
<mkdir dir="${dist}/lib"/>
<jar jarfile="${jar}" basedir="${build}">
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
</manifest>
</jar>
</target>
<target name="-dist-without-examples" depends="-compile-without-examples"
description="generate the distribution excluding examples"
if="noexamples">
<mkdir dir="${dist}/lib"/>
<jar jarfile="${jar}" basedir="${build}">
</jar>
</target>
-<target name="compile-tests" depends="dist"
+ <target name="compile-tests" depends="dist"
description="compile the test sources " >
<javac srcdir="${src.tests}" destdir="${src.tests}"
debug="${compile.debug}"
source="1.6"
target="1.6">
<compilerarg line="-encoding utf-8"/>
<classpath>
<pathelement location="${jar}"/>
<pathelement location="${JUNIT_JAR}"/>
</classpath>
</javac>
</target>
<target name="instrument" if="cobertura-jar" depends="compile-tests">
<delete dir="${cobertura.dir}"/>
<mkdir dir="${cobertura.dir}"/>
<cobertura-instrument todir="${cobertura.dir}">
<fileset dir="test">
<include name="**/*.class"/>
</fileset>
</cobertura-instrument>
</target>
<target name="run-tests" depends="compile-tests">
<delete dir="${test.results}"/>
<mkdir dir="${test.results}"/>
<junit fork="yes">
- <formatter type="xml"/>
- <classpath>
- <pathelement location="${cobertura.dir}"/>
- <path refid="cobertura.classpath"/>
- </classpath>
- <classpath>
- <pathelement location="${JUNIT_JAR}"/>
- <pathelement location="${jar}"/>
- <pathelement location="${src.tests}"/>
- <path refid="classpath"/>
- </classpath>
- <batchtest todir="${test.results}">
- <fileset dir="${src.tests}">
- <include name="**/*Test.java"/>
- <!--<exclude name="**/AllTests.java"/>-->
- </fileset>
- </batchtest>
+ <formatter type="xml"/>
+ <classpath>
+ <pathelement location="${cobertura.dir}"/>
+ <path refid="cobertura.classpath"/>
+ </classpath>
+ <classpath>
+ <pathelement location="${JUNIT_JAR}"/>
+ <pathelement location="${jar}"/>
+ <pathelement location="${src.tests}"/>
+ <path refid="classpath"/>
+ </classpath>
+ <batchtest todir="${test.results}">
+ <fileset dir="${src.tests}">
+ <include name="**/*Test.java"/>
+ <!--<exclude name="**/AllTests.java"/>-->
+ </fileset>
+ </batchtest>
</junit>
-
</target>
<target name="coverage" if="cobertura-jar" depends="instrument, run-tests">
<delete dir="${coveragereport.dir}"/>
<mkdir dir="${coveragereport.dir}"/>
<cobertura-report format="xml" destdir="${coveragereport.dir}">
- <fileset dir="${src}">
- <include name="**/*.java"/>
- </fileset>
- <fileset dir="${src.tests}">
- <include name="**/*.java"/>
- </fileset>
+ <fileset dir="${src}">
+ <include name="**/*.java"/>
+ </fileset>
+ <fileset dir="${src.tests}">
+ <include name="**/*.java"/>
+ </fileset>
</cobertura-report>
</target>
<target name="findbugs" if="findbugs.home" depends="dist">
<path id="findbugs-jar">
<pathelement path="${findbugs.home}/lib/findbugs-ant.jar" />
</path>
<taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask" classpathref="findbugs-jar" />
<findbugs home="${findbugs.home}"
output="xml"
outputFile="findbugs.xml" >
<auxClasspath>
<path refid="classpath" />
</auxClasspath>
<sourcePath path="${src}" />
<class location="${jar}" />
</findbugs>
</target>
<target name="pmd">
<path id="pmd-jar">
<fileset dir="${pmd.home}/lib">
<include name="*.jar" />
</fileset>
</path>
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpathref="pmd-jar"/>
<pmd shortFilenames="true">
<ruleset>pmd-ruleset.xml</ruleset>
<formatter type="xml" toFile="pmd.xml" />
<fileset dir="${src}">
<include name="**/*.java"/>
</fileset>
</pmd>
</target>
<target name="test" depends="compile-tests, instrument, run-tests, coverage, findbugs, pmd">
</target>
<target name="clean"
- description="clean up" >
+ description="clean up" >
<delete dir="${build}"/>
<delete dir="${test.results}"/>
<delete dir="${dist}"/>
<delete dir="${doc}"/>
<delete dir="${coveragereport.dir}"/>
<delete dir="${cobertura.dir}"/>
</target>
<target name="javadoc" depends="init">
<!-- Note that this may stall if no network connection is available
to the Oracle website -->
<javadoc packagenames="com.isode.**.**"
sourcepath="${src}"
destdir="${doc}"
windowtitle="Stroke">
<!--<classpath>
<fileset dir="${xpp-dir}" includes="xpp.jar"/>
</classpath>-->
- <link href="http://docs.oracle.com/javase/6/docs/api/"/>
+ <link href="http://docs.oracle.com/javase/6/docs/api/"/>
</javadoc>
</target>
<target name="run" description="Run the demo" depends="dist">
- <java fork="true" classname="${main-class}">
- <classpath>
- <path refid="classpath"/>
- <path location="${jar}"/>
- </classpath>
- </java>
+ <java fork="true" classname="${main-class}">
+ <classpath>
+ <path refid="classpath"/>
+ <path location="${jar}"/>
+ </classpath>
+ </java>
</target>
</project>
diff --git a/src/com/isode/stroke/network/PlatformDomainNameResolver.java b/src/com/isode/stroke/network/PlatformDomainNameResolver.java
index 3eef682..32f466d 100644
--- a/src/com/isode/stroke/network/PlatformDomainNameResolver.java
+++ b/src/com/isode/stroke/network/PlatformDomainNameResolver.java
@@ -1,69 +1,72 @@
/*
- * Copyright (c) 2010-2012, Isode Limited, London, England.
+ * Copyright (c) 2010-2013, Isode Limited, London, England.
* All rights reserved.
*/
/*
* Copyright (c) 2010, Remko Tronçon.
* All rights reserved.
*/
package com.isode.stroke.network;
import com.isode.stroke.eventloop.Event.Callback;
import com.isode.stroke.eventloop.EventLoop;
import com.isode.stroke.eventloop.EventOwner;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
+import org.xbill.DNS.Address;
+
public class PlatformDomainNameResolver extends DomainNameResolver {
private class AddressQuery extends DomainNameAddressQuery implements EventOwner {
private class AddressQueryThread extends Thread {
@Override
public void run() {
final Collection<HostAddress> results = new ArrayList<HostAddress>();
try {
- for (InetAddress result : InetAddress.getAllByName(hostname)) {
+ for (InetAddress result : Address.getAllByName(hostname)) {
results.add(new HostAddress(result));
}
} catch (UnknownHostException ex) {
+ /* results remains empty */
}
eventLoop.postEvent(new Callback() {
public void run() {
onResult.emit(results, results.isEmpty() ? new DomainNameResolveError() : null);
}
});
}
}
AddressQuery(String host, EventLoop eventLoop) {
hostname = host;
this.eventLoop = eventLoop;
}
public void run() {
AddressQueryThread thread = new AddressQueryThread();
thread.setDaemon(true);
thread.start();
}
final String hostname;
final EventLoop eventLoop;
}
public PlatformDomainNameResolver(EventLoop eventLoop) {
- this.eventLoop = eventLoop;
+ this.eventLoop_ = eventLoop;
}
@Override
public DomainNameServiceQuery createServiceQuery(String name) {
- return new PlatformDomainNameServiceQuery(getNormalized(name), eventLoop);
+ return new PlatformDomainNameServiceQuery(getNormalized(name), eventLoop_);
}
@Override
public DomainNameAddressQuery createAddressQuery(String name) {
- return new AddressQuery(getNormalized(name), eventLoop);
+ return new AddressQuery(getNormalized(name), eventLoop_);
}
- private final EventLoop eventLoop;
+ private final EventLoop eventLoop_;
}
diff --git a/src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java b/src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java
index 0fc7976..37cf1f2 100644
--- a/src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java
+++ b/src/com/isode/stroke/network/PlatformDomainNameServiceQuery.java
@@ -1,87 +1,77 @@
/*
- * Copyright (c) 2010-2012, Isode Limited, London, England.
+ * Copyright (c) 2010-2013, Isode Limited, London, England.
* All rights reserved.
*/
/*
* Copyright (c) 2010 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
package com.isode.stroke.network;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.xbill.DNS.Lookup;
+import org.xbill.DNS.Record;
+import org.xbill.DNS.SRVRecord;
+import org.xbill.DNS.TextParseException;
+import org.xbill.DNS.Type;
import com.isode.stroke.eventloop.Event.Callback;
import com.isode.stroke.eventloop.EventLoop;
-import com.isode.stroke.eventloop.EventOwner;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Hashtable;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
+import com.isode.stroke.network.DomainNameServiceQuery;
-public class PlatformDomainNameServiceQuery extends DomainNameServiceQuery implements EventOwner {
+public class PlatformDomainNameServiceQuery extends DomainNameServiceQuery {
+ private final String service;
+ private final EventLoop eventLoop;
- private class QueryThread extends Thread {
+ public PlatformDomainNameServiceQuery(final String service, final EventLoop eventLoop) {
+ this.service = service;
+ this.eventLoop = eventLoop;
+ }
+ private class QueryThread extends Thread {
@Override
public void run() {
final Collection<Result> results = new ArrayList<Result>();
- Hashtable env = new Hashtable();
- env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
- env.put("java.naming.provider.url", "dns:");
- DirContext ctx = null;
+ Lookup request;
try {
- ctx = new InitialDirContext(env);
- Attributes attrs = ctx.getAttributes(service, new String[]{"SRV"});
- Attribute attribute = attrs.get("SRV");
- for (int i = 0; attribute != null && i < attribute.size(); i++) {
- /* SRV results are going to be returned in the space-separated format
- * Priority Weight Port Target
- * (See RFC2782)
- */
- String[] srvParts = ((String) attribute.get(i)).split(" ");
- String host = srvParts[3];
- if (host.endsWith(".")) {
- host = host.substring(0, host.length() - 1);
+ request = new Lookup(service, Type.SRV);
+ final Record[] records = request.run();
+ if (records != null) {
+ for (final Record record : records) {
+ /* It's only anticipated that SRVRecords will be
+ * returned, but check first
+ */
+ if (record instanceof SRVRecord) {
+ final SRVRecord srv = (SRVRecord) record;
+ final Result result = new Result(srv.getTarget()
+ .toString(), srv.getPort(), srv.getPriority(),
+ srv.getWeight());
+ results.add(result);
+ }
}
- Result result = new Result(host, Integer.parseInt(srvParts[2]), Integer.parseInt(srvParts[0]), Integer.parseInt(srvParts[1]));
- results.add(result);
}
- } catch (NamingException ex) {
- /* Turns out that you get the exception just for not finding a result, so we want to fall through to A lookups and ignore.*/
+ } catch (final TextParseException e) {
+ /* Lookup failed because "service" was not a valid DNS name;
+ * leave "results" empty
+ */
}
eventLoop.postEvent(new Callback() {
+ @Override
public void run() {
onResult.emit(results);
}
});
- //close the context as otherwise this will lead to open sockets in
- //CLOSE_WAIT condition
- if(ctx != null) {
- try {
- ctx.close();
- } catch (NamingException e) {
- //at least we try to close the context
- }
- }
}
}
- public PlatformDomainNameServiceQuery(String service, EventLoop eventLoop) {
- this.service = service;
- this.eventLoop = eventLoop;
- }
-
@Override
public void run() {
- QueryThread thread = new QueryThread();
+ final QueryThread thread = new QueryThread();
thread.setDaemon(true);
thread.start();
}
- private final String service;
- private final EventLoop eventLoop;
}