summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Greig <rgreig@apache.org>2007-02-20 16:51:32 +0000
committerRobert Greig <rgreig@apache.org>2007-02-20 16:51:32 +0000
commit53dfa7e61494fc38de8b527a91dfdb6051260e2a (patch)
tree9c36100358f74974f5c5b544d8c09b5053aa6d6d
parent797b61fa56e3576e4a85780e7e8bdc20e6833d75 (diff)
downloadqpid-python-53dfa7e61494fc38de8b527a91dfdb6051260e2a.tar.gz
(Path submitted by Rupert Smith) Qpid-338. Custom SASL implementation for Java 1.4 retrotranslation of the Java client.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@509642 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--java/client-java14/README.txt33
-rw-r--r--java/client-java14/client-java14.iml469
-rw-r--r--java/client-java14/etc/sasl.properties20
-rw-r--r--java/client-java14/pom.xml152
-rw-r--r--java/client-java14/src/main/assembly/client-java14-bin.xml69
-rw-r--r--java/client-java14/src/main/java/org/apache/qpid/sasl/ClientFactoryImpl.java343
-rw-r--r--java/client-java14/src/main/java/org/apache/qpid/sasl/CramMD5Client.java349
-rw-r--r--java/client-java14/src/main/java/org/apache/qpid/sasl/PlainClient.java277
-rw-r--r--java/client-java14/src/main/java/org/apache/qpid/sasl/Provider.java61
-rw-r--r--java/client-java14/src/test/java/org/apache/qpid/test/integration/client/ConnectionTest.java66
-rw-r--r--java/client/distribution/pom.xml15
-rw-r--r--java/client/pom.xml107
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java71
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java103
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java99
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java36
-rw-r--r--java/common/pom.xml74
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/FileUtils.java161
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/PrettyPrintingUtils.java73
-rw-r--r--java/pom.xml188
21 files changed, 2514 insertions, 256 deletions
diff --git a/java/client-java14/README.txt b/java/client-java14/README.txt
new file mode 100644
index 0000000000..66621c7eb2
--- /dev/null
+++ b/java/client-java14/README.txt
@@ -0,0 +1,33 @@
+An implementation of SASL is provided here, for the PLAIN and CRAM-MD5 mechanisms as well as maven assembly
+instructions for producing a backported Java client for Java 1.4. In order to use the custom SASL implementation
+on JRE 1.4 the following steps must be taken:
+
+ * Install the SASL JSR-28 API jar.
+ * Install the qpid-client-java14 jar or set it up as a dynamically registered SASL provider.
+ * Set up java.security to add the SASL provider to the list of security providers if hte SASL implemenation jar was installed as an extension.
+
+Installing the SASL JSR-28 API jar.
+
+ Download, http://www.worldspot.com/jsr28/v1.1/download/sasl.jar, and copy it to the JAVA_HOME\lib\ext directory.
+
+Install or set up the qpid-client-java14 jar.
+
+ Copy the output jar for this project, qpid-client-java14-1.0-incubating-M2-SNAPSHOT.jar, to JAVA_HOME\lib\ext.
+
+ OR
+
+ Create a properties file and register the SASL implementations in the jar so that Qpids dynamic SASL registry can find them. In a properties file
+ add the lines:
+
+ PLAIN=org.apache.qpid.sasl.ClientFactoryImpl
+ CRAM-MD5=org.apache.qpid.sasl.ClientFactoryImpl
+
+ Place this somewhere on the classpath and put the qpid-client-java14-1.0-incubating-M2-SNAPSHOT.jar on the classpath too. When starting your application
+ pass in the system property amq.dynamicsaslregistrar.properties and set it to point to the location of the properties file.
+
+Set up the SASL provider.
+
+ You only need to do this if the custom SASL jar, qpid-client-java14-1.0-incubating-M2-SNAPSHOT.jar, was copied to JAVA_HOME\lib\ext.
+ Add the following line to JAVA_HOME\lib\security\java.security file (where n is the providers preference order):
+
+ security.provider.n=org.apache.qpid.sasl.Provider \ No newline at end of file
diff --git a/java/client-java14/client-java14.iml b/java/client-java14/client-java14.iml
new file mode 100644
index 0000000000..3ae83132fa
--- /dev/null
+++ b/java/client-java14/client-java14.iml
@@ -0,0 +1,469 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="JAVA_MODULE">
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager">
+ <output url="file://$MODULE_DIR$/target/classes" />
+ <exclude-output />
+ <exclude-exploded />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="qpid-client" />
+ <orderEntry type="module" module-name="qpid-common" />
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/concurrent/concurrent/1.3.2/concurrent-1.3.2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/junit/junit/3.8.1/junit-3.8.1-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/relaxngDatatype/relaxngDatatype/20020414/relaxngDatatype-20020414.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/relaxngDatatype/relaxngDatatype/20020414/relaxngDatatype-20020414-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/apache/mina/mina-core/1.0.0/mina-core-1.0.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/apache/mina/mina-core/1.0.0/mina-core-1.0.0-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/isorelax/isorelax/20020414/isorelax-20020414.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/isorelax/isorelax/20020414/isorelax-20020414-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/log4j/log4j/1.2.12/log4j-1.2.12.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/xdoclet/xdoclet-xjavadoc-uc/1.2b2/xdoclet-xjavadoc-uc-1.2b2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/xdoclet/xdoclet-xdoclet-module/1.2b2/xdoclet-xdoclet-module-1.2b2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-lang/commons-lang/2.1/commons-lang-2.1.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-lang/commons-lang/2.1/commons-lang-2.1-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-lang/commons-lang/2.1/commons-lang-2.1-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-collections/commons-collections/3.1/commons-collections-3.1.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-collections/commons-collections/3.1/commons-collections-3.1-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-collections/commons-collections/3.1/commons-collections-3.1-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-digester/commons-digester/1.6/commons-digester-1.6.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-digester/commons-digester/1.6/commons-digester-1.6-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-digester/commons-digester/1.6/commons-digester-1.6-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/xerces/xercesImpl/2.3.0/xercesImpl-2.3.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-cli/commons-cli/1.0/commons-cli-1.0.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-cli/commons-cli/1.0/commons-cli-1.0-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-cli/commons-cli/1.0/commons-cli-1.0-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/easymock/easymock/2.2/easymock-2.2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/easymock/easymock/2.2/easymock-2.2-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/msv/msv/20020414/msv-20020414.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/msv/msv/20020414/msv-20020414-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/backport-util-concurrent/backport-util-concurrent/2.2/backport-util-concurrent-2.2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/backport-util-concurrent/backport-util-concurrent/2.2/backport-util-concurrent-2.2-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-codec/commons-codec/1.3/commons-codec-1.3.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-codec/commons-codec/1.3/commons-codec-1.3-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-codec/commons-codec/1.3/commons-codec-1.3-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/apache/mina/mina-filter-ssl/1.0.0/mina-filter-ssl-1.0.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/apache/mina/mina-filter-ssl/1.0.0/mina-filter-ssl-1.0.0-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/apache/geronimo/specs/geronimo-jms_1.1_spec/1.0/geronimo-jms_1.1_spec-1.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/oro/oro/2.0.7/oro-2.0.7.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/javax/servlet/servlet-api/2.3/servlet-api-2.3.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/javax/servlet/servlet-api/2.3/servlet-api-2.3-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/xalan/xalan/2.5.1/xalan-2.5.1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/xalan/xalan/2.5.1/xalan-2.5.1-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/easymock/easymockclassextension/2.2/easymockclassextension-2.2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/easymock/easymockclassextension/2.2/easymockclassextension-2.2-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-configuration/commons-configuration/1.2/commons-configuration-1.2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-configuration/commons-configuration/1.2/commons-configuration-1.2-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/exolabcore/exolabcore/0.3.7/exolabcore-0.3.7.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/apache/mina/mina-java5/1.0.0/mina-java5-1.0.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/apache/mina/mina-java5/1.0.0/mina-java5-1.0.0-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/ant/ant/1.5.3-1/ant-1.5.3-1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/ant/ant/1.5.3-1/ant-1.5.3-1-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/jaxen/jaxen/1.0-FCS/jaxen-1.0-FCS.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/jaxen/jaxen/1.0-FCS/jaxen-1.0-FCS-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/jaxen/jaxen/1.0-FCS/jaxen-1.0-FCS-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/xdoclet/xdoclet/1.2b2/xdoclet-1.2b2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/slf4j/slf4j-simple/1.0/slf4j-simple-1.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/org/slf4j/slf4j-simple/1.0/slf4j-simple-1.0-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/castor/castor/0.9.5/castor-0.9.5.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/castor/castor/0.9.5/castor-0.9.5-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-beanutils/commons-beanutils/1.6/commons-beanutils-1.6.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-beanutils/commons-beanutils/1.6/commons-beanutils-1.6-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-beanutils/commons-beanutils-core/1.7.0/commons-beanutils-core-1.7.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/ant/ant-optional/1.5.3-1/ant-optional-1.5.3-1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/dom4j/dom4j/1.4/dom4j-1.4.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/dom4j/dom4j/1.4/dom4j-1.4-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/saxpath/saxpath/1.0-FCS/saxpath-1.0-FCS.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/saxpath/saxpath/1.0-FCS/saxpath-1.0-FCS-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/saxpath/saxpath/1.0-FCS/saxpath-1.0-FCS-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/jmscts/jmscts/0.5-b2/jmscts-0.5-b2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../.m2/repository/net/sf/retrotranslator/retrotranslator-runtime/1.2.1/retrotranslator-runtime-1.2.1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntryProperties />
+ </component>
+</module>
+
diff --git a/java/client-java14/etc/sasl.properties b/java/client-java14/etc/sasl.properties
new file mode 100644
index 0000000000..04519e2a30
--- /dev/null
+++ b/java/client-java14/etc/sasl.properties
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+PLAIN=org.apache.qpid.sasl.ClientFactoryImpl
+CRAM-MD5=org.apache.qpid.sasl.ClientFactoryImpl
diff --git a/java/client-java14/pom.xml b/java/client-java14/pom.xml
new file mode 100644
index 0000000000..cf45250f94
--- /dev/null
+++ b/java/client-java14/pom.xml
@@ -0,0 +1,152 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-client-java14</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0-incubating-M2-SNAPSHOT</version>
+ <name>Qpid Client for Java 1.4</name>
+ <url>http://cwiki.apache.org/confluence/display/qpid</url>
+
+ <parent>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid</artifactId>
+ <version>1.0-incubating-M2-SNAPSHOT</version>
+ </parent>
+
+ <properties>
+ <topDirectoryLocation>..</topDirectoryLocation>
+ <java.source.version>1.4</java.source.version>
+ <qpid.version>${pom.version}</qpid.version>
+ <qpid.targetDir>${project.build.directory}</qpid.targetDir>
+ <qpid.root>${basedir}/..</qpid.root>
+ <sasl.properties>${basedir}/etc/sasl.properties</sasl.properties>
+ <jvm.1.4.bin>path/to/java1.4</jvm.1.4.bin>
+ </properties>
+
+ <dependencies>
+
+ <!-- Use the java 1.4 retrotranslated client. -->
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-client</artifactId>
+ <type>jar</type>
+ <version>${pom.version}</version>
+ <classifier>java14</classifier>
+ </dependency>
+
+ <!-- Use the java 1.4 retrotranslated common library. -->
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-common</artifactId>
+ <type>jar</type>
+ <version>${pom.version}</version>
+ <classifier>java14</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>net.sf.retrotranslator</groupId>
+ <artifactId>retrotranslator-runtime</artifactId>
+ <scope>package</scope>
+ </dependency>
+
+ <!-- Test dependencies. -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <!-- Sets up the compiler plugin to compile on 1.4 -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>${java.source.version}</source>
+ <target>${java.source.version}</target>
+ </configuration>
+ </plugin>
+
+ <!-- Sets up the assembly plugin to use the assembly directions to build a 1.4 compatable client. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>${assembly.version}</version>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/client-java14-bin.xml</descriptor>
+ </descriptors>
+ <finalName>qpid-${pom.version}</finalName>
+ <outputDirectory>${qpid.targetDir}</outputDirectory>
+ <tarLongFileMode>gnu</tarLongFileMode>
+ </configuration>
+ </plugin>
+
+ <!-- Sets up surefire to run during the integration-test phase instead of the test phase. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ <executions>
+ <execution>
+ <id>surefire-it</id>
+ <phase>integration-test</phase>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <skip>false</skip>
+ <forkMode>once</forkMode>
+ <jvm>${jvm.1.4.bin}</jvm>
+ <systemProperties>
+ <property>
+ <name>amqj.logging.level</name>
+ <value>${amqj.logging.level}</value>
+ </property>
+ <property>
+ <name>log4j.configuration</name>
+ <value>${log4j.configuration}</value>
+ </property>
+ <property>
+ <name>amq.dynamicsaslregistrar.properties</name>
+ <value>${sasl.properties}</value>
+ </property>
+ </systemProperties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/java/client-java14/src/main/assembly/client-java14-bin.xml b/java/client-java14/src/main/assembly/client-java14-bin.xml
new file mode 100644
index 0000000000..87c7f498f9
--- /dev/null
+++ b/java/client-java14/src/main/assembly/client-java14-bin.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<!-- Assembly instructions for a client that runs on Java 1.4 -->
+<assembly>
+ <id>java-client-java14-bin</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+
+ <fileSets>
+ <fileSet>
+ <!-- Apache license files -->
+ <directory>../resources</directory>
+ <outputDirectory>qpid-${qpid.version}</outputDirectory>
+ <includes>
+ <include>DISCLAIMER</include>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ <include>README.txt</include>
+ </includes>
+ </fileSet>
+
+ <fileSet>
+ <directory>../release-docs</directory>
+ <outputDirectory>qpid-${qpid.version}/docs</outputDirectory>
+ <includes>
+ <include>RELEASE_NOTES.txt</include>
+ </includes>
+ </fileSet>
+
+ </fileSets>
+
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>qpid-${qpid.version}/lib</outputDirectory>
+ <unpack>false</unpack>
+ <excludes>
+ <!-- Exclude the Java 5 built client and common. The java 1.4 retrotranslated versions are used instead. -->
+ <exclude>org.apache.qpid:qpid-client:jar</exclude>
+ <exclude>org.apache.qpid:qpid-common:jar</exclude>
+
+ <!-- Mina SSL support only available in Java 5. No SSL on 1.4. -->
+ <exclude>org.apache.mina:mina-java5</exclude>
+ <exclude>org.apache.mina:mina-filter-ssl</exclude>
+ </excludes>
+ </dependencySet>
+ </dependencySets>
+</assembly>
+
+
diff --git a/java/client-java14/src/main/java/org/apache/qpid/sasl/ClientFactoryImpl.java b/java/client-java14/src/main/java/org/apache/qpid/sasl/ClientFactoryImpl.java
new file mode 100644
index 0000000000..691020307a
--- /dev/null
+++ b/java/client-java14/src/main/java/org/apache/qpid/sasl/ClientFactoryImpl.java
@@ -0,0 +1,343 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sasl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.security.auth.callback.*;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslClientFactory;
+import javax.security.sasl.SaslException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.util.PrettyPrintingUtils;
+
+/**
+ * Implements a factory for generating Sasl client implementations.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a list of supported encryption mechansims that meet a defined set of Sasl properties.
+ * <tr><td> Provide the best matching supported Sasl mechanism to a preference ordered list of mechanisms and Sasl
+ * properties.
+ * <tr><td> Perform username and password request call backs. <td> CallBackHandler
+ * </table>
+ */
+public class ClientFactoryImpl implements SaslClientFactory
+{
+ //private static final Logger log = Logger.getLogger(ClientFactoryImpl.class);
+
+ /** Holds the names of the supported encryption mechanisms. */
+ private static final String[] SUPPORTED_MECHANISMS = { "CRAM-MD5", "PLAIN" };
+
+ /** Defines index of the CRAM-MD5 mechanism within the supported mechanisms. */
+ private static final int CRAM_MD5 = 0;
+
+ /** Defines index of the PLAIN mechanism within the supported mechanisms. */
+ private static final int PLAIN = 1;
+
+ /** Bit mapping of the no plain text policy. */
+ private static final int NOPLAINTEXT = 0x0001;
+
+ /** Bit mapping of the no susceptible active attacks policy. */
+ private static final int NOACTIVE = 0x0002;
+
+ /** Bit mapping of the no susceptible to dictionary attacks policy. */
+ private static final int NODICTIONARY = 0x0004;
+
+ /** Bit mapping of the must use forward secrecy between sessions policy. */
+ private static final int FORWARD_SECRECY = 0x0008;
+
+ /** Bit mapping of the no anonymous logins policy. */
+ private static final int NOANONYMOUS = 0x0010;
+
+ /** Bit mapping of the must pass credentials policy. */
+ private static final int PASS_CREDENTIALS = 0x0020;
+
+ /** Defines a mapping from supported mechanisms to supported policy flags. */
+ private static final int[] SUPPPORTED_MECHANISMS_POLICIES =
+ {
+ NOPLAINTEXT | NOANONYMOUS, // CRAM-MD5
+ NOANONYMOUS // PLAIN
+ };
+
+ /**
+ * Creates a SaslClient using the parameters supplied.
+ *
+ * @param mechanisms The non-null list of mechanism names to try. Each is the IANA-registered name of a SASL
+ * mechanism. (e.g. "GSSAPI", "CRAM-MD5").
+ * @param authorizationId The possibly null protocol-dependent identification to be used for authorization.
+ * If null or empty, the server derives an authorization ID from the client's authentication
+ * credentials. When the SASL authentication completes successfully, the specified entity is
+ * granted access.
+ * @param protocol The non-null string name of the protocol for which the authentication is being performed
+ * (e.g., "ldap").
+ * @param serverName The non-null fully qualified host name of the server to authenticate to.
+ * @param props The possibly null set of properties used to select the SASL mechanism and to configure the
+ * authentication exchange of the selected mechanism. See the <tt>Sasl</tt> class for a list
+ * of standard properties. Other, possibly mechanism-specific, properties can be included.
+ * Properties not relevant to the selected mechanism are ignored.
+ * @param cbh The possibly null callback handler to used by the SASL mechanisms to get further
+ * information from the application/library to complete the authentication. For example, a
+ * SASL mechanism might require the authentication ID, password and realm from the caller.
+ * The authentication ID is requested by using a <tt>NameCallback</tt>.
+ * The password is requested by using a <tt>PasswordCallback</tt>.
+ * The realm is requested by using a <tt>RealmChoiceCallback</tt> if there is a list
+ * of realms to choose from, and by using a <tt>RealmCallback</tt> if
+ * the realm must be entered.
+ *
+ * @return A possibly null <tt>SaslClient</tt> created using the parameters supplied. If null, this factory cannot
+ * produce a <tt>SaslClient</tt> using the parameters supplied.
+ *
+ * @throws javax.security.sasl.SaslException If cannot create a <tt>SaslClient</tt> because of an error.
+ */
+ public SaslClient createSaslClient(String[] mechanisms, String authorizationId, String protocol, String serverName,
+ Map props, CallbackHandler cbh) throws SaslException
+ {
+ /*log.debug("public SaslClient createSaslClient(String[] mechanisms = " + PrettyPrintingUtils.printArray(mechanisms)
+ + ", String authorizationId = " + authorizationId + ", String protocol = " + protocol
+ + ", String serverName = " + serverName + ", Map props = " + props + ", CallbackHandler cbh): called");*/
+
+ // Get a list of all supported mechanisms that matched the required properties.
+ String[] matchingMechanisms = getMechanismNames(props);
+ //log.debug("matchingMechanisms = " + PrettyPrintingUtils.printArray(matchingMechanisms));
+
+ // Scan down the list of mechanisms until the first one that matches one of the matching supported mechanisms
+ // is found.
+ String chosenMechanism = null;
+
+ for (int i = 0; i < mechanisms.length; i++)
+ {
+ String mechanism = mechanisms[i];
+
+ for (int j = 0; j < matchingMechanisms.length; j++)
+ {
+ String matchingMechanism = matchingMechanisms[j];
+
+ if (mechanism.equals(matchingMechanism))
+ {
+ chosenMechanism = mechanism;
+
+ break;
+ }
+ }
+
+ // Stop scanning if a match has been found.
+ if (chosenMechanism != null)
+ {
+ break;
+ }
+ }
+
+ // Check that a matching mechanism was found or return null otherwise.
+ if (chosenMechanism == null)
+ {
+ //log.debug("No matching mechanism could be found.");
+
+ return null;
+ }
+
+ // Instantiate an appropriate client type for the chosen mechanism.
+ if (chosenMechanism.equals(SUPPORTED_MECHANISMS[CRAM_MD5]))
+ {
+ Object[] uinfo = getUserInfo("CRAM-MD5", authorizationId, cbh);
+
+ //log.debug("Using CRAM-MD5 mechanism.");
+
+ return new CramMD5Client((String) uinfo[0], (byte[]) uinfo[1]);
+ }
+ else
+ {
+ Object[] uinfo = getUserInfo("PLAIN", authorizationId, cbh);
+
+ //log.debug("Using PLAIN mechanism.");
+
+ return new PlainClient(authorizationId, (String) uinfo[0], (byte[]) uinfo[1]);
+ }
+ }
+
+ /**
+ * Returns an array of names of mechanisms that match the specified
+ * mechanism selection policies.
+ *
+ * @param props The possibly null set of properties used to specify the
+ * security policy of the SASL mechanisms. For example, if <tt>props</tt>
+ * contains the <tt>Sasl.POLICY_NOPLAINTEXT</tt> property with the value
+ * <tt>"true"</tt>, then the factory must not return any SASL mechanisms
+ * that are susceptible to simple plain passive attacks.
+ * See the <tt>Sasl</tt> class for a complete list of policy properties.
+ * Non-policy related properties, if present in <tt>props</tt>, are ignored.
+ *
+ * @return A non-null array containing a IANA-registered SASL mechanism names.
+ */
+ public String[] getMechanismNames(Map props)
+ {
+ //log.debug("public String[] getMechanismNames(Map props = " + props + "): called");
+
+ // Used to build up the valid mechanisms in.
+ List validMechanisms = new ArrayList();
+
+ // Transform the Sasl properties into a set of bit mapped flags indicating the required properties of the
+ // encryption mechanism employed.
+ int requiredFlags = bitMapSaslProperties(props);
+ //log.debug("requiredFlags = " + requiredFlags);
+
+ // Scan down the list of supported mechanisms filtering in only those that satisfy all of the desired
+ // encryption properties.
+ for (int i = 0; i < SUPPORTED_MECHANISMS.length; i++)
+ {
+ int mechanismFlags = SUPPPORTED_MECHANISMS_POLICIES[i];
+ //log.debug("mechanismFlags = " + mechanismFlags);
+
+ // Check if the current mechanism contains all of the required flags.
+ if ((requiredFlags & ~mechanismFlags) == 0)
+ {
+ //log.debug("Mechanism " + SUPPORTED_MECHANISMS[i] + " meets the required properties.");
+ validMechanisms.add(SUPPORTED_MECHANISMS[i]);
+ }
+ }
+
+ String[] result = (String[]) validMechanisms.toArray(new String[validMechanisms.size()]);
+
+ //log.debug("result = " + PrettyPrintingUtils.printArray(result));
+
+ return result;
+ }
+
+ /**
+ * Transforms a set of Sasl properties, defined using the property names in javax.security.sasl.Sasl, into
+ * a bit mapped set of property flags encoded using the bit mapping constants defined in this class.
+ *
+ * @param properties The Sasl properties to bit map.
+ *
+ * @return A set of bit mapped properties encoded in an integer.
+ */
+ private int bitMapSaslProperties(Map properties)
+ {
+ //log.debug("private int bitMapSaslProperties(Map properties = " + properties + "): called");
+
+ int result = 0;
+
+ // No flags set if no properties are set.
+ if (properties == null)
+ {
+ return result;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NOPLAINTEXT)))
+ {
+ result |= NOPLAINTEXT;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NOACTIVE)))
+ {
+ result |= NOACTIVE;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NODICTIONARY)))
+ {
+ result |= NODICTIONARY;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NOANONYMOUS)))
+ {
+ result |= NOANONYMOUS;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_FORWARD_SECRECY)))
+ {
+ result |= FORWARD_SECRECY;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_PASS_CREDENTIALS)))
+ {
+ result |= PASS_CREDENTIALS;
+ }
+
+ return result;
+ }
+
+ /**
+ * Uses the specified call back handler to query for the users log in name and password.
+ *
+ * @param prefix A prefix to prepend onto the username and password queries.
+ * @param authorizationId The default autorhization name.
+ * @param cbh The call back handler.
+ *
+ * @return The username and password from the callback.
+ *
+ * @throws SaslException If the callback fails for any reason.
+ */
+ private Object[] getUserInfo(String prefix, String authorizationId, CallbackHandler cbh) throws SaslException
+ {
+ // Check that the callback handler is defined.
+ if (cbh == null)
+ {
+ throw new SaslException("Callback handler to get username/password required.");
+ }
+
+ try
+ {
+ String userPrompt = prefix + " authentication id: ";
+ String passwdPrompt = prefix + " password: ";
+
+ NameCallback ncb =
+ (authorizationId == null) ? new NameCallback(userPrompt) : new NameCallback(userPrompt, authorizationId);
+ PasswordCallback pcb = new PasswordCallback(passwdPrompt, false);
+
+ // Ask the call back handler to get the users name and password.
+ cbh.handle(new Callback[] { ncb, pcb });
+
+ char[] pw = pcb.getPassword();
+
+ byte[] bytepw;
+ String authId;
+
+ if (pw != null)
+ {
+ bytepw = new String(pw).getBytes("UTF8");
+ pcb.clearPassword();
+ }
+ else
+ {
+ bytepw = null;
+ }
+
+ authId = ncb.getName();
+
+ return new Object[] { authId, bytepw };
+ }
+ catch (IOException e)
+ {
+ throw new SaslException("Cannot get password.", e);
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ throw new SaslException("Cannot get userid/password.", e);
+ }
+ }
+}
diff --git a/java/client-java14/src/main/java/org/apache/qpid/sasl/CramMD5Client.java b/java/client-java14/src/main/java/org/apache/qpid/sasl/CramMD5Client.java
new file mode 100644
index 0000000000..c771df458e
--- /dev/null
+++ b/java/client-java14/src/main/java/org/apache/qpid/sasl/CramMD5Client.java
@@ -0,0 +1,349 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sasl;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+/**
+ * Implements the CRAM-MD5 SASL mechanism.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Concatenate the user id and password hashed by a challenge string as the challenge response.
+ * <tr><td> Ensure password is wiped once a challenge has been processed.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class CramMD5Client implements SaslClient
+{
+ /** Defines the HMAC block size. */
+ private static final int MD5_BLOCKSIZE = 64;
+
+ /** Flag used to indicate that the authentication has completed. */
+ private boolean completed = false;
+
+ private String authenticationId;
+ private byte[] password;
+
+ /**
+ * Creates a PLAIN SASL client for an authorization id, authentication id and password.
+ *
+ * @param authenticationId The authentication id.
+ * @param password The password.
+ *
+ * @throws SaslException If the authentication id or password is null.
+ */
+ CramMD5Client(String authenticationId, byte[] password) throws SaslException
+ {
+ // Check that a username and password are specified.
+ if ((authenticationId == null) || (password == null))
+ {
+ throw new SaslException("CRAM: authentication id and password must be specified");
+ }
+
+ // Keep the log in credentials.
+ this.authenticationId = authenticationId;
+ this.password = password;
+ }
+
+ /**
+ * Returns the IANA-registered mechanism name of this SASL client. (e.g. "CRAM-MD5", "GSSAPI").
+ *
+ * @return A non-null string representing the IANA-registered mechanism name.
+ */
+ public String getMechanismName()
+ {
+ return "CRAM-MD5";
+ }
+
+ /**
+ * Determines whether this mechanism has an optional initial response. If true, caller should call
+ * <tt>evaluateChallenge()</tt> with an empty array to get the initial response.
+ *
+ * <p/>CRAM-MD5 has no intial response.
+ *
+ * @return true if this mechanism has an initial response.
+ */
+ public boolean hasInitialResponse()
+ {
+ return false;
+ }
+
+ /**
+ * Evaluates the challenge data and generates a response. If a challenge is received from the server during the
+ * authentication process, this method is called to prepare an appropriate next response to submit to the server.
+ *
+ * <p/>The initial response for the SASL command, for the CRAM-MD5 mechanism is the concatenation of authentication
+ * ID and password HMAC-MD5 hashed by the server challenge.
+ *
+ * @param challenge The non-null challenge sent from the server. The challenge array may have zero length.
+ *
+ * @return The possibly null reponse to send to the server. It is null if the challenge accompanied a "SUCCESS"
+ * status and the challenge only contains data for the client to update its state and no response
+ * needs to be sent to the server. The response is a zero-length byte array if the client is to send a
+ * response with no data.
+ *
+ * @throws javax.security.sasl.SaslException If an error occurred while processing the challenge or generating a
+ * response.
+ */
+ public byte[] evaluateChallenge(byte[] challenge) throws SaslException
+ {
+ // Check that the authentication has not already been performed.
+ if (completed)
+ {
+ throw new IllegalStateException("CRAM-MD5 authentication already completed.");
+ }
+
+ // Check if the password is null, this will be the case if a previous attempt to authenticated failed.
+ if (password == null)
+ {
+ throw new IllegalStateException("CRAM-MD5 authentication previously aborted due to error.");
+ }
+
+ // Generate a keyed-MD5 digest from the user's password keyed by the challenge bytes.
+ try
+ {
+ String digest = hmac_md5(password, challenge);
+ String result = authenticationId + " " + digest;
+
+ completed = true;
+
+ return result.getBytes("UTF8");
+ }
+ catch (java.security.NoSuchAlgorithmException e)
+ {
+ throw new SaslException("MD5 algorithm not available on platform", e);
+ }
+ catch (java.io.UnsupportedEncodingException e)
+ {
+ throw new SaslException("UTF8 not available on platform", e);
+ }
+ finally
+ {
+ clearPassword();
+ }
+ }
+
+ /**
+ * Determines whether the authentication exchange has completed. This method may be called at any time, but
+ * typically, it will not be called until the caller has received indication from the server (in a protocol-specific
+ * manner) that the exchange has completed.
+ *
+ * @return true if the authentication exchange has completed; false otherwise.
+ */
+ public boolean isComplete()
+ {
+ return completed;
+ }
+
+ /**
+ * Unwraps a byte array received from the server. This method can be called only after the authentication exchange
+ * has completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has
+ * negotiated integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is
+ * thrown.
+ *
+ * <p/><tt>incoming</tt> is the contents of the SASL buffer as defined in RFC 2222 without the leading four octet
+ * field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of <tt>incoming</tt>
+ * to use.
+ *
+ * @param incoming A non-null byte array containing the encoded bytes from the server.
+ * @param offset The starting position at <tt>incoming</tt> of the bytes to use.
+ * @param len The number of bytes from <tt>incoming</tt> to use.
+ *
+ * @return A non-null byte array containing the decoded bytes.
+ *
+ * @throws javax.security.sasl.SaslException If <tt>incoming</tt> cannot be successfully unwrapped.
+ * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
+ * protection has neither integrity nor privacy.
+ */
+ public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
+ {
+ throw new SaslException("CRAM-MD5 does not support quality of protection.");
+ }
+
+ /**
+ * Wraps a byte array to be sent to the server. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has negotiated
+ * integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * <p/>The result of this method will make up the contents of the SASL buffer as defined in RFC 2222 without the
+ * leading four octet field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of
+ * <tt>outgoing</tt> to use.
+ *
+ * @param outgoing A non-null byte array containing the bytes to encode.
+ * @param offset The starting position at <tt>outgoing</tt> of the bytes to use.
+ * @param len The number of bytes from <tt>outgoing</tt> to use.
+ *
+ * @return A non-null byte array containing the encoded bytes.
+ *
+ * @throws javax.security.sasl.SaslException If <tt>outgoing</tt> cannot be successfully wrapped.
+ * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
+ * protection has neither integrity nor privacy.
+ */
+ public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
+ {
+ throw new SaslException("CRAM-MD5 does not support quality of protection.");
+ }
+
+ /**
+ * Retrieves the negotiated property. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true); otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * @param propName The non-null property name.
+ *
+ * @return The value of the negotiated property. If null, the property was not negotiated or is not applicable to
+ * this mechanism.
+ *
+ * @throws IllegalStateException If this authentication exchange has not completed.
+ */
+ public Object getNegotiatedProperty(String propName)
+ {
+ if (completed)
+ {
+ if (propName.equals(Sasl.QOP))
+ {
+ return "auth";
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ throw new IllegalStateException("CRAM-MD5 authentication not completed");
+ }
+ }
+
+ /**
+ * Disposes of any system resources or security-sensitive information the SaslClient might be using. Invoking this
+ * method invalidates the SaslClient instance. This method is idempotent.
+ *
+ * @throws javax.security.sasl.SaslException If a problem was encountered while disposing the resources.
+ */
+ public void dispose() throws SaslException
+ { }
+
+ /*
+ * Hashes its input arguments according to HMAC-MD5 (RFC 2104) and returns the resulting digest in its ASCII
+ * representation.
+ *
+ * <p/> The HMAC-MD5 function is described as follows:
+ * <p/><pre>
+ * MD5(key XOR opad, MD5(key XOR ipad, text))
+ * </pre>
+ *
+ * <p/>Where key is an n byte key, ipad is the byte 0x36 repeated 64 times, opad is the byte 0x5c repeated 64 times
+ * and text is the data to be protected.
+ *
+ * @param key The key to hash by.
+ * @param text The plain text to hash.
+ *
+ * @return The hashed text.
+ *
+ * @throws NoSuchAlgorithmException If the Java platform does not supply an MD5 implementation.
+ */
+ private static final String hmac_md5(byte[] key, byte[] text) throws NoSuchAlgorithmException
+ {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+
+ /* digest the key if longer than 64 bytes */
+ if (key.length > 64)
+ {
+ key = md5.digest(key);
+ }
+
+ byte[] ipad = new byte[MD5_BLOCKSIZE]; /* inner padding */
+ byte[] opad = new byte[MD5_BLOCKSIZE]; /* outer padding */
+ byte[] digest;
+ int i;
+
+ /* store key in pads */
+ for (i = 0; i < MD5_BLOCKSIZE; i++)
+ {
+ for (; i < key.length; i++)
+ {
+ ipad[i] = key[i];
+ opad[i] = key[i];
+ }
+
+ ipad[i] = 0x00;
+ opad[i] = 0x00;
+ }
+
+ /* XOR key with pads */
+ for (i = 0; i < MD5_BLOCKSIZE; i++)
+ {
+ ipad[i] ^= 0x36;
+ opad[i] ^= 0x5c;
+ }
+
+ /* inner MD5 */
+ md5.update(ipad);
+ md5.update(text);
+ digest = md5.digest();
+
+ /* outer MD5 */
+ md5.update(opad);
+ md5.update(digest);
+ digest = md5.digest();
+
+ // Get character representation of digest
+ StringBuffer digestString = new StringBuffer();
+
+ for (i = 0; i < digest.length; i++)
+ {
+ if ((digest[i] & 0x000000ff) < 0x10)
+ {
+ digestString.append("0" + Integer.toHexString(digest[i] & 0x000000ff));
+ }
+ else
+ {
+ digestString.append(Integer.toHexString(digest[i] & 0x000000ff));
+ }
+ }
+
+ return (digestString.toString());
+ }
+
+ /**
+ * Overwrites the password with zeros.
+ */
+ private void clearPassword()
+ {
+ if (password != null)
+ {
+ // Zero out password.
+ for (int i = 0; i < password.length; i++)
+ {
+ password[i] = (byte) 0;
+ }
+
+ password = null;
+ }
+ }
+}
diff --git a/java/client-java14/src/main/java/org/apache/qpid/sasl/PlainClient.java b/java/client-java14/src/main/java/org/apache/qpid/sasl/PlainClient.java
new file mode 100644
index 0000000000..67d00fd7d4
--- /dev/null
+++ b/java/client-java14/src/main/java/org/apache/qpid/sasl/PlainClient.java
@@ -0,0 +1,277 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sasl;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+/**
+ * Implements the PLAIN SASL mechanism.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Concatenate the user id and password in plain text as the challenge respose.
+ * <tr><td> Ensure password is wiped once a challenge has been processed.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class PlainClient implements SaslClient
+{
+ /** Flag used to indicate that the authentication has completed. */
+ private boolean completed = false;
+
+ private String authorizationId;
+ private String authenticationId;
+ private byte[] password;
+
+ private static byte SEPERATOR = 0; // US-ASCII <NUL>
+
+ /**
+ * Creates a PLAIN SASL client for an authorization id, authentication id and password.
+ *
+ * @param authorizationId The authorization id. May be null.
+ * @param authenticationId The authentication id.
+ * @param password The password.
+ *
+ * @throws SaslException If the authentication id or password is null.
+ */
+ PlainClient(String authorizationId, String authenticationId, byte[] password) throws SaslException
+ {
+ // Check that a username and password are specified.
+ if ((authenticationId == null) || (password == null))
+ {
+ throw new SaslException("PLAIN: authentication ID and password must be specified");
+ }
+
+ // Keep the log in credentials.
+ this.authorizationId = authorizationId;
+ this.authenticationId = authenticationId;
+ this.password = password;
+ }
+
+ /**
+ * Returns the IANA-registered mechanism name of this SASL client. (e.g. "CRAM-MD5", "GSSAPI").
+ *
+ * @return A non-null string representing the IANA-registered mechanism name.
+ */
+ public String getMechanismName()
+ {
+ return "PLAIN";
+ }
+
+ /**
+ * Determines whether this mechanism has an optional initial response. If true, caller should call
+ * <tt>evaluateChallenge()</tt> with an empty array to get the initial response.
+ *
+ * @return true if this mechanism has an initial response.
+ */
+ public boolean hasInitialResponse()
+ {
+ return true;
+ }
+
+ /**
+ * Evaluates the challenge data and generates a response. If a challenge is received from the server during the
+ * authentication process, this method is called to prepare an appropriate next response to submit to the server.
+ *
+ * <p/>The initial response for the SASL command, for the PLAIN mechanism is the concatenation of authorization ID,
+ * authentication ID and password, with each component separated by the US-ASCII <NUL> byte.
+ *
+ * @param challenge The non-null challenge sent from the server. The challenge array may have zero length.
+ *
+ * @return The possibly null reponse to send to the server. It is null if the challenge accompanied a "SUCCESS"
+ * status and the challenge only contains data for the client to update its state and no response
+ * needs to be sent to the server. The response is a zero-length byte array if the client is to send a
+ * response with no data.
+ *
+ * @throws javax.security.sasl.SaslException If an error occurred while processing the challenge or generating a
+ * response.
+ */
+ public byte[] evaluateChallenge(byte[] challenge) throws SaslException
+ {
+ // Check that the authentication has not already been performed.
+ if (completed)
+ {
+ throw new IllegalStateException("PLAIN authentication already completed");
+ }
+
+ try
+ {
+ // Get the authorization and authentication ids in bytes.
+ byte[] authorizationBytes = (authorizationId != null) ? authorizationId.getBytes("UTF8") : null;
+ byte[] authenticationBytes = authenticationId.getBytes("UTF8");
+
+ // Create an array big enough to hold the results.
+ byte[] result =
+ new byte[password.length + authenticationBytes.length + 2
+ + ((authorizationBytes == null) ? 0 : authorizationBytes.length)];
+
+ // Copy the authorization id, authentication id and password into the results.
+ int pos = 0;
+ if (authorizationBytes != null)
+ {
+ System.arraycopy(authorizationBytes, 0, result, 0, authorizationBytes.length);
+ pos = authorizationBytes.length;
+ }
+
+ result[pos++] = SEPERATOR;
+ System.arraycopy(authenticationBytes, 0, result, pos, authenticationBytes.length);
+
+ pos += authenticationBytes.length;
+ result[pos++] = SEPERATOR;
+
+ System.arraycopy(password, 0, result, pos, password.length);
+
+ completed = true;
+
+ return result;
+ }
+ catch (java.io.UnsupportedEncodingException e)
+ {
+ throw new SaslException("Cannot get UTF-8 encoding of ids", e);
+ }
+ finally
+ {
+ clearPassword();
+ }
+ }
+
+ /**
+ * Determines whether the authentication exchange has completed. This method may be called at any time, but
+ * typically, it will not be called until the caller has received indication from the server (in a protocol-specific
+ * manner) that the exchange has completed.
+ *
+ * @return true if the authentication exchange has completed; false otherwise.
+ */
+ public boolean isComplete()
+ {
+ return completed;
+ }
+
+ /**
+ * Unwraps a byte array received from the server. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has negotiated
+ * integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * <p/><tt>incoming</tt> is the contents of the SASL buffer as defined in RFC 2222 without the leading four octet
+ * field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of <tt>incoming</tt>
+ * to use.
+ *
+ * @param incoming A non-null byte array containing the encoded bytes
+ * from the server.
+ * @param offset The starting position at <tt>incoming</tt> of the bytes to use.
+ * @param len The number of bytes from <tt>incoming</tt> to use.
+ *
+ * @return A non-null byte array containing the decoded bytes.
+ *
+ * @throws javax.security.sasl.SaslException If <tt>incoming</tt> cannot be successfully unwrapped.
+ * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
+ * protection has neither integrity nor privacy.
+ */
+ public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
+ {
+ throw new SaslException("PLAIN does not support quality of protection.");
+ }
+
+ /**
+ * Wraps a byte array to be sent to the server. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has negotiated
+ * integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * <p/>The result of this method will make up the contents of the SASL buffer as defined in RFC 2222 without the
+ * leading four octet field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of
+ * <tt>outgoing</tt> to use.
+ *
+ * @param outgoing A non-null byte array containing the bytes to encode.
+ * @param offset The starting position at <tt>outgoing</tt> of the bytes to use.
+ * @param len The number of bytes from <tt>outgoing</tt> to use.
+ *
+ * @return A non-null byte array containing the encoded bytes.
+ *
+ * @throws javax.security.sasl.SaslException If <tt>outgoing</tt> cannot be successfully wrapped.
+ * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
+ * protection has neither integrity nor privacy.
+ */
+ public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
+ {
+ throw new SaslException("PLAIN does not support quality of protection.");
+ }
+
+ /**
+ * Retrieves the negotiated property. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true); otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * @param propName The non-null property name.
+ *
+ * @return The value of the negotiated property. If null, the property was not negotiated or is not applicable to
+ * this mechanism.
+ *
+ * @throws IllegalStateException If this authentication exchange has not completed.
+ */
+ public Object getNegotiatedProperty(String propName)
+ {
+ if (completed)
+ {
+ if (propName.equals(Sasl.QOP))
+ {
+ return "auth";
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ throw new IllegalStateException("PLAIN authentication not completed");
+ }
+ }
+
+ /**
+ * Disposes of any system resources or security-sensitive information the SaslClient might be using. Invoking this
+ * method invalidates the SaslClient instance. This method is idempotent.
+ *
+ * @throws javax.security.sasl.SaslException If a problem was encountered while disposing the resources.
+ */
+ public void dispose() throws SaslException
+ {
+ clearPassword();
+ }
+
+ /**
+ * Overwrites the password with zeros.
+ */
+ private void clearPassword()
+ {
+ if (password != null)
+ {
+ // Zero out password.
+ for (int i = 0; i < password.length; i++)
+ {
+ password[i] = (byte) 0;
+ }
+
+ password = null;
+ }
+ }
+}
diff --git a/java/client-java14/src/main/java/org/apache/qpid/sasl/Provider.java b/java/client-java14/src/main/java/org/apache/qpid/sasl/Provider.java
new file mode 100644
index 0000000000..f9a5c42c3d
--- /dev/null
+++ b/java/client-java14/src/main/java/org/apache/qpid/sasl/Provider.java
@@ -0,0 +1,61 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sasl;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A SASL provider for Java 1.4. Declares the capabilities of this implementation, which supports PLAIN and CRAM-MD5
+ * client implementations only.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Declare PLAIN SASL support.
+ * <tr><td> Declare CRAM-MD5 SASL support.
+ * </table>
+ */
+public class Provider extends java.security.Provider
+{
+ //Logger log = Logger.getLogger(Provider.class);
+
+ private static final String info = "Qpid SASL provider" + "(implements client mechanisms for: PLAIN, CRAM-MD5)";
+
+ public Provider()
+ {
+ super("QpidSASL", 1.4, info);
+
+ //log.debug("public Provider(): called");
+
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ put("SaslClientFactory.PLAIN", "org.apache.qpid.sasl.ClientFactoryImpl");
+ put("SaslClientFactory.CRAM-MD5", "org.apache.qpid.sasl.ClientFactoryImpl");
+
+ return null;
+ }
+ });
+ }
+}
diff --git a/java/client-java14/src/test/java/org/apache/qpid/test/integration/client/ConnectionTest.java b/java/client-java14/src/test/java/org/apache/qpid/test/integration/client/ConnectionTest.java
new file mode 100644
index 0000000000..468beda5b5
--- /dev/null
+++ b/java/client-java14/src/test/java/org/apache/qpid/test/integration/client/ConnectionTest.java
@@ -0,0 +1,66 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.integration.client;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.NDC;
+
+import org.apache.qpid.client.AMQConnection;
+
+/**
+ * Implements a trivial broker connection test, to a broker on the default port on localhost, to check that SASL
+ * authentication works.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Check that a connection to a broker can be established.
+ * </table>
+ */
+public class ConnectionTest extends TestCase
+{
+ private String BROKER_URL = "tcp://localhost:5672";
+
+ public ConnectionTest(String name)
+ {
+ super(name);
+ }
+
+ /** Check that a connection to a broker can be established. */
+ public void testConnection() throws Exception
+ {
+ // Open a connection to the broker and close it again.
+ AMQConnection conn = new AMQConnection(BROKER_URL, "guest", "guest", "clientid", "test");
+ conn.close();
+ }
+
+ protected void setUp()
+ {
+ NDC.push(getName());
+ }
+
+ protected void tearDown()
+ {
+ NDC.pop();
+ }
+}
diff --git a/java/client/distribution/pom.xml b/java/client/distribution/pom.xml
index 3e9c0e493f..4ad14d40d2 100644
--- a/java/client/distribution/pom.xml
+++ b/java/client/distribution/pom.xml
@@ -48,20 +48,6 @@
<type>jar</type>
<version>${pom.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.qpid</groupId>
- <artifactId>qpid-client</artifactId>
- <type>jar</type>
- <version>${pom.version}</version>
- <classifier>java1.4</classifier>
- </dependency>
- <dependency>
- <groupId>org.apache.qpid</groupId>
- <artifactId>qpid-common</artifactId>
- <type>jar</type>
- <version>${pom.version}</version>
- <classifier>java1.4</classifier>
- </dependency>
</dependencies>
<build>
@@ -119,7 +105,6 @@
<configuration>
<descriptors>
<descriptor>src/main/assembly/client-bin.xml</descriptor>
- <descriptor>src/main/assembly/client-java1.4-bin.xml</descriptor>
<descriptor>src/main/assembly/client-src.xml</descriptor>
</descriptors>
<finalName>qpid-${pom.version}</finalName>
diff --git a/java/client/pom.xml b/java/client/pom.xml
index af85c5e63a..3a425cae1a 100644
--- a/java/client/pom.xml
+++ b/java/client/pom.xml
@@ -15,7 +15,7 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
- -->
+-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
@@ -100,12 +100,18 @@
<scope>test</scope>
</dependency>
- <!-- This needs to be included at compile time, for the retrotranslator verification to find it. -->
- <dependency>
- <groupId>net.sf.retrotranslator</groupId>
- <artifactId>retrotranslator-runtime</artifactId>
- <scope>provided</scope>
- </dependency>
+ <!-- These need to be included at compile time only, for the retrotranslator verification to find them. -->
+ <dependency>
+ <groupId>net.sf.retrotranslator</groupId>
+ <artifactId>retrotranslator-runtime</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
@@ -122,16 +128,16 @@
<configuration>
<systemProperties>
<property>
- <name>amqj.noAutoCreateVMBroker</name>
- <value>true</value>
- </property>
- <property>
<name>amqj.logging.level</name>
<value>${amqj.logging.level}</value>
</property>
<property>
<name>log4j.configuration</name>
- <value>file:///${basedir}/src/main/java/client.log4j</value>
+ <value>${log4j.configuration}</value>
+ </property>
+ <property>
+ <name>amqj.noAutoCreateVMBroker</name>
+ <value>true</value>
</property>
</systemProperties>
</configuration>
@@ -152,35 +158,38 @@
<!-- Backports the module to Java 1.4. This is done during the packaging phase as a transformation of the Jar. -->
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>retrotranslator-maven-plugin</artifactId>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>translate</goal>
- </goals>
- <configuration>
- <destjar>${project.build.directory}/${project.build.finalName}-java1.4.jar</destjar>
- <verify>${retrotranslator.verify}</verify>
- <verifyClasspath>
- <element>${retrotranslator.1.4-rt-path}</element>
- <element>${retrotranslator.1.4-jce-path}</element>
- <element>${retrotranslator.1.4-jsse-path}</element>
- </verifyClasspath>
- <includes>
- <include>
- <directory>${project.build.directory}</directory>
- <pattern>${project.build.finalName}.jar</pattern>
- </include>
- </includes>
- </configuration>
- </execution>
-
- </executions>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>retrotranslator-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>retro-client</id>
+ <phase>package</phase>
+ <goals>
+ <goal>translate</goal>
+ </goals>
+ <configuration>
+ <!--<destdir>${project.build.directory}/retro-classes</destdir>-->
+ <destjar>${project.build.directory}/${project.build.finalName}-java14.jar</destjar>
+ <verify>${retrotranslator.verify}</verify>
+ <verifyClasspath>
+ <element>${retrotranslator.1.4-rt-path}</element>
+ <element>${retrotranslator.1.4-jce-path}</element>
+ <element>${retrotranslator.1.4-jsse-path}</element>
+ <element>${retrotranslator.1.4-sasl-path}</element>
+ </verifyClasspath>
+ <failonwarning>false</failonwarning>
+ <includes>
+ <include>
+ <directory>${project.build.directory}</directory>
+ <pattern>${project.build.finalName}.jar</pattern>
+ </include>
+ </includes>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
-
- <!-- This identifies the backported java 1.4 jar and attaches it as a jar (classified as java1.4) build artifact. -->
+
+ <!-- This identifies the backported java 1.4 jars and attaches them as jar (classified as java14) build artifacts. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
@@ -194,9 +203,9 @@
<configuration>
<artifacts>
<artifact>
- <file>${project.build.directory}/${project.build.finalName}-java1.4.jar</file>
+ <file>${project.build.directory}/${project.build.finalName}-java14.jar</file>
<type>jar</type>
- <classifier>java1.4</classifier>
+ <classifier>java14</classifier>
</artifact>
</artifacts>
</configuration>
@@ -215,15 +224,18 @@
<include>**</include>
</includes>
</testResource>
- <testResource>
+
+ <!--
+ <testResource>
<targetPath>src/</targetPath>
<filtering>false</filtering>
<directory>src/test/java</directory>
<includes>
- <include>**/*.java</include>
+ <include>**/*.java</include>
</includes>
- </testResource>
-
+ </testResource>
+ -->
+
<testResource>
<targetPath></targetPath>
<filtering>false</filtering>
@@ -233,8 +245,7 @@
</includes>
</testResource>
</testResources>
-
+
</build>
</project>
- \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
index 66ae92113c..2aa2c1872b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
@@ -29,6 +29,7 @@ import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
import org.apache.log4j.Logger;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.client.security.AMQCallbackHandler;
@@ -48,7 +49,6 @@ import org.apache.qpid.protocol.AMQMethodEvent;
public class ConnectionStartMethodHandler implements StateAwareMethodListener
{
-
private static final Logger _log = Logger.getLogger(ConnectionStartMethodHandler.class);
private static final ConnectionStartMethodHandler _instance = new ConnectionStartMethodHandler();
@@ -59,19 +59,23 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
}
private ConnectionStartMethodHandler()
- {
- }
+ { }
- public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException
+ public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt)
+ throws AMQException
{
+ _log.debug("public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, "
+ + "AMQMethodEvent evt): called");
+
ConnectionStartBody body = (ConnectionStartBody) evt.getMethod();
byte major = (byte) body.versionMajor;
byte minor = (byte) body.versionMinor;
boolean versionOk = false;
- // for the purposes of interop, we can make the client accept the broker's version string.
- // if it does, it then internally records the version as being the latest one that it understands.
- // it needs to do this since frame lookup is done by version.
+
+ // For the purposes of interop, we can make the client accept the broker's version string.
+ // If it does, it then internally records the version as being the latest one that it understands.
+ // It needs to do this since frame lookup is done by version.
if (Boolean.getBoolean("qpid.accept.broker.version"))
{
versionOk = true;
@@ -90,8 +94,9 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
try
{
- // the mechanism we are going to use
+ // Used to hold the SASL mechanism to authenticate with.
String mechanism;
+
if (body.mechanisms == null)
{
throw new AMQException("mechanism not specified in ConnectionStart method frame");
@@ -99,6 +104,7 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
else
{
mechanism = chooseMechanism(body.mechanisms);
+ _log.debug("mechanism = " + mechanism);
}
if (mechanism == null)
@@ -109,15 +115,17 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
byte[] saslResponse;
try
{
- SaslClient sc = Sasl.createSaslClient(new String[]{mechanism},
- null, "AMQP", "localhost",
- null,createCallbackHandler(mechanism, protocolSession));
+ SaslClient sc =
+ Sasl.createSaslClient(new String[] { mechanism }, null, "AMQP", "localhost", null,
+ createCallbackHandler(mechanism, protocolSession));
if (sc == null)
{
- throw new AMQException("Client SASL configuration error: no SaslClient could be created for mechanism " +
- mechanism + ". Please ensure all factories are registered. See DynamicSaslRegistrar for " +
- " details of how to register non-standard SASL client providers.");
+ throw new AMQException(
+ "Client SASL configuration error: no SaslClient could be created for mechanism " + mechanism
+ + ". Please ensure all factories are registered. See DynamicSaslRegistrar for "
+ + " details of how to register non-standard SASL client providers.");
}
+
protocolSession.setSaslClient(sc);
saslResponse = (sc.hasInitialResponse() ? sc.evaluateChallenge(new byte[0]) : null);
}
@@ -131,6 +139,7 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
{
throw new AMQException("Locales is not defined in Connection Start method");
}
+
final String locales = new String(body.locales, "utf8");
final StringTokenizer tokenizer = new StringTokenizer(locales, " ");
String selectedLocale = null;
@@ -146,21 +155,24 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
FieldTable clientProperties = FieldTableFactory.newFieldTable();
- clientProperties.setString(new AMQShortString(ClientProperties.instance.toString()), protocolSession.getClientID());
- clientProperties.setString(new AMQShortString(ClientProperties.product.toString()), QpidProperties.getProductName());
- clientProperties.setString(new AMQShortString(ClientProperties.version.toString()), QpidProperties.getReleaseVersion());
+ clientProperties.setString(new AMQShortString(ClientProperties.instance.toString()),
+ protocolSession.getClientID());
+ clientProperties.setString(new AMQShortString(ClientProperties.product.toString()),
+ QpidProperties.getProductName());
+ clientProperties.setString(new AMQShortString(ClientProperties.version.toString()),
+ QpidProperties.getReleaseVersion());
clientProperties.setString(new AMQShortString(ClientProperties.platform.toString()), getFullSystemInfo());
// AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
protocolSession.writeFrame(ConnectionStartOkBody.createAMQFrame(evt.getChannelId(),
- protocolSession.getProtocolMajorVersion(),
- protocolSession.getProtocolMinorVersion(),
- clientProperties, // clientProperties
- new AMQShortString(selectedLocale), // locale
- new AMQShortString(mechanism), // mechanism
- saslResponse)); // response
+ protocolSession.getProtocolMajorVersion(),
+ protocolSession.getProtocolMinorVersion(),
+ clientProperties, // clientProperties
+ new AMQShortString(selectedLocale), // locale
+ new AMQShortString(mechanism), // mechanism
+ saslResponse)); // response
}
catch (UnsupportedEncodingException e)
@@ -170,11 +182,8 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
}
else
{
- _log.error("Broker requested Protocol ["
- + body.versionMajor
- + "-"
- + body.versionMinor
- + "] which is not supported by this version of the client library");
+ _log.error("Broker requested Protocol [" + body.versionMajor + "-" + body.versionMinor
+ + "] which is not supported by this version of the client library");
protocolSession.closeProtocolSession();
}
@@ -185,7 +194,7 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
byte[][] supportedVersions = ProtocolVersionList.pv;
boolean supported = false;
int i = supportedVersions.length;
- while(i-- != 0 && !supported)
+ while ((i-- != 0) && !supported)
{
supported = (supportedVersions[i][ProtocolVersionList.PROTOCOL_MAJOR] == versionMajor)
&& (supportedVersions[i][ProtocolVersionList.PROTOCOL_MINOR] == versionMinor);
@@ -228,11 +237,12 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
return mech;
}
}
+
return null;
}
private AMQCallbackHandler createCallbackHandler(String mechanism, AMQProtocolSession protocolSession)
- throws AMQException
+ throws AMQException
{
Class mechanismClass = CallbackHandlerRegistry.getInstance().getCallbackHandlerClass(mechanism);
try
@@ -240,6 +250,7 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
Object instance = mechanismClass.newInstance();
AMQCallbackHandler cbh = (AMQCallbackHandler) instance;
cbh.initialise(protocolSession);
+
return cbh;
}
catch (Exception e)
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java b/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java
index bcf77e1586..5c0f1de5bb 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -33,45 +33,102 @@ import java.util.Properties;
import org.apache.log4j.Logger;
+import org.apache.qpid.util.FileUtils;
+
+/**
+ * CallbackHandlerRegistry is a registry for call back handlers for user authentication and interaction during user
+ * authentication. It is capable of reading its configuration from a properties file containing call back handler
+ * implementing class names for different SASL mechanism names. Instantiating this registry also has the effect of
+ * configuring and registering the SASL client factory implementations using {@link DynamicSaslRegistrar}.
+ *
+ * <p/>The callback configuration should be specified in a properties file, refered to by the System property
+ * "amp.callbackhandler.properties". The format of the properties file is:
+ *
+ * <p/><pre>
+ * CallbackHanlder.mechanism=fully.qualified.class.name
+ * </pre>
+ *
+ * <p/>Where mechanism is an IANA-registered mechanism name and the fully qualified class name refers to a
+ * class that implements org.apache.qpid.client.security.AMQCallbackHanlder and provides a call back handler for the
+ * specified mechanism.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Parse callback properties.
+ * <tr><td> Provide mapping from SASL mechanisms to callback implementations.
+ * </table>
+ */
public class CallbackHandlerRegistry
{
+ private static final Logger _logger = Logger.getLogger(CallbackHandlerRegistry.class);
+
+ /** The name of the system property that holds the name of the callback handler properties file. */
private static final String FILE_PROPERTY = "amq.callbackhandler.properties";
- private static final Logger _logger = Logger.getLogger(CallbackHandlerRegistry.class);
+ /** The default name of the callback handler properties resource. */
+ public static final String DEFAULT_RESOURCE_NAME = "org/apache/qpid/client/security/CallbackHandlerRegistry.properties";
+ /** A static reference to the singleton instance of this registry. */
private static CallbackHandlerRegistry _instance = new CallbackHandlerRegistry();
- private Map _mechanismToHandlerClassMap = new HashMap();
+ /** Holds a map from SASL mechanism names to call back handlers. */
+ private Map<String, Class> _mechanismToHandlerClassMap = new HashMap<String, Class>();
+ /** Holds a space delimited list of mechanisms that callback handlers exist for. */
private String _mechanisms;
+ /**
+ * Gets the singleton instance of this registry.
+ *
+ * @return The singleton instance of this registry.
+ */
public static CallbackHandlerRegistry getInstance()
{
- return _instance;
+ return _instance;
}
+ /**
+ * Gets the callback handler class for a given SASL mechanism name.
+ *
+ * @param mechanism The SASL mechanism name.
+ *
+ * @return The callback handler class for the mechanism, or null if none is configured for that mechanism.
+ */
public Class getCallbackHandlerClass(String mechanism)
{
return (Class) _mechanismToHandlerClassMap.get(mechanism);
}
+ /**
+ * Gets a space delimited list of supported SASL mechanisms.
+ *
+ * @return A space delimited list of supported SASL mechanisms.
+ */
public String getMechanisms()
{
return _mechanisms;
}
+ /**
+ * Creates the call back handler registry from its configuration resource or file. This also has the side effect
+ * of configuring and registering the SASL client factory implementations using {@link DynamicSaslRegistrar}.
+ */
private CallbackHandlerRegistry()
{
- // first we register any Sasl client factories
+ // Register any configured SASL client factories.
DynamicSaslRegistrar.registerSaslProviders();
- InputStream is = openPropertiesInputStream();
+ String filename = System.getProperty(FILE_PROPERTY);
+ InputStream is =
+ FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME,
+ CallbackHandlerRegistry.class.getClassLoader());
+
try
{
Properties props = new Properties();
props.load(is);
parseProperties(props);
- _logger.info("Available SASL mechanisms: " + _mechanisms);
+ _logger.info("Callback handlers available for SASL mechanisms: " + _mechanisms);
}
catch (IOException e)
{
@@ -94,9 +151,8 @@ public class CallbackHandlerRegistry
}
}
- private InputStream openPropertiesInputStream()
+ /*private InputStream openPropertiesInputStream(String filename)
{
- String filename = System.getProperty(FILE_PROPERTY);
boolean useDefault = true;
InputStream is = null;
if (filename != null)
@@ -111,15 +167,23 @@ public class CallbackHandlerRegistry
_logger.error("Unable to read from file " + filename + ": " + e, e);
}
}
-
+
if (useDefault)
{
- is = CallbackHandlerRegistry.class.getResourceAsStream("CallbackHandlerRegistry.properties");
+ is = CallbackHandlerRegistry.class.getResourceAsStream(DEFAULT_RESOURCE_NAME);
}
-
+
return is;
- }
-
+ }*/
+
+ /**
+ * Scans the specified properties as a mapping from IANA registered SASL mechanism to call back handler
+ * implementations, that provide the necessary call back handling for obtaining user log in credentials
+ * during authentication for the specified mechanism, and builds a map from mechanism names to handler
+ * classes.
+ *
+ * @param props
+ */
private void parseProperties(Properties props)
{
Enumeration e = props.propertyNames();
@@ -130,8 +194,10 @@ public class CallbackHandlerRegistry
if (period < 0)
{
_logger.warn("Unable to parse property " + propertyName + " when configuring SASL providers");
+
continue;
}
+
String mechanism = propertyName.substring(period + 1);
String className = props.getProperty(propertyName);
Class clazz = null;
@@ -140,10 +206,12 @@ public class CallbackHandlerRegistry
clazz = Class.forName(className);
if (!AMQCallbackHandler.class.isAssignableFrom(clazz))
{
- _logger.warn("SASL provider " + clazz + " does not implement " + AMQCallbackHandler.class +
- ". Skipping");
+ _logger.warn("SASL provider " + clazz + " does not implement " + AMQCallbackHandler.class
+ + ". Skipping");
+
continue;
}
+
_mechanismToHandlerClassMap.put(mechanism, clazz);
if (_mechanisms == null)
{
@@ -158,6 +226,7 @@ public class CallbackHandlerRegistry
catch (ClassNotFoundException ex)
{
_logger.warn("Unable to load class " + className + ". Skipping that SASL provider");
+
continue;
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java
index 078c5e4989..f8ee22a5d9 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -36,20 +36,62 @@ import javax.security.sasl.SaslClientFactory;
import org.apache.log4j.Logger;
+import org.apache.qpid.util.FileUtils;
+
+/**
+ * DynamicSaslRegistrar provides a collection of helper methods for reading a configuration file that contains a mapping
+ * from SASL mechanism names to implementing client factory class names and registering a security provider with the
+ * Java runtime system, that uses the configured client factory implementations.
+ *
+ * <p/>The sasl configuration should be specified in a properties file, refered to by the System property
+ * "amp.dynamicsaslregistrar.properties". The format of the properties file is:
+ *
+ * <p/><pre>
+ * mechanism=fully.qualified.class.name
+ * </pre>
+ *
+ * <p/>Where mechanism is an IANA-registered mechanism name and the fully qualified class name refers to a
+ * class that implements javax.security.sasl.SaslClientFactory and provides the specified mechanism.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Parse SASL mechanism properties.
+ * <tr><td> Create and register security provider for SASL mechanisms.
+ * </table>
+ */
public class DynamicSaslRegistrar
{
+ private static final Logger _logger = Logger.getLogger(DynamicSaslRegistrar.class);
+
+ /** The name of the system property that holds the name of the SASL configuration properties. */
private static final String FILE_PROPERTY = "amq.dynamicsaslregistrar.properties";
- private static final Logger _logger = Logger.getLogger(DynamicSaslRegistrar.class);
+ /** The default name of the SASL properties file resource. */
+ public static final String DEFAULT_RESOURCE_NAME = "org/apache/qpid/client/security/DynamicSaslRegistrar.properties";
+ /**
+ * Reads the properties file, and creates a dynamic security provider to register the SASL implementations
+ * with.
+ */
public static void registerSaslProviders()
{
- InputStream is = openPropertiesInputStream();
+ _logger.debug("public static void registerSaslProviders(): called");
+
+ // Open the SASL properties file, using the default name is one is not specified.
+ String filename = System.getProperty(FILE_PROPERTY);
+ InputStream is =
+ FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME,
+ DynamicSaslRegistrar.class.getClassLoader());
+
try
{
Properties props = new Properties();
props.load(is);
+
+ _logger.debug("props = " + props);
+
Map<String, Class<? extends SaslClientFactory>> factories = parseProperties(props);
+
if (factories.size() > 0)
{
Security.addProvider(new JCAProvider(factories));
@@ -77,16 +119,30 @@ public class DynamicSaslRegistrar
}
}
- private static InputStream openPropertiesInputStream()
+ /**
+ * Either attempts to open the specified filename as an input stream, or uses the default SASL configuration
+ * resource.
+ *
+ * @param filename The name of the file to get the SASL properties from, null to use the default.
+ *
+ * @return An input stream to read the dynamic SASL configuration from, or null if one could not be opened.
+ */
+ /*private static InputStream openPropertiesInputStream(String filename)
{
- String filename = System.getProperty(FILE_PROPERTY);
- boolean useDefault = true;
InputStream is = null;
+
+ // Flag to indicate whether the default resource should be used. By default this is true, so that the default
+ // is used when opening the file fails.
+ boolean useDefault = true;
+
+ // Try to open the file if one was specified.
if (filename != null)
{
try
{
is = new BufferedInputStream(new FileInputStream(new File(filename)));
+
+ // Clear the default flag because the file was succesfully opened.
useDefault = false;
}
catch (FileNotFoundException e)
@@ -95,19 +151,35 @@ public class DynamicSaslRegistrar
}
}
+ // Load the default resource if a file was not specified, or if opening the file failed.
if (useDefault)
{
- is = CallbackHandlerRegistry.class.getResourceAsStream("DynamicSaslRegistrar.properties");
+ is = CallbackHandlerRegistry.class.getResourceAsStream(DEFAULT_RESOURCE_NAME);
}
return is;
- }
+ }*/
+ /**
+ * Parses the specified properties as a mapping from IANA registered SASL mechanism names to implementing client
+ * factories. If the client factories cannot be instantiated or do not implement SaslClientFactory then the
+ * properties refering to them are ignored.
+ *
+ * @param props The properties to scan for Sasl client factory implementations.
+ *
+ * @return A map from SASL mechanism names to implementing client factory classes.
+ *
+ * @todo Why tree map here? Do really want mechanisms in alphabetical order? Seems more likely that the declared
+ * order of the mechanisms is intended to be preserved, so that they are registered in the declared order
+ * of preference. Consider LinkedHashMap instead.
+ */
private static Map<String, Class<? extends SaslClientFactory>> parseProperties(Properties props)
{
Enumeration e = props.propertyNames();
+
TreeMap<String, Class<? extends SaslClientFactory>> factoriesToRegister =
- new TreeMap<String, Class<? extends SaslClientFactory>>();
+ new TreeMap<String, Class<? extends SaslClientFactory>>();
+
while (e.hasMoreElements())
{
String mechanism = (String) e.nextElement();
@@ -118,17 +190,18 @@ public class DynamicSaslRegistrar
if (!(SaslClientFactory.class.isAssignableFrom(clazz)))
{
_logger.error("Class " + clazz + " does not implement " + SaslClientFactory.class + " - skipping");
+
continue;
}
+
factoriesToRegister.put(mechanism, (Class<? extends SaslClientFactory>) clazz);
}
catch (Exception ex)
{
- _logger.error("Error instantiating SaslClientFactory calss " + className + " - skipping");
+ _logger.error("Error instantiating SaslClientFactory calss " + className + " - skipping");
}
}
+
return factoriesToRegister;
}
-
-
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
index ee66664455..c2a7d7928c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
+++ b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
@@ -6,9 +6,9 @@
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java b/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java
index ff3ead6d42..2fa8dcddde 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -26,22 +26,46 @@ import java.util.Map;
import javax.security.sasl.SaslClientFactory;
+import org.apache.log4j.Logger;
+
+/**
+ * JCAProvider is a security provider for SASL client factories that is configured from a map of SASL mechanism names
+ * to client factories implementation class names. It is intended that the map of client factories can be read from a
+ * configuration file or other application configuration mechanism.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Register SASL mechanism implementations.
+ * </table>
+ */
public class JCAProvider extends Provider
{
+ private static final Logger log = Logger.getLogger(JCAProvider.class);
+
+ /**
+ * Creates the security provider with a map from SASL mechanisms to implementing factories.
+ *
+ * @param providerMap The map from SASL mechanims to implementing factory classes.
+ */
public JCAProvider(Map<String, Class<? extends SaslClientFactory>> providerMap)
{
- super("AMQSASLProvider", 1.0, "A JCA provider that registers all " +
- "AMQ SASL providers that want to be registered");
+ super("AMQSASLProvider", 1.0, "A JCA provider that registers all "
+ + "AMQ SASL providers that want to be registered");
register(providerMap);
Security.addProvider(this);
}
+ /**
+ * Registers client factory classes for a map of mechanism names to client factory classes.
+ *
+ * @param providerMap The map from SASL mechanims to implementing factory classes.
+ */
private void register(Map<String, Class<? extends SaslClientFactory>> providerMap)
{
- for (Map.Entry<String, Class<? extends SaslClientFactory>> me :
- providerMap.entrySet())
+ for (Map.Entry<String, Class<? extends SaslClientFactory>> me : providerMap.entrySet())
{
put("SaslClientFactory." + me.getKey(), me.getValue().getName());
+ log.debug("Registered SASL Client factory for " + me.getKey() + " as " + me.getValue().getName());
}
}
}
diff --git a/java/common/pom.xml b/java/common/pom.xml
index c8168c34bb..5e94153346 100644
--- a/java/common/pom.xml
+++ b/java/common/pom.xml
@@ -15,7 +15,7 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
- -->
+-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
@@ -67,35 +67,37 @@
<!-- Backports the module to Java 1.4. This is done during the packaging phase as a transformation of the Jar. -->
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>retrotranslator-maven-plugin</artifactId>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>translate</goal>
- </goals>
- <configuration>
- <destjar>${project.build.directory}/${project.build.finalName}-java1.4.jar</destjar>
- <verify>${retrotranslator.verify}</verify>
- <verifyClasspath>
- <element>${retrotranslator.1.4-rt-path}</element>
- <element>${retrotranslator.1.4-jce-path}</element>
- <element>${retrotranslator.1.4-jsse-path}</element>
- </verifyClasspath>
- <includes>
- <include>
- <directory>${project.build.directory}</directory>
- <pattern>${project.build.finalName}.jar</pattern>
- </include>
- </includes>
- </configuration>
- </execution>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>retrotranslator-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>translate</goal>
+ </goals>
+ <configuration>
+ <destjar>${project.build.directory}/${project.build.finalName}-java14.jar</destjar>
+ <verify>${retrotranslator.verify}</verify>
+ <verifyClasspath>
+ <element>${retrotranslator.1.4-rt-path}</element>
+ <element>${retrotranslator.1.4-jce-path}</element>
+ <element>${retrotranslator.1.4-jsse-path}</element>
+ <element>${retrotranslator.1.4-sasl-path}</element>
+ </verifyClasspath>
+ <failonwarning>false</failonwarning>
+ <includes>
+ <include>
+ <directory>${project.build.directory}</directory>
+ <pattern>${project.build.finalName}.jar</pattern>
+ </include>
+ </includes>
+ </configuration>
+ </execution>
- </executions>
+ </executions>
</plugin>
-
- <!-- This identifies the backported java 1.4 jar and attaches it as a jar (classified as java1.4) build artifact. -->
+
+ <!-- This identifies the backported java 1.4 jar and attaches it as a jar (classified as java14) build artifact. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
@@ -109,9 +111,9 @@
<configuration>
<artifacts>
<artifact>
- <file>${project.build.directory}/${project.build.finalName}-java1.4.jar</file>
+ <file>${project.build.directory}/${project.build.finalName}-java14.jar</file>
<type>jar</type>
- <classifier>java1.4</classifier>
+ <classifier>java14</classifier>
</artifact>
</artifacts>
</configuration>
@@ -156,12 +158,12 @@
<scope>test</scope>
</dependency>
- <!-- This needs to be included at compile time, for the retrotranslator verification to find it. -->
- <dependency>
- <groupId>net.sf.retrotranslator</groupId>
- <artifactId>retrotranslator-runtime</artifactId>
- <scope>provided</scope>
- </dependency>
+ <!-- This needs to be included at compile time, for the retrotranslator verification to find it. -->
+ <dependency>
+ <groupId>net.sf.retrotranslator</groupId>
+ <artifactId>retrotranslator-runtime</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/java/common/src/main/java/org/apache/qpid/util/FileUtils.java b/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
new file mode 100644
index 0000000000..ba79a6e8d4
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
@@ -0,0 +1,161 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import java.io.*;
+
+import org.apache.log4j.Logger;
+
+/**
+ * FileUtils provides some simple helper methods for working with files. It follows the convention of wrapping all
+ * checked exceptions as runtimes, so code using these methods is free of try-catch blocks but does not expect to
+ * recover from errors.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Read a text file as a string.
+ * <tr><td> Open a file or default resource as an input stream.
+ * </table>
+ */
+public class FileUtils
+{
+ /**
+ * Reads a text file as a string.
+ *
+ * @param filename The name of the file.
+ *
+ * @return The contents of the file.
+ */
+ public static String readFileAsString(String filename)
+ {
+ BufferedInputStream is = null;
+
+ try
+ {
+ is = new BufferedInputStream(new FileInputStream(filename));
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return readStreamAsString(is);
+ }
+
+ /**
+ * Reads a text file as a string.
+ *
+ * @param file The file.
+ *
+ * @return The contents of the file.
+ */
+ public static String readFileAsString(File file)
+ {
+ BufferedInputStream is = null;
+
+ try
+ {
+ is = new BufferedInputStream(new FileInputStream(file));
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return readStreamAsString(is);
+ }
+
+ /**
+ * Reads the contents of a reader, one line at a time until the end of stream is encountered, and returns all
+ * together as a string.
+ *
+ * @param is The reader.
+ *
+ * @return The contents of the reader.
+ */
+ private static String readStreamAsString(BufferedInputStream is)
+ {
+ try
+ {
+ byte[] data = new byte[4096];
+
+ StringBuffer inBuffer = new StringBuffer();
+
+ String line;
+ int read;
+
+ while ((read = is.read(data)) != -1)
+ {
+ String s = new String(data, 0, read);
+ inBuffer.append(s);
+ }
+
+ return inBuffer.toString();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Either opens the specified filename as an input stream, or uses the default resource loaded using the
+ * specified class loader, if opening the file fails or no file name is specified.
+ *
+ * @param filename The name of the file to open.
+ * @param defaultResource The name of the default resource on the classpath if the file cannot be opened.
+ * @param cl The classloader to load the default resource with.
+ *
+ * @return An input stream for the file or resource, or null if one could not be opened.
+ */
+ public static InputStream openFileOrDefaultResource(String filename, String defaultResource, ClassLoader cl)
+ {
+ InputStream is = null;
+
+ // Flag to indicate whether the default resource should be used. By default this is true, so that the default
+ // is used when opening the file fails.
+ boolean useDefault = true;
+
+ // Try to open the file if one was specified.
+ if (filename != null)
+ {
+ try
+ {
+ is = new BufferedInputStream(new FileInputStream(new File(filename)));
+
+ // Clear the default flag because the file was succesfully opened.
+ useDefault = false;
+ }
+ catch (FileNotFoundException e)
+ {
+ // Ignore this exception, the default will be used instead.
+ }
+ }
+
+ // Load the default resource if a file was not specified, or if opening the file failed.
+ if (useDefault)
+ {
+ is = cl.getResourceAsStream(defaultResource);
+ }
+
+ return is;
+ }
+}
diff --git a/java/common/src/main/java/org/apache/qpid/util/PrettyPrintingUtils.java b/java/common/src/main/java/org/apache/qpid/util/PrettyPrintingUtils.java
new file mode 100644
index 0000000000..faeb9d7167
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/util/PrettyPrintingUtils.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+/**
+ * Contains pretty printing convenienve methods for producing formatted logging output, mostly for debugging purposes.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ */
+public class PrettyPrintingUtils
+{
+ /**
+ * Pretty prints an array of ints as a string.
+ *
+ * @param array The array to pretty print.
+ *
+ * @return The pretty printed string.
+ */
+ public static String printArray(int[] array)
+ {
+ String result = "[";
+ for (int i = 0; i < array.length; i++)
+ {
+ result += array[i];
+ result += (i < (array.length - 1)) ? ", " : "";
+ }
+
+ result += "]";
+
+ return result;
+ }
+
+ /**
+ * Pretty prints an array of strings as a string.
+ *
+ * @param array The array to pretty print.
+ *
+ * @return The pretty printed string.
+ */
+ public static String printArray(String[] array)
+ {
+ String result = "[";
+ for (int i = 0; i < array.length; i++)
+ {
+ result += array[i];
+ result += (i < (array.length - 1)) ? ", " : "";
+ }
+
+ result += "]";
+
+ return result;
+ }
+}
diff --git a/java/pom.xml b/java/pom.xml
index 41b0b97674..0b7ecba55b 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -1,22 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- -->
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
@@ -49,9 +49,9 @@
<!-- Qpid has a Wiki site, maven generated site not used. This is just so that it can be created locally for viewing the reports. -->
<site>
- <id>Qpid_Site</id>
- <name>Qpid Site</name>
- <url>file:/temp</url>
+ <id>Qpid_Site</id>
+ <name>Qpid Site</name>
+ <url>file:/temp</url>
</site>
</distributionManagement>
@@ -98,9 +98,9 @@
<compile.flags>-Xlint:fallthrough,finally</compile.flags>
<!--
- This should always point to a default minimal log4j configuration that all developers are happy with as a useable default. To use your own
- log4j preferences set up an alternative in your settings.xml and avoid corrupting the default with private preferences.
- -->
+ This should always point to a default minimal log4j configuration that all developers are happy with as a useable default. To use your own
+ log4j preferences set up an alternative in your settings.xml and avoid corrupting the default with private preferences.
+ -->
<!--<log4j.configuration>file:/${topDirectoryLocation}/etc/log4j.xml</log4j.configuration>-->
<amqj.logging.level>warn</amqj.logging.level> <!-- This is referenced in the default log4j.xml -->
@@ -121,16 +121,17 @@
<site.version>2.0-beta-5</site.version>
<surefire-report.version>2.1-SNAPSHOT</surefire-report.version>
<surefire.version>2.2</surefire.version>
- <retrotranslator.plugin.version>1.0-alpha-1</retrotranslator.plugin.version>
- <build-helper.plugin.version>1.0</build-helper.plugin.version>
+ <retrotranslator.plugin.version>1.0-SNAPSHOT</retrotranslator.plugin.version>
+ <build-helper.plugin.version>1.0</build-helper.plugin.version>
<eclipse.workspace.dir>${basedir}/${topDirectoryLocation}/../workspace</eclipse.workspace.dir>
<clover.license.pathname>/set/clover/license/path/here</clover.license.pathname>
- <!-- Override these in local settings.xml to perform verification. Cannot make assumptions about 1.4 Jdk location to turn this on by default. -->
- <retrotranslator.verify>false</retrotranslator.verify>
+ <!-- Override these in local settings.xml to perform verification. Cannot make assumptions about 1.4 Jdk location to turn this on by default. -->
+ <retrotranslator.verify>false</retrotranslator.verify>
<retrotranslator.1.4-rt-path>pathto/rt.jar</retrotranslator.1.4-rt-path>
<retrotranslator.1.4-jce-path>pathto/jce.jar</retrotranslator.1.4-jce-path>
<retrotranslator.1.4-jsse-path>pathto/jsse.jar</retrotranslator.1.4-jsse-path>
+ <retrotranslator.1.4-sasl-path>pathto/sasl.jar</retrotranslator.1.4-sasl-path>
</properties>
@@ -213,49 +214,49 @@
<executions>
- <!-- This Ant task writes the module name, version and the Subversion version information out to a properties file.
- The svnversion command must be available to run from the command line for this to work. The build will not fail if
- svnversion cannot be run though.
- This is done during the 'compile' phase to reflect the version of the currently compiled code and to ensure that
- these properties are up to date when running from a file system classpath. Consider moving this to, or running a second
- time, during the 'package' phase to capture the version of any resources added to jar files.
- This svnversion command is always run in the top directory to accurately reflect the svnversion range accross all modules
- at the time of the build.
- The properties are placed into a file 'qpidversion.properties' in the target/classes directory of any child module
- that runs this plugin.
- The 'qpidversion.properties' file is loaded by the org.apache.qpid.common.QpidProperties class.
- Be carefull of the possibility that the 'common' module may run this antrun plugin and recieve its own set of
- qpidversion.properties and then the client or broker being built against an older version of the common library ending
- up with the wrong version information. This is unlikely to happen because the client or broker should pick up its own
- properties from the classpath first. If this happens it will be obvious because the productName property will be
- 'Qpid Common Utilities'. If this is a problem then push this ant task down into the client and broker poms and remove it
- from here.
- -->
- <execution>
- <id>version_properties</id>
- <phase>compile</phase>
- <configuration>
- <tasks>
-
- <exec executable="svnversion" spawn="false" failifexecutionfails="false"
- dir="${topDirectoryLocation}" outputproperty="svnversion">
- <arg line="."/>
- </exec>
-
- <!-- Write the version.properties out. -->
- <propertyfile file="target/classes/qpidversion.properties">
- <entry key="qpid.svnversion" value="${svnversion}"/>
- <entry key="qpid.name" value="${project.name}"/>
- <entry key="qpid.version" value="${project.version}"/>
- </propertyfile>
-
- </tasks>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
+ <!-- This Ant task writes the module name, version and the Subversion version information out to a properties file.
+ The svnversion command must be available to run from the command line for this to work. The build will not fail if
+ svnversion cannot be run though.
+ This is done during the 'compile' phase to reflect the version of the currently compiled code and to ensure that
+ these properties are up to date when running from a file system classpath. Consider moving this to, or running a second
+ time, during the 'package' phase to capture the version of any resources added to jar files.
+ This svnversion command is always run in the top directory to accurately reflect the svnversion range accross all modules
+ at the time of the build.
+ The properties are placed into a file 'qpidversion.properties' in the target/classes directory of any child module
+ that runs this plugin.
+ The 'qpidversion.properties' file is loaded by the org.apache.qpid.common.QpidProperties class.
+ Be carefull of the possibility that the 'common' module may run this antrun plugin and recieve its own set of
+ qpidversion.properties and then the client or broker being built against an older version of the common library ending
+ up with the wrong version information. This is unlikely to happen because the client or broker should pick up its own
+ properties from the classpath first. If this happens it will be obvious because the productName property will be
+ 'Qpid Common Utilities'. If this is a problem then push this ant task down into the client and broker poms and remove it
+ from here.
+ -->
+ <execution>
+ <id>version_properties</id>
+ <phase>compile</phase>
+ <configuration>
+ <tasks>
+
+ <exec executable="svnversion" spawn="false" failifexecutionfails="false"
+ dir="${topDirectoryLocation}" outputproperty="svnversion">
+ <arg line="."/>
+ </exec>
+
+ <!-- Write the version.properties out. -->
+ <propertyfile file="target/classes/qpidversion.properties">
+ <entry key="qpid.svnversion" value="${svnversion}"/>
+ <entry key="qpid.name" value="${project.name}"/>
+ <entry key="qpid.version" value="${project.version}"/>
+ </propertyfile>
+
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
</execution>
- </executions>
+ </executions>
</plugin>
<plugin>
@@ -306,16 +307,16 @@
<forkMode>${surefire.fork.mode}</forkMode>
<childDelegation>false</childDelegation>
<argLine>-ea</argLine>
- <systemproperties>
+ <systemProperties>
<property>
<name>amqj.logging.level</name>
<value>${amqj.logging.level}</value>
- <!--
+ </property>
+ <property>
<name>log4j.configuration</name>
<value>${log4j.configuration}</value>
- -->
</property>
- </systemproperties>
+ </systemProperties>
</configuration>
</plugin>
@@ -384,15 +385,15 @@
<dependencyManagement>
<dependencies>
- <!-- Comile time only dependencies. -->
- <dependency>
- <groupId>net.sf.retrotranslator</groupId>
- <artifactId>retrotranslator-runtime</artifactId>
- <version>1.0.8</version>
- <scope>provided</scope>
- </dependency>
+ <!-- Comile time only dependencies. -->
+ <dependency>
+ <groupId>net.sf.retrotranslator</groupId>
+ <artifactId>retrotranslator-runtime</artifactId>
+ <version>1.2.1</version>
+ <scope>provided</scope>
+ </dependency>
- <!-- Compilation and run time dependecies. -->
+ <!-- Compilation and run time dependecies. -->
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
@@ -566,14 +567,14 @@
<repositories>
<!-- not picking up any snapshots at the moment
- <repository>
- <id>apache.snapshots</id>
- <name>Apache SNAPSHOT Repository</name>
- <url>http://people.apache.org/repo/m2-snapshot-repository</url>
- <snapshots>
- <enabled>true</enabled>
- </snapshots>
- </repository>
+ <repository>
+ <id>apache.snapshots</id>
+ <name>Apache SNAPSHOT Repository</name>
+ <url>http://people.apache.org/repo/m2-snapshot-repository</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
-->
</repositories>
@@ -586,6 +587,15 @@
<enabled>true</enabled>
</snapshots>
</pluginRepository>
+
+ <pluginRepository>
+ <id>codehaus.snapshots</id>
+ <name>Codehaus SNAPSHOT Repository</name>
+ <url>http://snapshots.repository.codehaus.org</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
</pluginRepositories>
<profiles>