1.5.5 release branch
diff --git a/trunk/ChangeLog.txt b/trunk/ChangeLog.txt
new file mode 100644
index 0000000..56d218a
--- /dev/null
+++ b/trunk/ChangeLog.txt
@@ -0,0 +1,52 @@
+
+This file contains a listing of all Jira tickets that have been closed
+for a given release.  
+
+Portions of this report were generated using the ReleaseNotes facility
+in Jira.
+
+Release 1.5.4
+=============
+
+** Bug
+    * [WSS-51] - Incorrect test for null in WSHandler
+    * [WSS-52] - ArrayIndexOutOfBoundsException if certs.length > 1
+    * [WSS-54] - UsernameTokenProcessor not processing unhashed UsernameToken
+    * [WSS-56] - WSS4j statically inserts Bouncycastle and Juice in list of JCE providers
+    * [WSS-66] - Possible security hole when PasswordDigest is used by client.
+    * [WSS-68] - No way to create a UsernameToken with absent <Password> element
+    * [WSS-70] - WSHandler checkReceiverResults causes security problem
+    * [WSS-82] - Add the ability to use a custom-loaded JCE provider instance instead of using the system-provided one
+    * [WSS-89] - Error in verifying the signature with encrypted key
+    * [WSS-93] - xmlsec NPE on Reference URI and ValueType attributes
+    * [WSS-95] - Missing NOTICE file in WSS4J release
+    * [WSS-96] - Error when making a signature when containing a WSSecTimestamp
+    * [WSS-97] - Merlin passes invalid OID to getExtensionValue
+    * [WSS-100] - Bug in wsse11 element creation
+    * [WSS-101] - Bug in Encrypted SOAP Header creation
+    * [WSS-103] - BinarySecurityToken processor does not allow for custom token types
+    * [WSS-105] - Make WSS4J compliant with X.509 1.1 specification
+    * [WSS-106] - Certs are expired in wss4j.keystore
+    * [WSS-108] - Some work on KeyIdentifiers
+    * [WSS-109] - Review of error handling messages
+    * [WSS-112] - DerivedKeyProcessor is overwritten if more derivedkeys are present in a Soap Message.
+    * [WSS-113] - Bug in WSHandler#getPassword
+    * [WSS-114] - Some test reports are deleted by intermediate tasks in the ant build
+    * [WSS-116] - EncryptedKeyProcessor fails to record QName of decrypted element
+    * [WSS-119] - Error in Singature Processor 
+
+** Improvement
+    * [WSS-37] - Make it easier to set key-stores programmatically
+    * [WSS-38] - Make it easier to set key-stores programmatically
+    * [WSS-74] - Allow Actions and Processors to be customizable
+    * [WSS-80] - Doc fixes to main WSS4J page
+    * [WSS-88] - SecureRandom.getInstance("SHA1PRNG") is slow on IBM JDK 1.4.2 (And perhaps others)
+    * [WSS-92] - Support for Encrypted Header 
+    * [WSS-104] - Reference List processor should provide more information
+    * [WSS-107] - X509NameTokenizer.java contains Bouncy Castle JCE copyright code
+
+
+Version prior to 1.5.4
+======================
+
+no record
diff --git a/trunk/LICENSE.txt b/trunk/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/trunk/LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
diff --git a/trunk/NOTICE b/trunk/NOTICE
new file mode 100644
index 0000000..34502df
--- /dev/null
+++ b/trunk/NOTICE
@@ -0,0 +1,5 @@
+This product includes software developed by

+The Apache Software Foundation (http://www.apache.org/).

+

+This product includes software Copyright University of Southampton IT

+Innovation Centre, 2006 (http://www.it-innovation.soton.ac.uk).

diff --git a/trunk/README.txt b/trunk/README.txt
new file mode 100644
index 0000000..2ac8486
--- /dev/null
+++ b/trunk/README.txt
@@ -0,0 +1,217 @@
+* What is WSS4J? *
+
+WSS4J is part of the Apache Web Services project:
+
+http://ws.apache.org/
+
+Apache WSS4J is an implementation of the OASIS Web Services Security specifications
+(WS-Security, WSS) from OASIS Web Services Security TC. WSS4J is primarily
+a Java library that can be used to sign, verify, encrypt, and decrypt SOAP Messages
+according to the WS-Security specifications. WSS4J uses Apache Axis and other Apache 
+XML-Security projects and is interoperable with other JAX-RPC based server/clients 
+and .Net WSE server/clients that follow the OASIS WSS specifications
+
+* Supported WSS Specifications *
+
+WSS4J implements
+
+ * OASIS Web Serives Security: SOAP Message Security 1.0 Standard 200401, 
+   March 2004
+ * Username Token profile V1.0
+ * X.509 Token Profile V1.0
+
+The Web Services Security part of WSS4J is fairly well tested and many
+WebService projects use it already. Also interoperability with
+various other implementations is well tested.
+
+* Support of older WSS specifications *
+
+The WSS4J release 1.1.0 is the last release that was able to emulate previous 
+WSS specs
+
+The next WSS4J releases (>= 1.5.x)
+- support the OASIS V1.0 specs and the relevant namespaces only
+- support one versions of provisional (draft) namespaces for the upcoming version
+
+After the next version of the WSS specs is finished, we do one WSS4J release 
+with the provisional namespaces and another release (with a new release 
+number) with the then fixed namespace URIs. Doing so we could save a lot of
+coding while retaining some backward compatibility using the n-1 release.
+
+
+* Web Services Security Features *
+
+WSS4J can generate and process the following SOAP Bindings:
+
+    o XML Security
+         + XML Signature
+         + XML Encryption
+    o Tokens
+         + Username Tokens
+         + Timestamps
+         + SAML Tokens
+
+WSS4J supports X.509 binary certificates and certificate paths.
+
+The master link to WSS4J: http://ws.apache.org/wss4j/
+
+There is also a Wiki concerning Apache WS projects and WSS4J as one
+of the WS sub-projects:
+    http://wiki.apache.org/ws/
+    http://wiki.apache.org/ws/FrontPage/WsFx
+    
+
+WS-Trust and WS-Secure Conversation specifications
+
+WSS4J now comes with the support for derived key token signature and encryption.
+This is used by the Axis2-"rahas" module to provide the WS-Secure Conversation.
+
+WS-Trust support is also being developed within Axis2 based on WSS4J
+
+org.apache.ws.sandbox. package contains experimental implementations of these 
+specifications.
+
+* Installation (binary distribution) *
+
+The WSS4J zip archive is the binary distribution and contains the wss4j
+jar file, some examples, test classes (incl. sources), the interop test
+classes (incl. sources and necessary certificate store), and the according
+client and server deployment and property files.
+
+The WSS4J jar file contains all classes that implement the basic functions
+and the handlers. To install it make sure this jar file is in the classpath
+of your Axis client and/or Axis server. 
+
+In addition you need to set up the property files that contain information
+about the certificate keystores you use. The property files and the keystore
+are accessed either as resources via classpath or, if that fails, as files
+using the relative path of the application
+
+Thus no specific installation is required. The wss4j jar file could be 
+included into ear or war files of enterprise or web application servers.
+
+Please refer to the JAVADOC files of the distribution for further 
+information how to use WSS4J, the handlers, and how to setup the
+deployment files.
+
+
+* Crypto Notice *
+
+   This distribution includes cryptographic software.  The country in
+   which you currently reside may have restrictions on the import,
+   possession, use, and/or re-export to another country, of
+   encryption software.  BEFORE using any encryption software, please
+   check your country's laws, regulations and policies concerning the
+   import, possession, or use, and re-export of encryption software, to
+   see if this is permitted.  See <http://www.wassenaar.org/> for more
+   information.
+
+   The U.S. Government Department of Commerce, Bureau of Industry and
+   Security (BIS), has classified this software as Export Commodity
+   Control Number (ECCN) 5D002.C.1, which includes information security
+   software using or performing cryptographic functions with asymmetric
+   algorithms.  The form and manner of this Apache Software Foundation
+   distribution makes it eligible for export under the License Exception
+   ENC Technology Software Unrestricted (TSU) exception (see the BIS
+   Export Administration Regulations, Section 740.13) for both object
+   code and source code.
+
+   The following provides more details on the included cryptographic
+   software:
+
+   Apache Santuario : http://santuario.apache.org/
+   Apache WSS4J     : http://ws.apache.org/wss4j/
+   Bouncycastle     : http://www.bouncycastle.org/
+
+
+
+* Required software *
+
+To work with WSS4J you need additional software. Most of the software is also
+needed by your SOAP base system, e.g. Apache Axis. 
+
+To simplify installation and operation of WSS4J an additional ZIP file 
+is provided that holds all other JARs that are required by WSS4J. Please 
+note that we probably not use the very latest versions of these JARs, but 
+we used them during the tests.
+
+To implement the Web Service Security (WSS) part specific software is 
+required:
+
+addressing-1.0.jar
+    This jar contains the implementation of WS-Addressing, required
+    by WSS4J Trust.
+
+    See: http://ws.apache.org/addressing/
+
+axis-1.4.jar
+axis-ant-1.4.jar
+axis-jaxrpc-1.4.jar
+axis-saaj-1.4.jar
+    These jars contain the Apache Axis base software. They implement
+    the basic SOAP processing, deployment, WSDL to Java, Java to WSDL
+    tools and a lot more. Please refer to a Axis documentation how to
+    setup Axis. You should be familiar with Axis, its setup, and 
+    deployment methods before you start with any WSS4J functions.
+    
+    See: http://ws.apache.org/axis/
+
+bcprov-jdk14-140.jar
+    This is the BouncyCastle library that implements all necessary
+    encryption, hashing, certificate, and keystore functions. Without
+    this fantastic library WSS4J wouldn't work at all.
+    
+    See: http://www.bouncycastle.org/
+    
+commons-codec-1.3.jar
+commons-discovery-0.2.jar
+commons-logging-1.1.jar
+    These jars are from the Commons project and provide may useful 
+    functions, such as Base64 encoding/decoding, resource lookup,
+    and much more. Please refer to the commons project to get more
+    information.
+    
+    The master link for the commons project:
+    http://jakarta.apache.org/commons/index.html
+
+junit-3.8.1.jar
+    The famous unit test library. Required if you like to build WSS4J
+    from source and run the unit tests.
+    
+    See: http://www.junit.org/
+    
+log4j-1.2.9.jar
+    The logging library. Required to control the logging, error 
+    reporting and so on.
+    
+    See: http://logging.apache.org/
+
+opensaml-1.1.jar
+    The SAML implementation used by WSS4J to implement the SAML profile.
+    
+    See: http://www.opensaml.org/
+
+wsdl4j-1.5.1.jar
+    The WSDL parsing functions, required by Axis tools to read and
+    parse WSDL.
+    
+    See: http://ws.apache.org/axis/  under related projects
+    
+xalan-2.7.1.jar
+    Library that implements XML Path Language (XPath) and XSLT. The XML 
+    Security implementation needs several functions of Xalan XPath.
+   
+    See: http://xml.apache.org/xalan-j/
+   
+xmlsec-1.4.2.jar
+    This library implements the XML-Signature Syntax and Processing and
+    the XML Encryption Syntax and Processing specifications of the W3C. Thus
+    they form one of the base foundations of WSS4J.  
+    
+    See: http://xml.apache.org/security/
+    
+xercesImpl.jar
+xml-apis.jar
+    The XML parser implementation. Required by anybody :-) .
+
+    See: http://xml.apache.org/xerces2-j/
diff --git a/trunk/assembly/bin.xml b/trunk/assembly/bin.xml
new file mode 100644
index 0000000..eb3a122
--- /dev/null
+++ b/trunk/assembly/bin.xml
@@ -0,0 +1,21 @@
+<assembly>

+  <id>bin</id>

+  <formats>

+    <format>tar.gz</format>

+  </formats>

+  <includeSiteDirectory>true</includeSiteDirectory>

+  <fileSets>

+    <fileSet>

+      <includes>

+        <include>*.txt</include>

+      </includes>

+    </fileSet>

+    <fileSet>

+      <directory>target</directory>

+      <outputDirectory></outputDirectory>

+      <includes>

+        <include>*.jar</include>

+      </includes>

+    </fileSet>

+  </fileSets>

+</assembly>

diff --git a/trunk/assembly/src.xml b/trunk/assembly/src.xml
new file mode 100644
index 0000000..10ec914
--- /dev/null
+++ b/trunk/assembly/src.xml
@@ -0,0 +1,23 @@
+<assembly>

+  <id>src</id>

+  <formats>

+    <format>tar.gz</format>

+  </formats>

+  <fileSets>

+    <fileSet>

+      <includes>

+        <include>*.txt</include>

+        <include>*.xml</include>

+        <include>*.properties</include>

+        <include>.classpath</include>

+        <include>.project</include>

+      </includes>

+    </fileSet>

+    <fileSet>

+      <directory>.settings</directory>

+    </fileSet>

+    <fileSet>

+      <directory>src</directory>

+    </fileSet>

+  </fileSets>

+</assembly>
\ No newline at end of file
diff --git a/trunk/build.properties.sample b/trunk/build.properties.sample
new file mode 100644
index 0000000..cff9c49
--- /dev/null
+++ b/trunk/build.properties.sample
@@ -0,0 +1,8 @@
+# To enable the use of proxy settings Replace XXXXX 

+# with your environment information and remove the '#' 

+# at the beginning of each line below.

+#http.proxyHost=XXXXX

+#http.proxyPort=XXXXX

+#http.nonProxyHosts=localhost|127.0.0.1

+#http.proxyUser=XXXXX

+#http.proxyPassword=XXXX

diff --git a/trunk/build.xml b/trunk/build.xml
new file mode 100644
index 0000000..8f5e901
--- /dev/null
+++ b/trunk/build.xml
@@ -0,0 +1,846 @@
+<?xml version="1.0"?>
+
+<project name="Web Services Security (WSS4J)" default="usage" basedir=".">
+    <!-- ================================================================== -->
+    <description>
+   Build file for WSS4J
+
+   This file is intended for ANT, a Java based build tool.
+   ANT is available from http://jakarta.apache.org/ant/index.html
+
+Prerequisites:
+    See the README file
+
+Build Instructions:
+   To build, run
+
+     ant "target"
+
+   on the directory where this file is located with the target you want.
+
+    </description>
+
+    <target name="init">
+        <property name='product.Name' value='Apache-WS-Security-J'/>
+        <property name='product.name' value='wss4j'/>
+        <property name='product.shortname' value='wss4j'/>
+
+        <property name='product.version.major' value='1'/>
+        <property name='product.version.minor' value='5'/>
+        <property name='product.version.level' value='4'/>
+        <property name='product.version' value='SNAPSHOT'/>
+        <!-- <property name='product.version' value='${product.version.major}.${product.version.minor}.${product.version.level}'/> -->
+        <property name="year" value="2008"/>
+        <property name="copyright" value="Copyright &#169; ${year} Apache WSS4J Project. All Rights Reserved."/>
+
+        <!-- Give user a chance to override without editing this file
+             (and without typing -D each time it compiles it) -->
+        <property file="./build.properties"/>
+        <property file="${user.home}/build.properties"/>
+
+        <!-- Place Holder for proxy settings -->
+        <property name="http.proxyHost" value=""/>
+        <property name="http.proxyPort" value=""/>
+        <property name="http.nonProxyHosts" value="localhost"/>
+        <property name="http.proxyUser" value=""/>
+        <property name="http.proxyPassword" value=""/>
+
+        <property name="dir.doc" value="./doc"/>
+        <property name="dir.dist" value="./dist"/>
+        <property name="dir.libs" value="./lib"/>
+        <property name="dir.endorsed.libs" value="./endorsed"/>
+        <property name="dir.src" value="./src"/>
+        <property name="dir.samples" value="./samples"/>
+        <property name="dir.test" value="./test"/>
+        <property name="dir.keys" value="./keys"/>
+        <property name="dir.specs" value="./specs"/>
+        <property name="dir.interop" value="./interop"/>
+        <property name="dir.webapp" location="./webapps/axis" />
+
+        <property name="build.dir" value="./build"/>
+        <property name="build.classes" value="${build.dir}/classes"/>
+        <property name="build.work" value="${build.dir}/work"/>
+        <property name="build.webapp" location="${build.dir}/webapps/axis"/>
+
+        <property name="jar.library" value="${product.shortname}-${product.version}.jar"/>
+
+        <property name="build.doc" value="${build.dir}/doc"/>
+        <property name="build.doc.xml" value="${build.doc}/xml"/>
+        <property name="build.doc.html" value="${build.doc}/html"/>
+        <property name="build.javadoc" value="${build.doc.html}/api"/>
+        <property name="build.junit.xml" value="${build.doc.xml}/junit"/>
+        <property name="build.junit.html" value="${build.doc.html}/junit"/>
+
+
+        <condition property="jdk13.present">
+          <equals arg1="${ant.java.version}" arg2="1.3"/>
+        </condition>
+
+        <condition property="jdk14.present">
+          <equals arg1="${ant.java.version}" arg2="1.4"/>
+        </condition>
+
+        <condition property="jdk15.present">
+          <equals arg1="${ant.java.version}" arg2="1.5"/>
+        </condition>
+
+        <condition property="merlin.ok">
+            <or>
+                <equals arg1="${ant.java.version}" arg2="1.4"/>
+                <equals arg1="${ant.java.version}" arg2="1.5"/>
+            </or>
+        </condition>
+
+        <!-- 
+
+         for the time being following path id uses the libs in the wss4j
+         lib directory only This is done to test if we really don't need
+         any axis libs. After this is done we can include the
+         java.class.path and leave the wss4j/lib empty. This requires that
+         the CLASSPATH includes all required packages (see above
+
+         -->
+        
+        
+        <path id="classpath.libraries" description="3rd party libs">
+            <fileset dir="${dir.libs}">
+                <include name="**/*.jar"/>
+                <exclude name="**/bcprov-jdk15-*.jar" unless="jdk15.present"/>
+                <exclude name="**/bcprov-jdk13-*.jar" if="jdk15.present" />
+                <!-- <pathelement path="${java.class.path}"/> -->
+            </fileset>
+            <fileset dir="${dir.endorsed.libs}">
+                <include name="**/*.jar"/>
+                <!-- <pathelement path="${java.class.path}"/> -->
+            </fileset>
+        </path>
+
+        <path id="classpath.wss4j" description="wss4j classes; first try pure class files, then jars">
+            <pathelement path="${build.classes}"/>
+            <pathelement path="${build.dir}/${jar.library}"/>
+        </path>
+
+        <path id="classpath.library">
+            <path refid="classpath.wss4j"/>
+            <path refid="classpath.libraries"/>
+        </path>
+
+        <taskdef resource="axis-tasks.properties" classpathref=
+              "classpath.library"/>
+        <taskdef name="runaxisfunctionaltests" classname=
+              "org.apache.axis.tools.ant.axis.RunAxisFunctionalTestsTask"
+            loaderref="axis">
+            <classpath refid="classpath.library"/>
+        </taskdef>
+      
+        <!-- this shall include Axis jars because the tests use the
+         Axis implementation of javax.xml.soap, etc. Therefore the
+         CLASSPATH is included.
+         -->
+        <path id="classpath.test">
+            <!-- classpath for test is librarypath plus junit -->
+            <path refid="classpath.library"/>
+<!--            <pathelement path="${java.class.path}"/> -->
+        </path>
+
+        <path id="classpath.test.jar">
+            <!-- classpath for test is librarypath plus junit -->
+            <path refid="classpath.library"/>
+            <pathelement path="${build.dir}/${jar.library}"/>
+            <pathelement path="${build.dir}/${jar.tests}"/>
+        </path>
+
+        <patternset id="distFiles">
+            <include name="build.xml"/>
+            <include name="LICENSE.txt"/>
+        </patternset>
+
+        <patternset id="srcFiles">
+         <!-- for some strange reasons, I can't use ${src} but must use src -->
+            <include name="src/**/*"/>
+        </patternset>
+
+        <patternset id="srcSamplesFiles">
+            <include name="samples/**/*"/>
+        </patternset>
+
+        <patternset id="srcUnitTestsFiles">
+            <include name="test/**/*"/>
+        </patternset>
+
+        <patternset id="srcInteropFiles">
+            <include name="interop/**/*"/>
+        </patternset>
+
+        <property name="javadoc.packages"
+            value="
+org.apache.ws.security,
+org.apache.ws.security.components,
+org.apache.ws.security.components.crypto,
+org.apache.ws.security.message,
+org.apache.ws.security.message.token,
+org.apache.ws.security.util,
+org.apache.ws.axis,
+org.apache.ws.axis.security,
+org.apache.ws.axis.security.util
+"/>
+
+      <echo level="debug">
+        -------------------------------------------------------------------
+        ${product.Name} v${product.version} [${year}] 
+        -------------------------------------------------------------------
+        Building with ${ant.version}
+        using build file ${ant.file}
+        Java ${java.version} located at ${java.home} 
+        -------------------------------------------------------------------
+        --- Property values ---
+        sun.boot.class.path=${sun.boot.class.path}
+      </echo>
+      <pathconvert targetos="windows" property="classpath.test.as.string" 
+          refid="classpath.test"/>
+      <echo level="debug">
+        classpath.test: ${classpath.test.as.string}
+      </echo>
+    </target>
+
+    <target name="usage" depends="init">
+      <echo>
+         Build instructions                                                
+        -------------------------------------------------------------------
+                                                                           
+         available targets are:                                            
+                                                                           
+           compile         --> compiles everything                         
+           compile.library --> compiles the source code                    
+           compile.samples --> compiles the samples source code            
+           compile.tests   --> compiles the tests source code              
+           compile.interops--> compiles the interop source code            
+                                                                           
+           javadoc         --> generates the API documentation             
+                               (needs Java > 1.2)                          
+                                                                           
+           test            --> runs the defined JUnit tests                
+           report          --> generates html report of test results       
+                                                                           
+           clean           --> cleans up all generated files and           
+                               directories                                 
+           jar             --> creates the JAR file                        
+           gump            --> includes javadoc, compile jar and test      
+                                                                           
+           usage           --> provides help on using the build tool       
+                               (default)                                   
+                                                                           
+           changelog       --> generates changelog.html                    
+                                                                           
+         See comments inside the build.xml file for more details.          
+        -------------------------------------------------------------------
+      </echo>
+    </target>
+
+    <target name="clean" depends="init"
+        description="Clean up all temporary build files">
+        <delete dir="${build.dir}"/>
+        <delete>
+            <fileset dir="." includes="before*.xml"/>
+            <fileset dir="." includes="after*.xml"/>
+            <fileset dir="." includes="signed*.xml"/>
+            <fileset dir="." includes="server*.wsdd"/>
+            <fileset dir="." includes="client*.wsdd"/>
+        </delete>
+        <delete dir="${dir.dist}"/>
+    </target>
+
+    <target name="prepare" depends="init"
+        description="This target generates a first build directory and checks for some libraries">
+        <tstamp/>
+        <mkdir dir="${build.dir}"/>
+        <!--<delete dir="${build.dir}/test-reports"/> -->
+        <mkdir dir="${build.dir}/test-reports"/>
+
+        <available property="junit.present" 
+                classname="junit.framework.TestCase">
+            <!-- check whether JUnit is available -->
+            <classpath refid="classpath.test"/>
+        </available>
+
+        <available property="bc.present" classname="org.bouncycastle.jce.provider.BouncyCastleProvider">
+            <!-- check whether BouncyCastle is available -->
+            <classpath refid="classpath.test"/>
+        </available>
+
+        <echo level="debug">
+        --- Flags (Note: If the {property name} is displayed,
+                   then the component is not present)
+        jdk13.present=${jdk13.present}
+        jdk14.present=${jdk14.present}
+        jdk15.present=${jdk15.present}
+        bc.present=${bc.present}
+        </echo>
+
+    </target>
+
+    <!-- ################################################################## -->
+    <!-- ################################################################## -->
+    <!-- ################################################################## -->
+    <!-- ################################################################## -->
+    <!-- ################################################################## -->
+
+    <target name="prepare-src" depends="prepare" 
+        description="This target copies the Java sources and brands the version information">
+        <!-- create directories -->
+        <mkdir dir="${build.classes}"/>
+    </target>
+
+    <target name="javadoc"
+        depends="prepare-src"
+        description="Generates javadoc from all .java files; this is done on the 'branded' files">
+        <mkdir dir="${build.doc}"/>
+        <mkdir dir="${build.doc.html}"/>
+        <mkdir dir="${build.javadoc}"/>
+
+        <javadoc destdir="${build.javadoc}"
+            packagenames="${javadoc.packages}"
+            classpathref="classpath.test">
+            <!-- additionalparam="-breakiterator"-->
+            <sourcepath>
+                <pathelement location="${dir.src}"/>
+                <pathelement location="${dir.test}"/>
+                <pathelement location="${dir.samples}"/>
+                <pathelement location="${dir.interop}"/>
+            </sourcepath>
+        </javadoc>
+    </target>
+
+    <!-- ################################################################## -->
+
+    <!-- Aliases -->
+    <target name="javadocs" depends="javadoc"/>
+    <target name="jars" depends="jar"/>
+
+    <!-- Collections -->
+    <target name="gump" 
+            depends="clean,javadoc,compile,test" 
+            description="Target for the gump run"/>
+
+    <target name="compile" 
+       depends="compile.library,compile.samples, compile.tests, 
+                compile.interops, fix.properties"
+            description="compile everything"/>
+
+    <target name="test"
+            depends="unitTests, systemTests"
+            description="tests everything"/>        
+
+    <!-- ################################################################## -->
+
+    <target name="fix.properties" if="jdk13.present">
+        <replace dir="${build.dir}" value="org.apache.ws.security.components.crypto.BouncyCastle">
+            <include name="**/*.properties"/>
+            <replacetoken>org.apache.ws.security.components.crypto.Merlin</replacetoken>
+        </replace>
+    </target>
+
+    <target name="compile.library" depends="prepare-src">
+        <!-- Compile the java code from ${dir.src} into ${build.classes} -->
+        <javac srcdir="${dir.src}" destdir="${build.classes}" debug="on" source="1.3" target="1.3">
+            <classpath refid="classpath.library"/>
+            <exclude name="**/Merlin.java" unless="merlin.ok"/>
+            <exclude name="**/sandbox/**/*.java" if="jdk13.present" />
+        </javac>
+        <!-- Copy Property files -->
+        <copy todir="${build.classes}">
+            <fileset dir="${dir.src}">
+                <include name="**/*.properties"/>
+                <exclude name="**/axis/**/*.properties"/>
+            </fileset>
+        </copy>
+    </target>
+
+    <target name="compile.tests"
+        depends="compile.interops"
+        if="junit.present">
+
+        <javac srcdir="${dir.test}" destdir="${build.classes}" debug="on" source="1.3" target="1.3">
+            <classpath refid="classpath.test"/>
+<!--            <exclude name="**/secconv/**/*.java"/> -->
+        </javac>
+
+        <mkdir dir="${build.work}"/>
+
+        <javac srcdir="${build.work}" destdir="${build.classes}" debug="on" source="1.3" target="1.3">
+            <classpath refid="classpath.test"/>
+        </javac>
+
+        <!-- Copy Property files -->
+        <copy todir="${build.classes}">
+            <fileset dir="${dir.test}" includes="**/*.properties"/>
+            <fileset dir="${dir.interop}">
+                <include name="**/*.properties"/>
+            </fileset>
+        </copy>
+    </target>
+
+    <target name="compile.samples"
+        depends="compile.library">
+        <!-- Compile the java code from ${dir.src} into ${build.classes} -->
+        <javac srcdir="${dir.samples}"
+            debug="on"
+            source="1.4"
+            destdir="${build.classes}" target="1.4">
+            <classpath refid="classpath.library"/>
+        </javac>
+        <copy todir="${build.classes}">
+            <fileset dir="${dir.src}" includes="**/axis/**/*.properties"/>
+        </copy>
+    </target>
+
+    <target name="compile.interops"
+        depends="compile.library">
+        <ant dir="${dir.interop}"
+            antfile="build.xml"
+            target="compile"
+            inheritAll="false">
+        </ant>
+    </target>
+
+    <target name="systemTests" unless="skip.tests" depends="compile"
+        if="junit.present"
+        description="Runs all JUnit tests">
+        <runaxisfunctionaltests
+            url="http://localhost:8088"
+            httpServerTarget="start-functional-test-http-server"
+            testTarget="allTests"
+            httpStopTarget="stop-functional-test-http-server"/>
+    </target>
+
+    <target name="start-functional-test-http-server" if="junit.present">
+        <echo message="Starting http server."/>
+        <java classname="org.apache.axis.transport.http.SimpleAxisServer" 
+          fork="yes" dir="${build.dir}">
+            <jvmarg value="-Djava.endorsed.dirs=${basedir}/endorsed"/>
+            <classpath refid="classpath.library"/>
+        </java>
+    </target>
+
+    <target name="stop-functional-test-http-server" if="junit.present">
+        <echo message="Stopping http server."/>
+        <java classname="org.apache.axis.client.AdminClient" fork="yes">
+            <classpath refid="classpath.library"/>
+            <arg line="quit"/>
+        </java>
+    </target>
+
+    <target name="allTests" depends="interopTests">
+    </target>
+
+    <target name="interopTests" depends="init">
+        <echo message="Running system tests - BEGIN..."/>
+
+        <path id="undeploy_xml_files">
+            <fileset dir="${build.work}">
+                <include name="**/undeploy.wsdd"/>
+            </fileset>
+        </path>
+        <property name="undeploy_xml_property" refid="undeploy_xml_files"/>
+
+        <antcall target="deployWSDD" />
+        <junit printsummary="yes"
+            haltonfailure="yes"
+            fork="yes"
+            dir="${basedir}">
+            <jvmarg value="-Djava.endorsed.dirs=${basedir}/endorsed"/>
+            <jvmarg value="-Dhttp.proxyHost=${http.proxyHost}"/>
+            <jvmarg value="-Dhttp.proxyPort=${http.proxyPort}"/>
+            <jvmarg value="-Dhttp.nonProxyHosts=${http.nonProxyHosts}"/>
+            <jvmarg value="-Dhttp.proxyUser=${http.proxyUser}"/>
+            <jvmarg value="-Dhttp.proxyPassword=${http.proxyPassword}"/>
+            <classpath refid="classpath.test"/>
+            <formatter type="xml"/>
+            <batchtest todir="${build.dir}/test-reports">
+                <fileset dir="${build.classes}">
+                    <include name="**/interop/PackageTests.class"/>
+                </fileset>
+            </batchtest>
+        </junit>
+
+        <java classname="org.apache.axis.utils.Admin" fork="true">
+            <classpath refid="classpath.library"/>
+            <arg value="client"/>
+            <arg file=
+               "${build.work}/org/apache/ws/axis/oasis/ping/undeploy.wsdd"/>
+        </java>
+
+        <junit printsummary="yes"
+            haltonfailure="yes"
+            fork="yes"
+            dir="${basedir}">
+            <jvmarg value="-Djava.endorsed.dirs=${basedir}/endorsed"/>
+            <jvmarg value="-Dhttp.proxyHost=${http.proxyHost}"/>
+            <jvmarg value="-Dhttp.proxyPort=${http.proxyPort}"/>
+            <jvmarg value="-Dhttp.nonProxyHosts=${http.nonProxyHosts}"/>
+            <jvmarg value="-Dhttp.proxyUser=${http.proxyUser}"/>
+            <jvmarg value="-Dhttp.proxyPassword=${http.proxyPassword}"/>
+            <classpath refid="classpath.test"/>
+            <formatter type="xml"/>
+            <batchtest todir="${build.dir}/test-reports">
+                <fileset dir="${build.classes}">
+                    <include name="**/interop/TestJAXRPCHandler.class"/>
+                </fileset>
+            </batchtest>
+        </junit>
+
+        <java classname="org.apache.axis.client.AdminClient" fork="yes">
+            <classpath refid="classpath.library"/>
+            <arg line="${undeploy_xml_property}"/>
+        </java>
+        
+        <echo message="Running system tests - END..."/>
+    </target>
+
+    <target name="unitTests" unless="skip.tests" depends="compile">
+        <junit printsummary="yes"
+            haltonfailure="yes"
+            fork="yes"
+            dir="${basedir}">
+            <!-- See if this helps with Gump test failures -->
+            <sysproperty key="build.clonevm" value="true"/>
+
+            <jvmarg value="-Djava.endorsed.dirs=${basedir}/endorsed"/>
+            <jvmarg value="-Dhttp.proxyHost=${http.proxyHost}"/>
+            <jvmarg value="-Dhttp.proxyPort=${http.proxyPort}"/>
+            <jvmarg value="-Dhttp.nonProxyHosts=${http.nonProxyHosts}"/>
+            <jvmarg value="-Dhttp.proxyUser=${http.proxyUser}"/>
+            <jvmarg value="-Dhttp.proxyPassword=${http.proxyPassword}"/>
+            <classpath refid="classpath.test"/>
+            <formatter type="xml"/>
+            <batchtest todir="${build.dir}/test-reports">
+                <fileset dir="${build.classes}">
+                    <include name="**/wssec/PackageTests.class"/>
+                    <include name="**/components/PackageTests.class"/>
+             <!--<include name="**/secconv/components/PackageTests.class"/> -->
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="sandboxTests" depends="compile">
+        <java classname="org.apache.axis.client.AdminClient" fork="yes">
+            <classpath refid="classpath.library"/>
+            <arg line="${dir.samples}/org/apache/ws/sandbox/security/trust2/samples/deploy.wsdd"/>
+        </java>
+
+        <junit printsummary="yes"
+            haltonfailure="yes"
+            fork="yes"
+            dir="${basedir}">
+            <!-- See if this helps with Gump test failures -->
+            <sysproperty key="build.clonevm" value="true"/>
+
+            <jvmarg value="-Djava.endorsed.dirs=${basedir}/endorsed"/>
+            <jvmarg value="-Dhttp.proxyHost=${http.proxyHost}"/>
+            <jvmarg value="-Dhttp.proxyPort=${http.proxyPort}"/>
+            <jvmarg value="-Dhttp.nonProxyHosts=${http.nonProxyHosts}"/>
+            <jvmarg value="-Dhttp.proxyUser=${http.proxyUser}"/>
+            <jvmarg value="-Dhttp.proxyPassword=${http.proxyPassword}"/>
+            <classpath refid="classpath.test"/>
+            <formatter type="xml"/>
+            <batchtest todir="${build.dir}/test-reports">
+                <fileset dir="${build.classes}">
+                    <include name="**/sandbox/PackageTests.class"/>
+                </fileset>
+            </batchtest>
+        </junit>
+
+        <java classname="org.apache.axis.client.AdminClient" fork="yes">
+            <classpath refid="classpath.library"/>
+            <arg line="${dir.samples}/org/apache/ws/sandbox/security/trust2/samples/undeploy.wsdd"/>
+        </java>
+    </target>
+    
+    <target name="tcpmon" depends="init" description=
+                "Start standalone tcp monitor application (provided by axis)">
+        <java dir="${basedir}" fork="yes" failOnError="true" 
+                 className="org.apache.axis.utils.tcpmon">
+            <classpath refid="classpath.library" />
+             <arg value="9080" />
+             <arg value="localhost" />
+             <arg value="8080" />
+         </java>
+    </target>
+
+    <!--
+    This runs the selected scenario with SimpleAxisServer locally.
+    Before you start this target be sure you have started tcpmon too 
+        in a separate
+    "ant tcpmon" call.
+    To run different scenarios use: "ant -DNumber=x scenarioTest" 
+        to run scenario x
+    -->
+    <target name="scenarioTest" depends="compile"
+        if="junit.present"
+        description="Runs all JUnit tests">
+        <runaxisfunctionaltests
+            url="http://localhost:8088"
+            httpServerTarget="start-functional-test-http-server"
+            testTarget="scenario"
+            httpStopTarget="stop-functional-test-http-server"/>
+    </target>
+
+    <target name="scenario" if="junit.present">
+        <echo message=
+          "Running interop test scenario ${Number} on SimpleAxisServer"/>
+
+        <antcall target="deployWSDD" />
+        
+        <java classname="interop.TestScenario${Number}" fork="yes" 
+                 dir="${basedir}">
+            <jvmarg value="-Djava.endorsed.dirs=${basedir}/endorsed"/>
+            <classpath refid="classpath.library"/>
+        </java>
+
+        <antcall target="undeployWSDD" />
+
+    </target>
+    
+    <!--
+    This runs the selected scenario with SimpleAxisServer locally 
+        with perfomance
+    timing switched on.
+    You may also emable the **.TIME entry in log4j.properties to get 
+        the internal
+    timing.
+    To run different scenarios use: "ant -DNumber=x scenarioTest" 
+        to run scenario x
+    -->
+    <target name="performanceTest" depends="compile"
+        if="junit.present"
+        description="Runs all JUnit tests">
+        <runaxisfunctionaltests
+            url="http://localhost:8088"
+            httpServerTarget="start-functional-test-http-server"
+            testTarget="performance"
+            httpStopTarget="stop-functional-test-http-server"/>
+    </target>
+
+    <target name="performance" if="junit.present">
+        <echo message=
+           "Running performance test scenario ${Number} on SimpleAxisServer"/>
+
+        <antcall target="deployWSDD" />
+        <java classname="interop.TestScenario${Number}" fork="yes" 
+            dir="${basedir}">
+            <jvmarg value="-Djava.endorsed.dirs=${basedir}/endorsed"/>
+       <arg value="-lhttp://localhost:8080/axis/services/Ping${Number}" />
+            <arg value="-t" />
+            <classpath refid="classpath.library"/>
+        </java>
+        <antcall target="undeployWSDD" />
+    </target>
+    
+    <target name="deployWSDD">
+      <path id="deploy_xml_files">
+      <fileset dir="${build.work}">
+        <include name="**/deploy.wsdd"/>
+      </fileset>
+      </path>
+
+      <copy todir="${build.dir}/keys">
+        <fileset dir="${dir.keys}" includes="**"/>
+      </copy>
+      <copy todir="${build.dir}/interop">
+        <fileset dir="${dir.interop}" includes="*.jks"/>
+      </copy>
+
+      <property name="deploy_xml_property" refid="deploy_xml_files"/>
+ 
+      <java classname="org.apache.axis.utils.Admin" fork="true">
+        <classpath refid="classpath.library"/>
+        <arg value="client"/>
+        <arg file="${build.work}/org/apache/ws/axis/oasis/Client_deploy.wsdd"/>
+      </java>
+        
+      <java classname="org.apache.axis.client.AdminClient" fork="yes">
+        <classpath refid="classpath.library"/>
+        <arg line="${deploy_xml_property}"/>
+      </java>
+    </target>
+    
+    <target name="undeployWSDD">
+      <path id="undeploy_xml_files">
+        <fileset dir="${build.work}">
+          <include name="**/undeploy.wsdd"/>
+        </fileset>
+      </path>
+
+      <property name="undeploy_xml_property" refid="undeploy_xml_files"/>
+
+      <java classname="org.apache.axis.utils.Admin" fork="true">
+            <classpath refid="classpath.library"/>
+            <arg value="client"/>
+            <arg file=
+                 "${build.work}/org/apache/ws/axis/oasis/ping/undeploy.wsdd"/>
+      </java>
+
+      <java classname="org.apache.axis.client.AdminClient" fork="yes">
+        <classpath refid="classpath.library"/>
+        <arg line="${undeploy_xml_property}"/>
+      </java>
+    </target>
+        
+    <!-- generate a report from all the tests. 
+           requires Xalan or other XSLT engine in ant\lib-->
+
+   <target name="report" depends="init">
+        <junitreport todir="${build.dir}/test-reports">
+            <fileset dir="${build.dir}/test-reports">
+                <include name="TEST-*.xml"/>
+            </fileset>
+            <report format="frames" todir="${build.dir}/test-reports/html"/>
+        </junitreport>
+        <echo message=
+            "point your browser to ${build.dir}/test-reports/html/index.html"/>
+    </target>
+
+    <target name="jar"
+        depends="compile, test"
+        description="Creates the ${jar.library}">
+
+        <jar jarfile="${build.dir}/${jar.library}"
+            basedir="${build.classes}"
+            includes="**/*, *.txt"
+            excludes="components/**, *.properties, **/sandbox/**, wssec/**, **/interop/**, **/oasis/**, **/samples/**" 
+            />
+    </target>
+
+    <target name="dist" depends="bindist, otherdist, srcdist"/>
+
+   <target name="bindist" depends="gump" 
+      description="Build zip file for distro">
+     <delete dir="${dir.dist}"/>
+     <mkdir dir="${dir.dist}"/>
+     <jar jarfile="${dir.dist}/${jar.library}"
+       basedir="${build.classes}"
+       includes="**/apache/**/security/**"  />
+     <zip destfile=
+        "${dir.dist}/${product.shortname}-bin-${product.version}.zip">
+        <zipfileset prefix="wss4j" dir="."
+          includes="keys/**, interop/**, interop2/**, test/**, samples/**,
+          LICENSE.txt, README.txt, NOTICE, legal/**, webapps/**"/>
+        <zipfileset prefix="wss4j/classes" dir="${build.classes}"
+          includes=
+     "*.properties, interop/**, wssec/**, org/**/oasis/**, org/**/samples/**"/>
+        <zipfileset prefix="wss4j/doc/api" dir="${build.javadoc}"/>
+        <zipfileset fullpath="wss4j/${jar.library}" dir="${dir.dist}" 
+          includes="${jar.library}"/>
+      </zip>
+    </target>
+
+    <target name="otherdist" depends="init" 
+             description="Build zip for required jars">
+         <mkdir dir="${dir.dist}"/>
+         <zip destfile=
+           "${dir.dist}/${product.shortname}-otherjars-${product.version}.zip">
+             <zipfileset prefix="wss4j" dir="."
+                 includes="lib/*.jar, endorsed/*.jar"/>
+         </zip>
+     </target>  
+    
+    <target name="srcdist" depends="init" description=
+               "Build source zip file for distro">
+        <mkdir dir="${dir.dist}"/>
+        <zip destfile=
+                 "${dir.dist}/${product.shortname}-src-${product.version}.zip">
+            <zipfileset prefix="wss4j" dir="."
+                includes="src/** LICENSE.txt README.txt NOTICE legal/** build.xml "/>
+        </zip>
+    </target>
+
+    <target name="fixcrlf"
+        description="Fixes CRLF">
+        <fixcrlf srcdir="."
+            eol="crlf"
+            includes="**/*.java"
+            />
+        <fixcrlf srcdir="."
+            eol="crlf"
+            includes="**/*.properties"
+            />
+    </target>
+
+    <target name="changelog"
+        depends="prepare"
+        description="Generate the changelog for WSS4J project">
+        <cvschangelog dir="."
+            destfile="${build.dir}/changelog.xml"
+            />
+        <style in="${build.dir}/changelog.xml"
+            out="${build.dir}/changelog.html"
+            style="./tools/changelog.xsl">
+            <param name="title" expression="WSS4J ChangeLog"/>
+            <param name="module" expression="ws-wss4j"/>
+            <param name="cvsweb" expression="http://cvs.apache.org/viewcvs/"/>
+        </style>
+    </target>
+
+  <!-- =================================================================== -->
+  <!-- Creates a war file for interop testing                              -->
+  <!-- =================================================================== -->
+  <target name="interop-war" depends="test"
+      description="Create the web application" >
+    <mkdir dir="${build.webapp}"/>
+    <copy todir="${build.webapp}">
+      <fileset dir="${dir.webapp}"/>
+    </copy>
+    <copy todir="${build.webapp}/WEB-INF/lib">
+      <fileset dir="${dir.libs}">
+        <include name="*.jar"/>
+      </fileset>
+      <fileset dir="${basedir}/endorsed">
+        <include name="*.jar"/>
+      </fileset>
+    </copy>
+    <copy todir="${build.webapp}/WEB-INF">
+      <fileset dir="${build.dir}">
+        <include name="*.wsdd"/>
+      </fileset>
+    </copy>
+    <copy todir="${build.webapp}/WEB-INF/classes/">
+      <fileset dir="${build.classes}"/>
+    </copy>
+    <copy todir="${build.webapp}/WEB-INF/classes/">
+      <fileset dir=".">
+          <include name="client-config.wsdd"/>
+      </fileset>
+    </copy>
+    <copy todir="${build.webapp}/WEB-INF/classes/interop">
+        <fileset dir="${dir.interop}">
+            <include name="**/interop2.jks"/>
+        </fileset>
+    </copy>
+
+    <delete>
+      <fileset dir="${build.webapp}" includes="**/CVS"/>
+    </delete>
+    <path id="deploy_xml_files">
+        <fileset dir="${build.work}">
+            <include name="**/deploy.wsdd"/>
+        </fileset>
+    </path>
+    <property name="deploy_xml_property" refid="deploy_xml_files"/>
+    <java classname="org.apache.axis.utils.Admin" fork="true"
+        dir="${build.webapp}/WEB-INF/classes">
+      <classpath refid="classpath.library"/>
+      <arg value="client"/>
+      <arg file="${build.work}/org/apache/ws/axis/oasis/Client_deploy.wsdd"/>
+    </java>
+    <java classname="org.apache.axis.utils.Admin" fork="yes" 
+        dir="${build.webapp}/WEB-INF">
+        <classpath refid="classpath.library"/>
+        <arg line="server"/>
+        <arg line="${deploy_xml_property}"/>
+    </java>
+
+    <jar jarfile="${build.dir}/wss4j.war" basedir="${build.webapp}"/>
+  </target>
+
+</project>
diff --git a/trunk/endorsed/xercesImpl.jar b/trunk/endorsed/xercesImpl.jar
new file mode 100644
index 0000000..eac75ae
--- /dev/null
+++ b/trunk/endorsed/xercesImpl.jar
Binary files differ
diff --git a/trunk/endorsed/xml-apis.jar b/trunk/endorsed/xml-apis.jar
new file mode 100644
index 0000000..243eaea
--- /dev/null
+++ b/trunk/endorsed/xml-apis.jar
Binary files differ
diff --git a/trunk/interop/WSETEST.cer b/trunk/interop/WSETEST.cer
new file mode 100644
index 0000000..1ad4118
--- /dev/null
+++ b/trunk/interop/WSETEST.cer
Binary files differ
diff --git a/trunk/interop/build.xml b/trunk/interop/build.xml
new file mode 100644
index 0000000..a72abfe
--- /dev/null
+++ b/trunk/interop/build.xml
@@ -0,0 +1,102 @@
+<project name="Axis_OASIS_Interop" default="compile">
+    <description>
+        generate files from WSDL description, also target to deploy
+        the service in a runing Axis (probably in Tomcat or alike)
+    </description>
+
+    <!-- The following setting assumes that all necessary libs (jars)
+      are located in a lib directory directly under wss4j. First set
+      a reference to the wss4j relative to this working directory -->
+    <property name="dir.wss4j" value="${basedir}/.."/>
+    <property name="dir.interop" value="${dir.wss4j}/interop"/>
+    <property name="dir.work" value="${dir.wss4j}/build/work"/>
+    <property name="dir.classes" value="${dir.wss4j}/build/classes"/>
+    <property name="dir.libs" value="${dir.wss4j}/lib"/>
+
+    <property name="server" value="org/apache/ws/axis/oasis/ping"/>
+    <property name="client" value="org/apache/ws/axis/oasis"/>
+
+    <path id="classpath.libraries" description=" 3rd party and Axis libs">
+        <fileset dir="${dir.libs}">
+            <include name="**/*.jar"/>
+        </fileset>
+    </path>
+
+    <taskdef resource="axis-tasks.properties" classpathref="classpath.libraries"/>
+
+    <target name="clientdeploy">
+        <java classname="org.apache.axis.utils.Admin" fork="true">
+            <classpath refid="classpath.libraries"/>
+            <arg value="client"/>
+            <arg file="${dir.work}/${client}/Client_deploy.wsdd"/>
+        </java>
+    </target>
+
+    <target name="serverdeploy">
+        <java classname="org.apache.axis.client.AdminClient" fork="true">
+            <classpath refid="classpath.libraries"/>
+            <arg file="${dir.work}/${server}/deploy.wsdd"/>
+        </java>
+    </target>
+
+    <target name="serverundeploy">
+        <java classname="org.apache.axis.client.AdminClient" fork="true">
+            <classpath refid="classpath.libraries"/>
+            <arg file="${dir.work}/${server}/undeploy.wsdd"/>
+        </java>
+    </target>
+
+    <target name="chkWsdl">
+      <uptodate property="wsdl.notRequired" 
+        targetfile="${dir.work}/${server}/PingBindingImpl.java"
+        srcfile="${dir.interop}/ping.wsdl"/>
+    </target>
+
+    <target name="wsdl" depends="chkWsdl" unless="wsdl.notRequired">
+      <axis-wsdl2java
+          output="${dir.work}"
+          serverSide="yes"
+          testcase="no"
+          verbose="no"
+          url="${dir.interop}/ping.wsdl">
+          <mapping
+              namespace="http://xmlsoap.org/Ping"
+              package="org.apache.ws.axis.oasis.ping"/>
+      </axis-wsdl2java>
+    </target>
+
+    <target name="init">
+      <mkdir dir="${dir.work}"/>
+    </target>
+
+    <target name="compile" depends="init, wsdl">
+        <copy todir="${dir.work}/${server}" overwrite="yes">
+          <fileset dir="${dir.interop}/${server}">
+            <include name="*.java"/>
+            <include name="*.wsdd"/>
+          </fileset>
+        </copy>
+        <copy todir="${dir.work}/${client}" overwrite="yes">
+          <fileset dir="${dir.interop}/${client}">
+            <include name="*.java"/>
+            <include name="*.wsdd"/>
+          </fileset>
+        </copy>
+        <javac srcdir="${dir.work}" 
+                destdir="${dir.classes}"
+                source="1.4"
+               debug="true">
+          <classpath refid="classpath.libraries" />
+          <include name="${server}/*.java" />
+          <include name="${client}/*.java" />
+        </javac>
+    </target>
+
+    <target name="clean"
+        description="clean up">
+        <delete dir="${dir.work}/${server}"/>
+        <delete dir="${dir.classes}/${server}"/>
+        <delete dir="${dir.work}/${client}"/>
+        <delete dir="${dir.classes}/${client}"/>
+    </target>
+</project>
\ No newline at end of file
diff --git a/trunk/interop/interop.jks b/trunk/interop/interop.jks
new file mode 100644
index 0000000..c8a34a9
--- /dev/null
+++ b/trunk/interop/interop.jks
Binary files differ
diff --git a/trunk/interop/interop2.jks b/trunk/interop/interop2.jks
new file mode 100644
index 0000000..babac0f
--- /dev/null
+++ b/trunk/interop/interop2.jks
Binary files differ
diff --git a/trunk/interop/keys/Alice.cer b/trunk/interop/keys/Alice.cer
new file mode 100644
index 0000000..a23c79b
--- /dev/null
+++ b/trunk/interop/keys/Alice.cer
Binary files differ
diff --git a/trunk/interop/keys/Bob.cer b/trunk/interop/keys/Bob.cer
new file mode 100644
index 0000000..1b8b8ee
--- /dev/null
+++ b/trunk/interop/keys/Bob.cer
Binary files differ
diff --git a/trunk/interop/keys/README.txt b/trunk/interop/keys/README.txt
new file mode 100644
index 0000000..380c8b7
--- /dev/null
+++ b/trunk/interop/keys/README.txt
@@ -0,0 +1,34 @@
+- Certificates and keys are from the Gartner WSS interop show. 
+- Passwords for every private key is 'password' (no quotes). 
+- Bob identity for service and Alice identity for client.
+- The ca.pfx files contains cert and private key for intermediary CA 
+  used to issue Alice and Bob certificates and root.pfx contains cert 
+  and private key for root CA used to issue the intermediary CA 
+  certificate.
+- Conversion tips are from http://mark.foster.cc/kb/openssl-keytool.html
+- Please use JDK1.5 (importing WssIP has problems with JDK1.4)
+
+set CLASSPATH=org.mortbay.jetty-5.1.4rc0.jar;
+
+java org.mortbay.util.PKCS12Import alice.pfx interop2.jks
+keytool -keyclone -keystore interop2.jks -alias 1 -dest alice
+keytool -delete -keystore interop2.jks -alias 1
+
+java org.mortbay.util.PKCS12Import bob.pfx interop2.jks
+keytool -keyclone -keystore interop2.jks -alias 1 -dest bob
+keytool -delete -keystore interop2.jks -alias 1
+
+java org.mortbay.util.PKCS12Import WssIP.pfx interop2.jks
+keytool -keyclone -keystore interop2.jks -alias "wssip's oasis interop test ca id" -dest wssip
+keytool -delete -keystore interop2.jks -alias "wssip's oasis interop test ca id"
+
+java org.mortbay.util.PKCS12Import ca.pfx ca.jks
+java org.mortbay.util.PKCS12Import root.pfx root.jks
+
+keytool -export -alias 1 -keystore root.jks -file root.crt
+keytool -export -alias 1 -keystore ca.jks -file ca.crt
+
+keytool -import -keystore interop2.jks -import -trustcacerts -alias root -file root.crt
+keytool -import -keystore interop2.jks -import -trustcacerts -alias ca -file ca.crt
+
+keytool -list -v -keystore interop2.jks
\ No newline at end of file
diff --git a/trunk/interop/keys/WssIP.cer b/trunk/interop/keys/WssIP.cer
new file mode 100644
index 0000000..df21df8
--- /dev/null
+++ b/trunk/interop/keys/WssIP.cer
Binary files differ
diff --git a/trunk/interop/keys/WssIP.pfx b/trunk/interop/keys/WssIP.pfx
new file mode 100644
index 0000000..e68c46a
--- /dev/null
+++ b/trunk/interop/keys/WssIP.pfx
Binary files differ
diff --git a/trunk/interop/keys/alice.pfx b/trunk/interop/keys/alice.pfx
new file mode 100644
index 0000000..8d1e2f2
--- /dev/null
+++ b/trunk/interop/keys/alice.pfx
Binary files differ
diff --git a/trunk/interop/keys/bob.pfx b/trunk/interop/keys/bob.pfx
new file mode 100644
index 0000000..4cda657
--- /dev/null
+++ b/trunk/interop/keys/bob.pfx
Binary files differ
diff --git a/trunk/interop/keys/ca.cer b/trunk/interop/keys/ca.cer
new file mode 100644
index 0000000..d73fb39
--- /dev/null
+++ b/trunk/interop/keys/ca.cer
Binary files differ
diff --git a/trunk/interop/keys/ca.pfx b/trunk/interop/keys/ca.pfx
new file mode 100644
index 0000000..7f264a7
--- /dev/null
+++ b/trunk/interop/keys/ca.pfx
Binary files differ
diff --git a/trunk/interop/keys/root.cer b/trunk/interop/keys/root.cer
new file mode 100644
index 0000000..e20d049
--- /dev/null
+++ b/trunk/interop/keys/root.cer
Binary files differ
diff --git a/trunk/interop/keys/root.pfx b/trunk/interop/keys/root.pfx
new file mode 100644
index 0000000..e6d14f3
--- /dev/null
+++ b/trunk/interop/keys/root.pfx
Binary files differ
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Client_deploy.wsdd b/trunk/interop/org/apache/ws/axis/oasis/Client_deploy.wsdd
new file mode 100644
index 0000000..a6f6fae
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Client_deploy.wsdd
@@ -0,0 +1,281 @@
+<deployment xmlns="http://xml.apache.org/axis/wsdd/"
+            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
+
+ <!--
+ Usage of cert/key identifiers (parameter: user / encryptionUser):
+ For the interop tests we have two different certificate/key pairs:
+ Server certificate: 
+ 	contained in bob.pfx
+ 	identified with: bob
+ Client certificate:
+    contained in alice.pfx
+    identified with: alice
+ 
+ The Server uses it's certificate/private key to sign its request, the client
+ uses the server's certificate/pub key to encrypt requests
+
+ The client uses it's certificate/private key to sign its request, the server 
+ uses the client's certificate/pub key to encrypt responses-
+ -->
+ <!-- define the service, using the WSDoAllSender security handler in request flow -->
+ <service name="Ping1">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="user" value="Chris"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="UsernameToken"/>
+    <parameter name="passwordType" value="PasswordText" />
+   </handler>
+  </requestFlow>
+  </service>
+
+ <service name="Ping2">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="UsernameToken Encrypt"/>
+    <parameter name="user" value="Chris"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="passwordType" value="PasswordText" />
+    <parameter name="addUTElements" value="Nonce Created" />
+    <parameter name="encryptionPropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />    
+    <!-- Use the Server's cert/key to encrypt the request -->
+    <parameter name="encryptionUser" value="bob" />
+    <parameter name="encryptionParts" 
+      value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken" />  
+   </handler>
+  </requestFlow>
+  </service>
+  
+ <service name="Ping2a">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="UsernameTokenSignature Encrypt Timestamp"/>
+    <parameter name="user" value="Chris"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="encryptionPropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />    
+    <!-- Use the Server's cert/key to encrypt the request -->
+    <parameter name="encryptionUser" value="bob" />
+    <parameter name="encryptionParts" 
+      value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken" />  
+   </handler>
+  </requestFlow>
+  </service>
+
+ <service name="Ping2b">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="UsernameTokenSignature Timestamp"/>
+    <parameter name="user" value="Chris"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="passwordType" value="PasswordDigest" />
+    <parameter name="signatureParts" 
+      value="Body;{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken" />  
+    
+   </handler>
+  </requestFlow>
+  </service>
+
+ <service name="Ping3">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <!-- Use the Client's cert/key to sign the request -->
+    <parameter name="user" value="alice"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />    
+    <parameter name="encryptionUser" value="bob" />
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+   </handler>
+  </responseFlow>
+ </service>
+
+ <service name="Ping4">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <!-- Use the Client's cert/key to sign the request -->
+    <parameter name="user" value="alice"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="EmbeddedKeyName" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
+    <parameter name="EmbeddedKeyCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1" />
+    <parameter name="EmbeddedKeyName" value="SessionKey" />
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/>
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+   </handler>
+  </responseFlow>
+  
+  </service>
+
+ <service name="Ping5">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Signature NoSerialization"/>
+    <!-- Use the Client's cert/key to sign the request -->
+    <parameter name="user" value="alice"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="signatureParts" value="{}{http://xmlsoap.org/Ping}ticket" />    
+   </handler>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Signature Timestamp"/>
+    <!-- Use the Client's cert/key to sign the request -->
+    <parameter name="user" value="alice"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+   </handler>  
+  </requestFlow>
+  </service>
+
+ <service name="Ping6">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Encrypt Signature Timestamp"/>
+    <!-- Use the Client's cert/key to sign the request -->
+    <parameter name="user" value="alice"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />    
+    <!-- Use the Server's cert/key to encrypt the request -->
+    <parameter name="encryptionUser" value="bob" />
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="Encrypt Signature Timestamp"/>
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+   </handler>
+  </responseFlow>
+  </service>
+
+
+ <service name="Ping7">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <parameter name="user" value="alice"/>
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="signatureParts"
+      value="{}{http://schemas.xmlsoap.org/soap/envelope/}Body;STRTransform" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />    
+    <parameter name="encryptionUser" value="bob" />
+    <parameter name="encryptionPropFile" value="wsstest.properties" />
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="decryptionPropFile" value="wsstest.properties" />
+   </handler>
+  </responseFlow>
+  </service>
+
+ <service name="STPing1">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Timestamp SAMLTokenUnsigned"/>
+    <parameter name="samlPropFile" value="saml.properties"/>
+    
+   </handler>
+  </requestFlow>
+  </service>
+  
+  <!--
+    The saml3.properties file defines a SAML token with "sender vouches"
+    option. Thus no further user specific data is required here. The
+    SAML issuer takes all the data from its data store (for the bare bone
+    SAML issuer included here: these data is in the saml properties file).
+    The SAML issuer uses its own certificate to sign, own certificate store,
+    etc.
+    
+    The DoAllSender then gets the issuer's data (key name, key password)
+    and forwards it to the SignEnvelope. The SignEnvelope now signs the
+    SAML token _and_ at least one part of the message (SOAP Body if nothing
+    was specified, or the specified part).
+   --> 
+   <service name="STPing3">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Timestamp SAMLTokenSigned"/>
+    <parameter name="samlPropFile" value="saml3.properties"/>
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+   </handler>
+  </requestFlow>
+  </service>
+  
+  <!--
+    The saml4.properties file defines a SAML token with "holder-of-key"
+    option. Because the DoAllSender handler acts as both, user and requestor,
+    we need the user specific data here. The handler gets this information,
+    forwards it to our (bare bone) SAML issuer. The SAML issuer creates
+    the SAML token and includes the user's certificate, and signs the
+    whole token with its certificate / Private Key.
+    
+    DoAllSender forwards the user's information to SignEnvelope that uses
+    this to sign the message (SOAP Body if nothing was specified, or the 
+    specified part). Because the issuer signed the SAML token the user's
+    certificate (contained in the token) can be trusted.
+   --> 
+   <service name="STPing4">
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Timestamp SAMLTokenSigned"/>
+    <parameter name="samlPropFile" value="saml4.properties"/>
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/>
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback"/>
+    <parameter name="signaturePropFile" value="crypto.properties" />    
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+   </handler>
+  </requestFlow>
+  </service>
+  
+ <transport name="java" pivot="java:org.apache.axis.transport.java.JavaSender"/>
+ <transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
+ <transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender"/>
+  
+  
+ </deployment>
diff --git a/trunk/interop/org/apache/ws/axis/oasis/PWCallback.java b/trunk/interop/org/apache/ws/axis/oasis/PWCallback.java
new file mode 100644
index 0000000..d2302b3
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/PWCallback.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/**
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com)
+ */
+package org.apache.ws.axis.oasis;
+
+import org.apache.ws.security.WSPasswordCallback;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+/**
+ * Class PWCallback
+ */
+public class PWCallback implements CallbackHandler {
+
+    /** Field key */
+    private static final byte[] key = {
+        (byte) 0x31, (byte) 0xfd, (byte) 0xcb, (byte) 0xda, (byte) 0xfb,
+        (byte) 0xcd, (byte) 0x6b, (byte) 0xa8, (byte) 0xe6, (byte) 0x19,
+        (byte) 0xa7, (byte) 0xbf, (byte) 0x51, (byte) 0xf7, (byte) 0xc7,
+        (byte) 0x3e, (byte) 0x80, (byte) 0xae, (byte) 0x98, (byte) 0x51,
+        (byte) 0xc8, (byte) 0x51, (byte) 0x34, (byte) 0x04,
+    };
+
+    /*
+     * (non-Javadoc)
+     * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
+     */
+
+    /**
+     * Method handle
+     * 
+     * @param callbacks 
+     * @throws IOException                  
+     * @throws UnsupportedCallbackException 
+     */
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                if (pc.getUsage() == WSPasswordCallback.KEY_NAME) {
+                    pc.setKey(key);
+                } else {
+                    pc.setPassword("security");
+                }
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/PWCallback1.java b/trunk/interop/org/apache/ws/axis/oasis/PWCallback1.java
new file mode 100644
index 0000000..ec18e08
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/PWCallback1.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/**
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com)
+ */
+package org.apache.ws.axis.oasis;
+
+import org.apache.ws.security.WSPasswordCallback;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+
+/**
+ * Class PWCallback
+ */
+public class PWCallback1 implements CallbackHandler {
+
+    /** Field key */
+    private static final byte[] key = {
+        (byte) 0x31, (byte) 0xfd, (byte) 0xcb, (byte) 0xda, (byte) 0xfb,
+        (byte) 0xcd, (byte) 0x6b, (byte) 0xa8, (byte) 0xe6, (byte) 0x19,
+        (byte) 0xa7, (byte) 0xbf, (byte) 0x51, (byte) 0xf7, (byte) 0xc7,
+        (byte) 0x3e, (byte) 0x80, (byte) 0xae, (byte) 0x98, (byte) 0x51,
+        (byte) 0xc8, (byte) 0x51, (byte) 0x34, (byte) 0x04,
+
+    };
+
+
+    /*
+     * (non-Javadoc)
+     * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
+     */
+
+
+    /**
+     * Method handle
+     * 
+     * @param callbacks 
+     * @throws java.io.IOException                  
+     * @throws javax.security.auth.callback.UnsupportedCallbackException 
+     */
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+
+                /*
+                 * This usage type is used only in case we received a
+                 * username token with a password of type PasswordText or
+                 * an unknown password type.
+                 * 
+                 * This case the WSPasswordCallback object contains the
+                 * identifier (aka username), the password we received, and
+                 * the password type string to identify the type.
+                 * 
+                 * Here we perform only a very simple check.
+                 */
+
+                if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {
+                    if(pc.getIdentifier().equals("Ron") && pc.getPassword().equals("noR")) {
+                        return;
+                    }
+                    if (pc.getPassword().equals("sirhC")) {
+                        return;
+                    }
+                    throw new UnsupportedCallbackException(callbacks[i],
+                    "check failed");
+                }
+
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+
+                if (pc.getUsage() == WSPasswordCallback.KEY_NAME) {
+                    pc.setKey(key);
+                } else if(pc.getIdentifier().equals("alice")) {
+                    pc.setPassword("password");
+                } else if(pc.getIdentifier().equals("bob")) {
+                    pc.setPassword("password");
+                } else if(pc.getIdentifier().equals("Ron")) {
+                    pc.setPassword("noR");
+                } else {
+                    pc.setPassword("sirhC");
+                }
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+}
+
diff --git a/trunk/interop/org/apache/ws/axis/oasis/STScenario1.java b/trunk/interop/org/apache/ws/axis/oasis/STScenario1.java
new file mode 100644
index 0000000..35aaa7e
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/STScenario1.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario1
+ */
+public class STScenario1 {
+
+    /** Field address */
+    private static final String address =
+            "http://localhost:9080/axis/services/STPing1";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getSTPing1(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - ST Scenario 1 text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/STScenario3.java b/trunk/interop/org/apache/ws/axis/oasis/STScenario3.java
new file mode 100644
index 0000000..2bcd2ca
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/STScenario3.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario1
+ */
+public class STScenario3 {
+
+    /** Field address */
+    private static final String address =
+            "http://localhost:9080/axis/services/STPing3";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getSTPing3(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - ST Scenario 3 text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/STScenario4.java b/trunk/interop/org/apache/ws/axis/oasis/STScenario4.java
new file mode 100644
index 0000000..5b7a132
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/STScenario4.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario1
+ */
+public class STScenario4 {
+
+    /** Field address */
+    private static final String address =
+            "http://localhost:9080/axis/services/STPing4";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getSTPing4(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - ST Scenario 4 text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Scenario1.java b/trunk/interop/org/apache/ws/axis/oasis/Scenario1.java
new file mode 100644
index 0000000..8fd2ae8
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Scenario1.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario1
+ */
+public class Scenario1 {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:9080/axis/services/Ping1";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing1(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario 1 text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Scenario2.java b/trunk/interop/org/apache/ws/axis/oasis/Scenario2.java
new file mode 100644
index 0000000..3c72968
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Scenario2.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario2
+ */
+public class Scenario2 {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:9080/axis/services/Ping2";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing2(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario 2 text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Scenario2a.java b/trunk/interop/org/apache/ws/axis/oasis/Scenario2a.java
new file mode 100644
index 0000000..58495b2
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Scenario2a.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario2a
+ */
+public class Scenario2a {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:9080/axis/services/Ping2a";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing2a(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario 2a text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Scenario2b.java b/trunk/interop/org/apache/ws/axis/oasis/Scenario2b.java
new file mode 100644
index 0000000..3122baf
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Scenario2b.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario2b
+ */
+public class Scenario2b {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:9080/axis/services/Ping2b";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing2b(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario 2b text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Scenario3.java b/trunk/interop/org/apache/ws/axis/oasis/Scenario3.java
new file mode 100644
index 0000000..5e98a3d
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Scenario3.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario3
+ */
+public class Scenario3 {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:9080/axis/services/Ping3";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing3(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario 3 text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+//        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+//                System.out.println("\nLoop #" + i);
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Scenario4.java b/trunk/interop/org/apache/ws/axis/oasis/Scenario4.java
new file mode 100644
index 0000000..caa262a
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Scenario4.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario4
+ */
+public class Scenario4 {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:9080/axis/services/Ping4";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing4(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario 4 text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Scenario5.java b/trunk/interop/org/apache/ws/axis/oasis/Scenario5.java
new file mode 100644
index 0000000..619dfea
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Scenario5.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+import org.apache.ws.axis.oasis.ping.TicketType;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario5
+ */
+public class Scenario5 {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:9080/axis/services/Ping5";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing5(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario 5 - text");
+        TicketType type = 
+                new TicketType("WSS4J - Scenario 5 - TicketType");
+        
+        port.ping(type, text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(type, text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Scenario6.java b/trunk/interop/org/apache/ws/axis/oasis/Scenario6.java
new file mode 100644
index 0000000..f620b6e
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Scenario6.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario6
+ */
+public class Scenario6 {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:9080/axis/services/Ping6";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing6(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario 6 text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Scenario7.java b/trunk/interop/org/apache/ws/axis/oasis/Scenario7.java
new file mode 100644
index 0000000..1f875b7
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Scenario7.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Scenario6
+ */
+public class Scenario7 {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:9080/axis/services/Ping7";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing7(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario 7 text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/Tester.java b/trunk/interop/org/apache/ws/axis/oasis/Tester.java
new file mode 100644
index 0000000..b7a36fe
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/Tester.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.oasis;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+
+import javax.xml.rpc.holders.StringHolder;
+
+/**
+ * Class Tester
+ */
+public class Tester {
+
+    /** Field address */
+    private static final java.lang.String address =
+            "http://localhost:8081/axis/services/SecHttp";
+
+    /**
+     * Method main
+     * 
+     * @param args 
+     * @throws Exception 
+     */
+    public static void main(String[] args) throws Exception {
+
+        Options opts = new Options(args);
+        opts.setDefaultURL(address);
+
+        /*
+         *     Start to prepare service call. Once this is done, several
+         *     calls can be made on the port (see below)
+         *
+         *     Fist: get the service locator. This implements the functionality
+         *     to get a client stub (aka port).
+         */
+        PingServiceLocator service = new PingServiceLocator();
+
+        /*
+         *     this is a JAX-RPC compliant call. It uses a preconfigured
+         *     endpoint address (usually contained in the WSDL). Note the
+         *     cast.
+         *    
+         * SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+         *     Here we use an Axis specific call that allows to override the
+         *     port address (service endpoint address) with an own URL. Comes
+         *     in handy for testing.
+         */
+        java.net.URL endpoint;
+
+        try {
+            endpoint = new java.net.URL(opts.getURL());
+        } catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+
+        PingPort port = (PingPort) service.getPing1(endpoint);
+
+        /*
+         *     At this point all preparations are done. Using the port we can
+         *     now perform as many calls as necessary.
+         */
+
+        // perform call
+        StringHolder text =
+                new StringHolder("WSS4J - Tester text");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+        System.out.println(text.value);
+
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+
+            for (int i = 0; i < 20; i++) {
+                port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J"), text);
+            }
+
+            long endTime = System.currentTimeMillis();
+
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/ping/PingBindingImpl.java b/trunk/interop/org/apache/ws/axis/oasis/ping/PingBindingImpl.java
new file mode 100644
index 0000000..6e9d6ae
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/ping/PingBindingImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/**
+ * PingBindingImpl.java
+ *
+ * This file was auto-generated from WSDL
+ * by the Apache Axis 1.2dev Oct 27, 2003 (02:34:09 EST) WSDL2Java emitter.
+ */
+
+package org.apache.ws.axis.oasis.ping;
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.handler.WSHandlerResult;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.handler.WSHandlerResult;
+
+import javax.xml.rpc.holders.StringHolder;
+import java.security.Principal;
+import java.util.Vector;
+
+public class PingBindingImpl
+    implements org.apache.ws.axis.oasis.ping.PingPort {
+    
+    public void ping(
+        org.apache.ws.axis.oasis.ping.TicketType pingTicket, 
+        StringHolder text
+    ) throws java.rmi.RemoteException {
+        MessageContext msgContext = MessageContext.getCurrentContext();
+        Message reqMsg = msgContext.getRequestMessage();
+
+        Vector results = 
+            (Vector) msgContext.getProperty(WSHandlerConstants.RECV_RESULTS);
+        if (results == null) {
+            System.out.println("No security results!!");
+        }
+        // System.out.println("Number of results: " + results.size());
+        for (int i = 0; i < results.size(); i++) {
+            WSHandlerResult rResult =
+                (WSHandlerResult) results.get(i);
+            Vector wsSecEngineResults = rResult.getResults();
+
+            for (int j = 0; j < wsSecEngineResults.size(); j++) {
+                WSSecurityEngineResult wser =
+                    (WSSecurityEngineResult) wsSecEngineResults.get(j);
+                int action = 
+                    ((java.lang.Integer)wser.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
+                Principal principal = 
+                    (Principal)wser.get(WSSecurityEngineResult.TAG_PRINCIPAL);
+                if (action != WSConstants.ENCR && principal != null) {
+                    // System.out.println(principal.getName());
+                }
+            }
+        }
+    }
+
+}
diff --git a/trunk/interop/org/apache/ws/axis/oasis/ping/deploy.wsdd b/trunk/interop/org/apache/ws/axis/oasis/ping/deploy.wsdd
new file mode 100644
index 0000000..6976047
--- /dev/null
+++ b/trunk/interop/org/apache/ws/axis/oasis/ping/deploy.wsdd
@@ -0,0 +1,448 @@
+<!-- Use this file to deploy some handlers/chains and services      -->
+<!-- Two ways to do this:                                           -->
+<!--   java org.apache.axis.client.AdminClient deploy.wsdd          -->
+<!--      after the axis server is running                          -->
+<!-- or                                                             -->
+<!--   java org.apache.axis.utils.Admin client|server deploy.wsdd   -->
+<!--      from the same directory that the Axis engine runs         -->
+
+<deployment
+    xmlns="http://xml.apache.org/axis/wsdd/"
+    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
+
+ <globalConfiguration>
+   <parameter name="disablePrettyXML" value="true"/>
+   <parameter name="enableNamespacePrefixOptimization" value="true"/>
+ </globalConfiguration>
+
+  <!-- Services from PingService WSDL service -->
+
+  <service name="Ping1" provider="java:RPC" style="wrapped" use="literal">
+      <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+      <parameter name="wsdlServiceElement" value="PingService"/>
+      <parameter name="wsdlServicePort" value="Ping1"/>
+      <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+      <parameter name="wsdlPortType" value="PingPort"/>
+      <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
+        <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+        <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+      </operation>
+      <parameter name="allowedMethods" value="ping"/>
+
+      <typeMapping
+        xmlns:ns="http://xmlsoap.org/Ping"
+        qname="ns:ticketType"
+        type="java:org.apache.ws.axis.oasis.ping.TicketType"
+        serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+        deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+        encodingStyle=""
+      />
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="UsernameToken"/>
+   </handler>
+  </requestFlow>
+  </service>
+
+  <service name="Ping2" provider="java:RPC" style="wrapped" use="literal">
+      <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+      <parameter name="wsdlServiceElement" value="PingService"/>
+      <parameter name="wsdlServicePort" value="Ping2"/>
+      <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+      <parameter name="wsdlPortType" value="PingPort"/>
+      <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
+        <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+        <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+      </operation>
+      <parameter name="allowedMethods" value="ping"/>
+
+      <typeMapping
+        xmlns:ns="http://xmlsoap.org/Ping"
+        qname="ns:ticketType"
+        type="java:org.apache.ws.axis.oasis.ping.TicketType"
+        serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+        deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+        encodingStyle=""
+      />
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="UsernameToken Encrypt"/>
+    <parameter name="decryptionPropFile" value="wsstest.properties" />
+   </handler>
+  </requestFlow>
+  </service>
+
+  <service name="Ping2a" provider="java:RPC" style="wrapped" use="literal">
+      <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+      <parameter name="wsdlServiceElement" value="PingService"/>
+      <parameter name="wsdlServicePort" value="Ping2"/>
+      <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+      <parameter name="wsdlPortType" value="PingPort"/>
+      <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
+        <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+        <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+      </operation>
+      <parameter name="allowedMethods" value="ping"/>
+
+      <typeMapping
+        xmlns:ns="http://xmlsoap.org/Ping"
+        qname="ns:ticketType"
+        type="java:org.apache.ws.axis.oasis.ping.TicketType"
+        serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+        deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+        encodingStyle=""
+      />
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="UsernameTokenSignature UsernameToken Encrypt Timestamp"/>
+    <parameter name="decryptionPropFile" value="wsstest.properties" />
+   </handler>
+  </requestFlow>
+  </service>
+
+  <service name="Ping2b" provider="java:RPC" style="wrapped" use="literal">
+      <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+      <parameter name="wsdlServiceElement" value="PingService"/>
+      <parameter name="wsdlServicePort" value="Ping2"/>
+      <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+      <parameter name="wsdlPortType" value="PingPort"/>
+      <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
+        <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+        <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+      </operation>
+      <parameter name="allowedMethods" value="ping"/>
+
+      <typeMapping
+        xmlns:ns="http://xmlsoap.org/Ping"
+        qname="ns:ticketType"
+        type="java:org.apache.ws.axis.oasis.ping.TicketType"
+        serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+        deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+        encodingStyle=""
+      />
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="UsernameTokenSignature UsernameToken Timestamp"/>
+   </handler>
+  </requestFlow>
+  </service>
+
+  <service name="Ping3" provider="java:RPC" style="wrapped" use="literal">
+      <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+      <parameter name="wsdlServiceElement" value="PingService"/>
+      <parameter name="wsdlServicePort" value="Ping3"/>
+      <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+      <parameter name="wsdlPortType" value="PingPort"/>
+      <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
+        <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+        <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+      </operation>
+      <parameter name="allowedMethods" value="ping"/>
+
+      <typeMapping
+        xmlns:ns="http://xmlsoap.org/Ping"
+        qname="ns:ticketType"
+        type="java:org.apache.ws.axis.oasis.ping.TicketType"
+        serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+        deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+        encodingStyle=""
+      />
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <!-- Use the Server's cert/key to sign the response -->
+    <parameter name="user" value="bob"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />    
+    <!-- Use the Client's cert/key to encrypt the response -->
+    <parameter name="encryptionUser" value="alice" />
+   </handler>
+  </responseFlow>
+  </service>
+    
+  <service name="Ping4" provider="java:RPC" style="wrapped" use="literal">
+      <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+      <parameter name="wsdlServiceElement" value="PingService"/>
+      <parameter name="wsdlServicePort" value="Ping4"/>
+      <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+      <parameter name="wsdlPortType" value="PingPort"/>
+      <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
+        <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+        <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+      </operation>
+      <parameter name="allowedMethods" value="ping"/>
+
+      <typeMapping
+        xmlns:ns="http://xmlsoap.org/Ping"
+        qname="ns:ticketType"
+        type="java:org.apache.ws.axis.oasis.ping.TicketType"
+        serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+        deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+        encodingStyle=""
+      />
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <!-- Use the Server's cert/key to sign the response -->
+    <parameter name="user" value="bob"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="EmbeddedKeyName" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />    
+    <parameter name="EmbeddedKeyCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1" />
+    <parameter name="EmbeddedKeyName" value="SessionKey" />
+   </handler>
+  </responseFlow>
+  </service>
+
+  <service name="Ping5" provider="java:RPC" style="wrapped" use="literal">
+      <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+      <parameter name="wsdlServiceElement" value="PingService"/>
+      <parameter name="wsdlServicePort" value="Ping5"/>
+      <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+      <parameter name="wsdlPortType" value="PingPort"/>
+      <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
+        <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+        <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+      </operation>
+      <parameter name="allowedMethods" value="ping"/>
+
+      <typeMapping
+        xmlns:ns="http://xmlsoap.org/Ping"
+        qname="ns:ticketType"
+        type="java:org.apache.ws.axis.oasis.ping.TicketType"
+        serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+        deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+        encodingStyle=""
+      />
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="Signature Signature Timestamp"/>
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+   </handler>
+  </requestFlow>
+  </service>
+
+  <service name="Ping6" provider="java:RPC" style="wrapped" use="literal">
+      <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+      <parameter name="wsdlServiceElement" value="PingService"/>
+      <parameter name="wsdlServicePort" value="Ping6"/>
+      <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+      <parameter name="wsdlPortType" value="PingPort"/>
+      <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
+        <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+        <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+      </operation>
+      <parameter name="allowedMethods" value="ping"/>
+
+      <typeMapping
+        xmlns:ns="http://xmlsoap.org/Ping"
+        qname="ns:ticketType"
+        type="java:org.apache.ws.axis.oasis.ping.TicketType"
+        serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+        deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+        encodingStyle=""
+      />
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="Encrypt Signature Timestamp"/>
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Encrypt Signature Timestamp"/>
+    <!-- Use the Server's cert/key to sign the response -->
+    <parameter name="user" value="bob"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="DirectReference" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />    
+    <!-- Use the Client's cert/key to encrypt the response -->
+    <parameter name="encryptionUser" value="alice" />
+   </handler>
+  </responseFlow>
+  </service>
+
+  <service name="Ping7" provider="java:RPC" style="wrapped" use="literal">
+      <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+      <parameter name="wsdlServiceElement" value="PingService"/>
+      <parameter name="wsdlServicePort" value="Ping7"/>
+      <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+      <parameter name="wsdlPortType" value="PingPort"/>
+      <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
+        <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+        <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+      </operation>
+      <parameter name="allowedMethods" value="ping"/>
+
+      <typeMapping
+        xmlns:ns="http://xmlsoap.org/Ping"
+        qname="ns:ticketType"
+        type="java:org.apache.ws.axis.oasis.ping.TicketType"
+        serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+        deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+        encodingStyle=""
+      />
+
+  <requestFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="decryptionPropFile" value="wsstest.properties" />
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="action" value="Signature Encrypt Timestamp"/>
+    <!-- Use the Server's cert/key to sign the response -->
+    <parameter name="user" value="bob"/>
+    <parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+    <parameter name="signatureKeyIdentifier" value="SKIKeyIdentifier" />
+    <parameter name="signaturePropFile" value="wsstest.properties" />
+    <parameter name="encryptionPropFile" value="wsstest.properties" />
+    <parameter name="encryptionKeyIdentifier" value="DirectReference" />
+    <parameter name="encryptionSymAlgorithm" value="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />   
+    <!-- Use the Client's cert/key to encrypt the response -->    
+    <parameter name="encryptionUser" value="alice" />
+   </handler>
+  </responseFlow>
+      
+  </service>
+    
+    <service name="STPing1" provider="java:RPC" style="wrapped" use="literal">
+        <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+        <parameter name="wsdlServiceElement" value="PingService"/>
+        <parameter name="wsdlServicePort" value="STPing1"/>
+        <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+        <parameter name="wsdlPortType" value="PingPort"/>
+        <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping">
+            <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+            <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+        </operation>
+        <parameter name="allowedMethods" value="ping"/>
+        <typeMapping
+            xmlns:ns="http://xmlsoap.org/Ping"
+            qname="ns:ticketType"
+            type="java:org.apache.ws.axis.oasis.ping.TicketType"
+            serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+            deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+            encodingStyle=""
+            />
+        <requestFlow>
+            <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+                <parameter name="action" value="Timestamp SAMLTokenUnsigned"/>
+            </handler>
+        </requestFlow>
+    </service>
+    
+    <service name="STPing3" provider="java:RPC" style="wrapped" use="literal">
+        <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+        <parameter name="wsdlServiceElement" value="PingService"/>
+        <parameter name="wsdlServicePort" value="STPing1"/>
+        <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+        <parameter name="wsdlPortType" value="PingPort"/>
+        <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping">
+            <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+            <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+        </operation>
+        <parameter name="allowedMethods" value="ping"/>
+        <typeMapping
+            xmlns:ns="http://xmlsoap.org/Ping"
+            qname="ns:ticketType"
+            type="java:org.apache.ws.axis.oasis.ping.TicketType"
+            serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+            deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+            encodingStyle=""
+            />
+		<!--
+		 ATTENTION: depending on the SAML token type (here "sender vouches") _and_
+		 the keyIdentfier specified by the sender be sure to set the correct
+		 crypto.properties
+		 
+		 action: if the sender specifies "SAMLTokenSigned" then DoAllSender
+		 performs two actions: inserting a SAML Token (unsigned) _and_ an
+		 associated Signature. Thus, at the receiver's side, we need to
+		 define both :-)
+		 -->
+
+        <requestFlow>
+            <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+                <parameter name="action" value="Timestamp Signature SAMLTokenUnsigned"/>
+                <parameter name="signaturePropFile" value="crypto.properties" />
+                
+            </handler>
+        </requestFlow>
+    </service>
+
+    <service name="STPing4" provider="java:RPC" style="wrapped" use="literal">
+        <parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
+        <parameter name="wsdlServiceElement" value="PingService"/>
+        <parameter name="wsdlServicePort" value="STPing1"/>
+        <parameter name="className" value="org.apache.ws.axis.oasis.ping.PingBindingImpl"/>
+        <parameter name="wsdlPortType" value="PingPort"/>
+        <operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping">
+            <parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
+            <parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
+        </operation>
+        <parameter name="allowedMethods" value="ping"/>
+        <typeMapping
+            xmlns:ns="http://xmlsoap.org/Ping"
+            qname="ns:ticketType"
+            type="java:org.apache.ws.axis.oasis.ping.TicketType"
+            serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
+            deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
+            encodingStyle=""
+            />
+		<!--
+		 ATTENTION: depending on the SAML token type (here "key holder") _and_
+		 the keyIdentfier specified by the sender be sure to set the correct
+		 crypto.properties
+		 
+		 action: if the sender specifies "SAMLTokenSigned" then DoAllSender
+		 performs two actions: inserting a SAML Token (unsigned) _and_ an
+		 associated Signature. Thus, at the receiver's side, we need to
+		 define both :-)
+		 -->
+        <requestFlow>
+            <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+                <parameter name="action" value="Timestamp Signature SAMLTokenUnsigned"/>
+			    <parameter name="signaturePropFile" value="crypto.properties" />
+                
+            </handler>
+        </requestFlow>
+    </service>
+
+
+</deployment>
\ No newline at end of file
diff --git a/trunk/interop/ping.wsdl b/trunk/interop/ping.wsdl
new file mode 100644
index 0000000..ca687b8
--- /dev/null
+++ b/trunk/interop/ping.wsdl
@@ -0,0 +1,102 @@
+<definitions xmlns:s1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
+             xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
+             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+             xmlns:s="http://www.w3.org/2001/XMLSchema"
+             xmlns:tns="http://xmlsoap.org/Ping"
+             xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
+             xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
+             xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
+             targetNamespace="http://xmlsoap.org/Ping"
+             xmlns="http://schemas.xmlsoap.org/wsdl/">
+    <types>
+        <s:schema elementFormDefault="qualified" targetNamespace="http://xmlsoap.org/Ping">
+            <s:import namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"/>
+            <s:element name="Ping" nillable="true" type="tns:ping"/>
+            <s:complexType name="ping">
+                <s:sequence>
+                    <s:element minOccurs="0" maxOccurs="1" name="ticket" type="tns:ticketType"/>
+                    <s:element minOccurs="1" maxOccurs="1" name="text" nillable="true" type="s:string"/>
+                </s:sequence>
+            </s:complexType>
+            <s:complexType name="ticketType">
+                <s:simpleContent>
+                    <s:extension base="s:string">
+                        <s:attribute ref="s1:Id"/>
+                    </s:extension>
+                </s:simpleContent>
+            </s:complexType>
+            <s:element name="PingResponse" nillable="true" type="tns:pingResponse"/>
+            <s:complexType name="pingResponse">
+                <s:sequence>
+                    <s:element minOccurs="1" maxOccurs="1" name="text" nillable="true" type="s:string"/>
+                </s:sequence>
+            </s:complexType>
+        </s:schema>
+        <s:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
+            <s:attribute name="Id" type="s:string"/>
+        </s:schema>
+    </types>
+    <message name="PingRequest">
+        <part name="ping" element="tns:Ping"/>
+    </message>
+    <message name="PingResponse">
+        <part name="pingResponse" element="tns:PingResponse"/>
+    </message>
+    <portType name="PingPort">
+        <operation name="Ping">
+            <input message="tns:PingRequest"/>
+            <output message="tns:PingResponse"/>
+        </operation>
+    </portType>
+    <binding name="PingBinding" type="tns:PingPort">
+        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="Ping">
+            <soap:operation soapAction="Ping" style="document"/>
+            <input>
+                <soap:body use="literal"/>
+            </input>
+            <output>
+                <soap:body use="literal"/>
+            </output>
+        </operation>
+    </binding>
+    <service name="PingService">
+        <port name="Ping1" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/Ping1"/>
+        </port>
+        <port name="Ping2" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/Ping2"/>
+        </port>
+        <port name="Ping2a" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/Ping2a"/>
+        </port>
+        <port name="Ping2b" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/Ping2b"/>
+        </port>        
+        <port name="Ping3" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/Ping3"/>
+        </port>
+        <port name="Ping4" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/Ping4"/>
+        </port>
+        <port name="Ping5" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/Ping5"/>
+        </port>
+        <port name="Ping6" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/Ping6"/>
+        </port>
+        <port name="Ping7" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/Ping7"/>
+        </port>
+        <port name="STPing1" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/STPing1"/>
+        </port>
+        <port name="STPing3" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/STPing3"/>
+        </port>
+        <port name="STPing4" binding="tns:PingBinding">
+            <soap:address location="http://localhost:9080/pingservice/STPing4"/>
+        </port>
+        
+    </service>
+</definitions>
\ No newline at end of file
diff --git a/trunk/interop/utility.xsd b/trunk/interop/utility.xsd
new file mode 100644
index 0000000..ec531e8
--- /dev/null
+++ b/trunk/interop/utility.xsd
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+OASIS takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any effort to identify any such rights. Information on OASIS's procedures with respect to rights in OASIS specifications can be found at the OASIS website. Copies of claims of rights made available for publication and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementors or users of this specification, can be obtained from the OASIS Executive Director.
+OASIS invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to implement this specification. Please address the information to the OASIS Executive Director.
+Copyright © OASIS Open 2002. All Rights Reserved.
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself does not be modified in any way, such as by removing the copyright notice or references to OASIS, except as needed for the purpose of developing OASIS specifications, in which case the procedures for copyrights defined in the OASIS Intellectual Property Rights document must be followed, or as required to translate it into languages other than English.
+The limited permissions granted above are perpetual and will not be revoked by OASIS or its successors or assigns.
+This document and the information contained herein is provided on an “AS IS” basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+-->
+<xsd:schema targetNamespace="http://schemas.xmlsoap.org/ws/2003/06/utility" xmlns="http://schemas.xmlsoap.org/ws/2003/06/utility" xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" version="0.1">
+	<!-- // Fault Codes /////////////////////////////////////////// -->
+	<xsd:simpleType name="tTimestampFault">
+		<xsd:annotation>
+			<xsd:documentation>
+This type defines the fault code value for Timestamp message expiration.
+          </xsd:documentation>
+		</xsd:annotation>
+		<xsd:restriction base="xsd:QName">
+			<xsd:enumeration value="wsu:MessageExpired"/>
+		</xsd:restriction>
+	</xsd:simpleType>
+	<!-- // Global attributes //////////////////////////////////// -->
+	<xsd:attribute name="Id" type="xsd:ID">
+		<xsd:annotation>
+			<xsd:documentation>
+This global attribute supports annotating arbitrary elements with an ID.
+          </xsd:documentation>
+		</xsd:annotation>
+	</xsd:attribute>
+	<xsd:attributeGroup name="commonAtts">
+		<xsd:annotation>
+			<xsd:documentation>
+Convenience attribute group used to simplify this schema.
+          </xsd:documentation>
+		</xsd:annotation>
+		<xsd:attribute ref="wsu:Id" use="optional"/>
+		<xsd:anyAttribute namespace="##other" processContents="lax"/>
+	</xsd:attributeGroup>
+	<!-- // Utility types //////////////////////////////////////// -->
+	<xsd:complexType name="AttributedDateTime">
+		<xsd:annotation>
+			<xsd:documentation>
+This type is for elements whose [children] is a psuedo-dateTime and can have arbitrary attributes. 
+      </xsd:documentation>
+		</xsd:annotation>
+		<xsd:simpleContent>
+			<xsd:extension base="xsd:string">
+				<xsd:attribute name="ValueType" type="xsd:QName">
+					<xsd:annotation>
+						<xsd:documentation>
+This attribute indicates the actual schema type of the element [children]. 
+If the ValueType attribute is present, conforming processors must process the string value of [children] as if it were affiliated with the type indicated by this attribute.
+If the ValueType attribute is absent, the implied value of this attribute is xsd:dateTime.
+            </xsd:documentation>
+					</xsd:annotation>
+				</xsd:attribute>
+				<xsd:attributeGroup ref="wsu:commonAtts"/>
+			</xsd:extension>
+		</xsd:simpleContent>
+	</xsd:complexType>
+	<xsd:complexType name="AttributedURI">
+		<xsd:annotation>
+			<xsd:documentation>
+This type is for elements whose [children] is an anyURI and can have arbitrary attributes.
+      </xsd:documentation>
+		</xsd:annotation>
+		<xsd:simpleContent>
+			<xsd:extension base="xsd:anyURI">
+				<xsd:attributeGroup ref="wsu:commonAtts"/>
+			</xsd:extension>
+		</xsd:simpleContent>
+	</xsd:complexType>
+	<!-- // Timestamp header components /////////////////////////// -->
+	<xsd:complexType name="TimestampType">
+		<xsd:annotation>
+			<xsd:documentation>
+This complex type ties together the timestamp related elements into a composite type.
+            </xsd:documentation>
+		</xsd:annotation>
+		<xsd:sequence>
+			<xsd:element ref="wsu:Created" minOccurs="0"/>
+			<xsd:element ref="wsu:Expires" minOccurs="0"/>
+			<xsd:choice minOccurs="0" maxOccurs="unbounded">
+				<xsd:any namespace="##other" processContents="lax"/>
+			</xsd:choice>
+		</xsd:sequence>
+		<xsd:attributeGroup ref="wsu:commonAtts"/>
+	</xsd:complexType>
+	<xsd:element name="Timestamp" type="wsu:TimestampType">
+		<xsd:annotation>
+			<xsd:documentation>
+This element allows Timestamps to be applied anywhere element wildcards are present,
+including as a SOAP header.
+            </xsd:documentation>
+		</xsd:annotation>
+	</xsd:element>
+	<!-- global element decls to allow individual elements to appear anywhere -->
+	<xsd:element name="Expires" type="wsu:AttributedDateTime">
+		<xsd:annotation>
+			<xsd:documentation>
+This element allows an expiration time to be applied anywhere element wildcards are present.
+            </xsd:documentation>
+		</xsd:annotation>
+	</xsd:element>
+	<xsd:element name="Created" type="wsu:AttributedDateTime">
+		<xsd:annotation>
+			<xsd:documentation>
+This element allows a creation time to be applied anywhere element wildcards are present.
+            </xsd:documentation>
+		</xsd:annotation>
+	</xsd:element>
+</xsd:schema>
diff --git a/trunk/interop/wsstest.properties b/trunk/interop/wsstest.properties
new file mode 100644
index 0000000..2dfd990
--- /dev/null
+++ b/trunk/interop/wsstest.properties
@@ -0,0 +1,5 @@
+org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+org.apache.ws.security.crypto.merlin.keystore.type=jks
+org.apache.ws.security.crypto.merlin.keystore.password=password
+org.apache.ws.security.crypto.merlin.file=interop/interop2.jks
+
diff --git a/trunk/interop/wsstest1.pfx b/trunk/interop/wsstest1.pfx
new file mode 100644
index 0000000..f7c781a
--- /dev/null
+++ b/trunk/interop/wsstest1.pfx
Binary files differ
diff --git a/trunk/interop/wsstest2.pfx b/trunk/interop/wsstest2.pfx
new file mode 100644
index 0000000..1ca1eb3
--- /dev/null
+++ b/trunk/interop/wsstest2.pfx
Binary files differ
diff --git a/trunk/keys/.keystore b/trunk/keys/.keystore
new file mode 100644
index 0000000..55f59c8
--- /dev/null
+++ b/trunk/keys/.keystore
Binary files differ
diff --git a/trunk/keys/BCMain.java b/trunk/keys/BCMain.java
new file mode 100644
index 0000000..9699778
--- /dev/null
+++ b/trunk/keys/BCMain.java
@@ -0,0 +1,296 @@
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.util.Enumeration;
+
+public class BCMain {
+    public static void main(String[] args) {
+        //==============================
+        // Setup stuff
+        //==============================
+
+        //Input FileName, Alias and Password
+        String jksFileName = ".keystore";
+        String jksAlias = "dims";
+        char[] jksPassword = "security".toCharArray();
+
+        //Output FileName, Alias and Password
+        String pkcs12FileName = "keystore.p12";
+        String pkcs12Alias = "dims";
+        char[] pkcs12Password = "security".toCharArray();
+
+        //Plug the Provider into the JCA/JCE
+        Security.addProvider(new BouncyCastleProvider());
+
+
+
+        //================================
+        // JKS Stuff
+        //================================
+
+        InputStream jksInputStream = null;
+        try {
+            jksInputStream = new FileInputStream(jksFileName);
+            System.out.println("Establish JKS InputStream to " +
+                    jksFileName);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+        KeyStore jksKeyStore = null;
+        try {
+            jksKeyStore = KeyStore.getInstance("JKS", "SUN");
+            System.out.println("Create JKS KeyStore Object.");
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (NoSuchProviderException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //Load the keystore
+        try {
+            jksKeyStore.load(jksInputStream, jksPassword);
+            System.out.println("Load JKS KeyStore.");
+        } catch (IOException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (CertificateException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //Fetch all aliases from the keystore.
+        Enumeration aliases = null;
+        try {
+            aliases = jksKeyStore.aliases();
+            System.out.println("Got KeyStore aliases.");
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //Shows all aliases from the keystore, only for info
+        while (aliases.hasMoreElements()) {
+            System.out.println("Has alias: " + aliases.nextElement());
+        }
+
+
+
+        //Get PrivateKey
+        RSAPrivateCrtKey jksPrivateCrtKey = null;
+        try {
+            jksPrivateCrtKey =
+                    (RSAPrivateCrtKey) jksKeyStore.getKey(jksAlias, jksPassword);
+            System.out.println("Get PKCS#12 RSAPrivateCrtKey(" + jksPrivateCrtKey +
+                    "): [Bit-Length: " + jksPrivateCrtKey.getModulus().bitLength() +
+                    ", Modulus: " + jksPrivateCrtKey.getModulus() +
+                    ", PublicExponent: " + jksPrivateCrtKey.getPublicExponent() +
+                    ", PrivateExponent: " + jksPrivateCrtKey.getPrivateExponent() +
+                    ", Prime-P: " + jksPrivateCrtKey.getPrimeP() +
+                    ", Prime-Q: " + jksPrivateCrtKey.getPrimeQ() +
+                    ", Prime-Exponent-P: " + jksPrivateCrtKey.getPrimeExponentP() +
+                    ", Prime-Exponent-Q: " + jksPrivateCrtKey.getPrimeExponentQ() +
+                    ", CRT-Coefficient: " + jksPrivateCrtKey.getCrtCoefficient()
+            );
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (UnrecoverableKeyException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //Get Certificate
+        Certificate jksCert = null;
+        try {
+            jksCert = jksKeyStore.getCertificate(jksAlias);
+            System.out.println("Get Certificate from PKCS#12: " + jksCert);
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //Get Certificate Chain
+        Certificate[] jksCerts = null;
+        try {
+            jksCerts = jksKeyStore.getCertificateChain(jksAlias);
+            System.out.println("Get Certificate Chain from JKS, with " +
+                    jksCerts.length + " certs.");
+            for (int i = 0; i < jksCerts.length; i++) {
+                System.out.println("Certificate " + (i + 1) +
+                        " from JKS in the chain: " + jksCerts[i]);
+            }
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //=====================================
+        // PKCS#12 stuff
+        //=====================================
+
+        KeyStore pkcs12KeyStore = null;
+        try {
+            pkcs12KeyStore = KeyStore.getInstance("PKCS12", "BC");
+            System.out.println("Create PKCS#12 KeyStore Object.");
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (NoSuchProviderException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+        try {
+            pkcs12KeyStore.load(null, pkcs12Password);
+            System.out.println(
+                    "Load a new fresh PKCS#12 KeyStore from scratch.");
+        } catch (IOException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (CertificateException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+        try {
+            pkcs12KeyStore.setKeyEntry(pkcs12Alias, jksPrivateCrtKey,
+                    pkcs12Password, jksCerts);
+            System.out.println("Add the RSA Private Crt Key and the " +
+                    "Certificate Chain to the PKCS#12 KeyStore.");
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+        OutputStream pkcs12OutputStream = null;
+        try {
+            pkcs12OutputStream = new FileOutputStream(pkcs12FileName);
+            System.out.println(
+                    "Establish PKCS#12 OutputStream to " + pkcs12FileName);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+        try {
+            pkcs12KeyStore.store(pkcs12OutputStream, pkcs12Password);
+            pkcs12OutputStream.close();
+            System.out.println("Store PKCS#12 KeyStore: " + pkcs12FileName);
+        } catch (IOException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (CertificateException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //=====================================
+        // Reread the pkcs12KeyStore
+        //=====================================
+
+        InputStream pkcs12InputStream = null;
+        try {
+            pkcs12InputStream = new FileInputStream(pkcs12FileName);
+            System.out.println(
+                    "Establish PKCS#12 InputStream to " + pkcs12FileName);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+        try {
+            pkcs12KeyStore.load(pkcs12InputStream, pkcs12Password);
+            System.out.println("Re-read the PKCS#12 KeyStore.");
+        } catch (IOException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (CertificateException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //Get PrivateKey
+        RSAPrivateCrtKey pkcs12PrivateCrtKey = null;
+        try {
+            pkcs12PrivateCrtKey =
+                    (RSAPrivateCrtKey) pkcs12KeyStore.getKey(pkcs12Alias, pkcs12Password);
+            System.out.println(
+                    "Get PKCS#12 RSAPrivateCrtKey(" + pkcs12PrivateCrtKey +
+                    "): [Bit-Length: " + pkcs12PrivateCrtKey.getModulus().bitLength() +
+                    ", Modulus: " + pkcs12PrivateCrtKey.getModulus() +
+                    ", PublicExponent: " + pkcs12PrivateCrtKey.getPublicExponent() +
+                    ", PrivateExponent: " + pkcs12PrivateCrtKey.getPrivateExponent() +
+                    ", Prime-P: " + pkcs12PrivateCrtKey.getPrimeP() +
+                    ", Prime-Q: " + pkcs12PrivateCrtKey.getPrimeQ() +
+                    ", Prime-Exponent-P: " + pkcs12PrivateCrtKey.getPrimeExponentP() +
+                    ", Prime-Exponent-Q: " + pkcs12PrivateCrtKey.getPrimeExponentQ() +
+                    ", CRT-Coefficient: " + pkcs12PrivateCrtKey.getCrtCoefficient()
+            );
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            System.exit(1);
+        } catch (UnrecoverableKeyException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //Get Certificate
+        Certificate pkcs12Cert = null;
+        try {
+            pkcs12Cert = pkcs12KeyStore.getCertificate(pkcs12Alias);
+            System.out.println("Get Certificate from PKCS#12: " + pkcs12Cert);
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        //Get Certificate Chain
+        Certificate[] pkcs12Certs = null;
+        try {
+            pkcs12Certs = pkcs12KeyStore.getCertificateChain(pkcs12Alias);
+            System.out.println("Get Certificate Chain from PKCS#12, with " +
+                    pkcs12Certs.length + " certs.");
+            for (int i = 0; i < pkcs12Certs.length; i++) {
+                System.out.println("Certificate " + (i + 1) +
+                        " from PKCS#12 in the chain: " + pkcs12Certs[i]);
+            }
+        } catch (KeyStoreException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+    }
+}
diff --git a/trunk/keys/CA.pem b/trunk/keys/CA.pem
new file mode 100644
index 0000000..512e7dd
--- /dev/null
+++ b/trunk/keys/CA.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDFjCCAn+gAwIBAgIJALgSDgFidfZsMA0GCSqGSIb3DQEBBQUAMGYxCzAJBgNV
+BAYTAkRFMQ8wDQYDVQQIEwZCYXllcm4xDzANBgNVBAcTBk11bmljaDENMAsGA1UE
+ChMESG9tZTEVMBMGA1UECxMMQXBhY2hlIFdTUzRKMQ8wDQYDVQQDEwZXZXJuZXIw
+HhcNMDgwNDA0MTkyODUxWhcNMDgwNTA0MTkyODUxWjBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQCuwhKUVyJwPQjPZmn9IKVh4rzqp3f5T5uqYC6V
+FRdBFcJHTONAggCoocm+gEhMmDItvCBqZJ4ShcK9rcl+pddDy8/JCjMmg8rZ+Bxd
+2wptSIZy8YL0DyCqRwnjmwu52r6VuZ5Pn3YQZoglnZLYUT7AFxG+6fSCIDnjMvqC
+Smu6YwIDAQABo4HLMIHIMB0GA1UdDgQWBBS/xbBx6JRiDGnFNU2Vv/PAXdhC+jCB
+mAYDVR0jBIGQMIGNgBS/xbBx6JRiDGnFNU2Vv/PAXdhC+qFqpGgwZjELMAkGA1UE
+BhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ0wCwYDVQQK
+EwRIb21lMRUwEwYDVQQLEwxBcGFjaGUgV1NTNEoxDzANBgNVBAMTBldlcm5lcoIJ
+ALgSDgFidfZsMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAeR9T/RnK
+yJ8ChKsDRwWv5saCmTo3O+h8YKhXqReoERLeJUrEWLxjfVGE3XdUia2EPCSzximQ
+7/8kN00uTJnRh8XlSoNPYTdQOS7FKX5MZuTOeTUJGYJQnJSIHuJhHrokW033scDJ
+yJdsotJFr0IS/nNO0taXvZiWtO1xvCiapB8=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/CAKey.pem b/trunk/keys/CAKey.pem
new file mode 100644
index 0000000..3cf1189
--- /dev/null
+++ b/trunk/keys/CAKey.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,7BB47E29807D02B0
+
+tiIERoGm/lMqiW8SJ/z5D63xBXA8u9mR9Lm0wOiZ9r5xWMRmZkHvbS5SfDw+rB8r
+R7dY4hqs7bdiCQ4x8YB9kfxFF0yLxCI8zfx93vqasXV5FPCU/MTrZJbrY4EdFcSl
+thaVxVZJDWXyrM4BhYo7p2vPNWykHMJYJcD62+Vvz+tUOzVl9zvtQr2Zpl2A9Fmc
+r5K3MAcVq9Uuu6ppBtoet8r32z1L+/mTJGPGugwDgF2gCWHJiZQtkWU3ewlk7r2v
+MG7s6Beso2G4dkbxvQwhrMeDdy9qtDLMmojDZUXwUEp1FZXeKc5XHwkLag8IswZo
+KF+F9Fb/sqG5Qw94kbaeQgsvw6AaE3tLrhdXgae+AVlIbyh8yzwByTC5BCkwgDjL
+LhfWQIXBi/sEi1ihSi+ouXm4JaupUxs7Iy/6dFFULwMMkJAf5CeWwXDwILX5ucsq
+W+NAsYBUsPRbzQEUZJRi4gQCmGHNpqVEQ53QcdUTflZNSaLVLElVt5ebO6K1be/4
+9Zi+nhNQzfssc9ZGN+lVDnEKx3KKBKgeXz7QlZH5vNGS4iPDs4Bh6s5RS3fKidkq
+gv0qKnhLjEPwvmpg0kGWW6sY+xiLy/HApdiqmLjy+feRvFtIs55Ka8Tmcg9oLQs2
+j3rNCaR8sKYqEXi42xXRi33Pm5qhA8biboT3KSpkgG2kpfLusSitV6Oz5FSy6ZvY
+se3GrQlY8SHvM7rPGhzaieL+fOfs8rrOti9Dip8xkz/IwGDLUzEg9aNi9UQ0bsvG
+aVoIl/oAVzDzcCWNErAqfRjzuRNDGGh4f4I5WIK/FNEkNbqip9O0MA==
+-----END RSA PRIVATE KEY-----
diff --git a/trunk/keys/ca.config b/trunk/keys/ca.config
new file mode 100644
index 0000000..b4abb6b
--- /dev/null
+++ b/trunk/keys/ca.config
@@ -0,0 +1,74 @@
+#

+# Beginning of file ca.config

+[ ca ]

+default_ca              = CA_own

+[ CA_own ]

+dir                     = .

+certs                   = $dir

+new_certs_dir           = $dir/ca.db.certs

+database                = $dir/ca.db.index

+serial                  = $dir/ca.db.serial

+RANDFILE                = $dir/ca.db.rand

+certificate             = $dir/CA.pem

+private_key             = $dir/CAKey.pem

+default_days            = 365

+default_crl_days        = 30

+default_md              = md5

+preserve                = no

+x509_extensions         = usr_cert

+policy                  = policy_match

+#

+[ usr_cert ]

+basicConstraints        = CA:FALSE

+nsComment               = "OpenSSL Generated Certificate"

+subjectKeyIdentifier    = hash

+authorityKeyIdentifier  = keyid,issuer:always

+[ req ]

+default_bits            = 1024

+distinguished_name      = req_distinguished_name

+x509_extensions         = v3_ca

+policy                  = policy_anything

+[ v3_req ]

+basicConstraints        = CA:FALSE

+keyUsage                = nonRepudiation, digitalSignature, keyEncipherment

+[ v3_ca ]

+subjectKeyIdentifier    = hash

+authorityKeyIdentifier  = keyid:always,issuer:always

+basicConstraints        = CA:true

+#

+# For the CA policy

+#

+[ policy_match ]

+countryName             = match

+stateOrProvinceName     = match

+organizationName        = match

+organizationalUnitName  = optional

+commonName              = supplied

+emailAddress            = optional

+#

+[ policy_anything ]

+countryName             = optional

+stateOrProvinceName     = optional

+localityName            = optional

+organizationName        = optional

+organizationalUnitName  = optional

+commonName              = supplied

+emailAddress            = optional

+#

+[ req_distinguished_name ]

+countryName             = Country Name (2 letter code)

+countryName_default     = DE

+CountryName_min         = 2

+CountryName_max         = 2

+stateOrProvinceName     = State or Province Name (full name)

+stateOrProvinceName_default = Bayern

+localityName            = Locality Name (e.g., city)

+localityName_default    = Munich

+0.organizationName      = Organization Name (e.g., company)

+0.organizationName_default = Home

+organizationalUnitName  = Organizational Unit Name (e.g., section)

+organizationalUnitName_default = Apache WSS4J

+commonName              = Common Name (e.g., your name or server name)

+commonName_max          = 64

+commonName_default		= Werner

+# end of file ca.config

diff --git a/trunk/keys/ca.crt b/trunk/keys/ca.crt
new file mode 100644
index 0000000..cc98749
--- /dev/null
+++ b/trunk/keys/ca.crt
Binary files differ
diff --git a/trunk/keys/ca.db.certs/01.pem b/trunk/keys/ca.db.certs/01.pem
new file mode 100644
index 0000000..fb2cd2d
--- /dev/null
+++ b/trunk/keys/ca.db.certs/01.pem
@@ -0,0 +1,92 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Feb 29 10:51:17 2004 GMT
+            Not After : Feb 28 10:51:17 2005 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=werner
+        Subject Public Key Info:
+            Public Key Algorithm: dsaEncryption
+            DSA Public Key:
+                pub: 
+                    00:e2:aa:a5:25:3a:2e:7b:7f:88:1a:73:a1:d1:1a:
+                    2d:5f:a1:fa:2b:bf:0c:de:55:f2:88:34:21:6c:eb:
+                    71:5a:2c:ce:e4:d1:b4:e6:7b:87:f8:33:2b:83:4c:
+                    4a:05:d0:f5:6c:50:b7:4a:aa:57:44:7a:7a:6c:e7:
+                    37:d1:2c:8d:97:98:34:e1:6b:72:a3:e9:cb:69:02:
+                    57:e9:0d:5d:ab:e8:a2:47:1d:15:01:cf:3d:7b:a8:
+                    c3:23:ea:8e:85:c9:e8:74:60:64:a8:c1:07:16:b2:
+                    87:6b:5d:c9:f8:eb:65:23:3e:2d:33:8a:9a:8f:09:
+                    e0:12:45:8d:7f:fe:44:70:e1
+                P:   
+                    00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                    e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                    51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                    c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                    6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                    10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                    c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                    54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                    f2:22:03:19:9d:d1:48:01:c7
+                Q:   
+                    00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                    84:0b:f0:58:1c:f5
+                G:   
+                    00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                    57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                    07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                    81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                    32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                    ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                    f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                    a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                    25:64:01:4c:3b:fe:cf:49:2a
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                55:B1:89:EB:BB:5E:9D:51:54:1C:50:AE:33:84:FC:22:E7:B6:4A:21
+            X509v3 Authority Key Identifier: 
+                keyid:D0:C2:5B:D0:A4:D4:EB:05:FD:7C:4C:0E:A7:1E:2F:A0:CA:68:4F:3A
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:00
+
+    Signature Algorithm: md5WithRSAEncryption
+        4b:e7:2b:8f:1b:19:92:34:52:af:b5:97:61:33:53:88:c0:dc:
+        db:fd:1c:30:11:3b:38:ab:5a:b4:4f:e6:3a:91:67:ba:89:68:
+        1e:9b:40:70:bc:0c:1d:07:c2:a0:46:c9:fb:e1:4b:02:10:fc:
+        7d:98:81:d7:98:9f:4b:7c:24:4c:1d:b1:6a:45:ca:5b:e7:44:
+        a3:e6:e8:17:8d:1d:87:72:68:86:a4:c3:04:08:b0:ca:09:78:
+        c0:2c:f5:01:3e:6e:ef:eb:64:dc:6c:1e:ad:74:2a:15:87:ec:
+        c9:b5:c4:de:47:6a:27:f7:27:a2:eb:8d:ac:16:b9:c2:2b:16:
+        ce:b0
+-----BEGIN CERTIFICATE-----
+MIIERjCCA6+gAwIBAgIBATANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA0MDIy
+OTEwNTExN1oXDTA1MDIyODEwNTExN1owYTELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMQ8wDQYDVQQDEwZ3ZXJuZXIwggG4MIIBLAYHKoZIzjgEATCCAR8C
+gYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F
+9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYV
+DwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKS
+uYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZ
+V4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFu
+o38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOB
+hQACgYEA4qqlJToue3+IGnOh0RotX6H6K78M3lXyiDQhbOtxWizO5NG05nuH+DMr
+g0xKBdD1bFC3SqpXRHp6bOc30SyNl5g04Wtyo+nLaQJX6Q1dq+iiRx0VAc89e6jD
+I+qOhcnodGBkqMEHFrKHa13J+OtlIz4tM4qajwngEkWNf/5EcOGjge4wgeswCQYD
+VR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlm
+aWNhdGUwHQYDVR0OBBYEFFWxieu7Xp1RVBxQrjOE/CLntkohMIGQBgNVHSMEgYgw
+gYWAFNDCW9Ck1OsF/XxMDqceL6DKaE86oWqkaDBmMQswCQYDVQQGEwJERTEPMA0G
+A1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUxFTAT
+BgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggEAMA0GCSqGSIb3
+DQEBBAUAA4GBAEvnK48bGZI0Uq+1l2EzU4jA3Nv9HDAROzirWrRP5jqRZ7qJaB6b
+QHC8DB0HwqBGyfvhSwIQ/H2YgdeYn0t8JEwdsWpFylvnRKPm6BeNHYdyaIakwwQI
+sMoJeMAs9QE+bu/rZNxsHq10KhWH7Mm1xN5Haif3J6LrjawWucIrFs6w
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/02.pem b/trunk/keys/ca.db.certs/02.pem
new file mode 100644
index 0000000..163081d
--- /dev/null
+++ b/trunk/keys/ca.db.certs/02.pem
@@ -0,0 +1,65 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Feb 29 12:00:29 2004 GMT
+            Not After : Feb 28 12:00:29 2005 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=wernerd
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:ad:ce:34:88:66:c7:13:0b:41:33:37:10:df:fd:
+                    87:2b:e0:3d:88:07:8d:84:7a:3c:51:1c:46:94:71:
+                    77:ad:e3:b1:4c:b3:30:0e:5d:b5:72:39:ee:89:2f:
+                    ab:bb:2f:08:2f:cd:de:a4:db:f7:4e:51:73:93:a2:
+                    21:e0:47:9f:8b:c2:58:05:c9:f4:60:8c:89:fa:d3:
+                    96:10:07:56:ce:de:06:63:e9:50:97:c1:83:3e:49:
+                    67:e5:82:eb:5f:ef:85:83:01:db:62:10:8d:27:20:
+                    3f:f3:03:40:6f:43:41:9e:e0:40:88:e5:bd:02:8f:
+                    a9:4a:10:58:83:7c:43:42:01
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                5E:61:46:E0:09:9A:44:80:9A:A4:B2:6F:04:00:24:F3:86:D6:16:8F
+            X509v3 Authority Key Identifier: 
+                keyid:D0:C2:5B:D0:A4:D4:EB:05:FD:7C:4C:0E:A7:1E:2F:A0:CA:68:4F:3A
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:00
+
+    Signature Algorithm: md5WithRSAEncryption
+        7c:35:e4:e7:63:18:af:26:77:1c:5f:cc:e6:89:2b:ac:8d:a2:
+        f9:70:60:84:58:75:40:12:6e:b2:37:47:26:92:97:5e:f1:28:
+        06:35:1a:e2:48:6b:89:f3:f0:73:52:ad:77:ce:5a:01:c0:84:
+        cf:e4:3e:a4:ee:6e:ad:93:99:6b:ec:48:27:0e:f4:8c:c9:21:
+        12:76:43:ce:1c:af:c6:2e:1c:c3:eb:8e:22:29:58:50:d2:0d:
+        01:3e:19:df:0f:51:ea:88:37:9c:66:08:a1:df:71:73:11:20:
+        b7:02:19:38:e1:2f:53:d9:0b:1f:cb:62:6c:75:fa:42:10:24:
+        ff:4a
+-----BEGIN CERTIFICATE-----
+MIIDLTCCApagAwIBAgIBAjANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA0MDIy
+OTEyMDAyOVoXDTA1MDIyODEyMDAyOVowYjELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMRAwDgYDVQQDEwd3ZXJuZXJkMIGfMA0GCSqGSIb3DQEBAQUAA4GN
+ADCBiQKBgQCtzjSIZscTC0EzNxDf/Ycr4D2IB42EejxRHEaUcXet47FMszAOXbVy
+Oe6JL6u7Lwgvzd6k2/dOUXOToiHgR5+LwlgFyfRgjIn605YQB1bO3gZj6VCXwYM+
+SWflgutf74WDAdtiEI0nID/zA0BvQ0Ge4ECI5b0Cj6lKEFiDfENCAQIDAQABo4Hu
+MIHrMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVk
+IENlcnRpZmljYXRlMB0GA1UdDgQWBBReYUbgCZpEgJqksm8EACTzhtYWjzCBkAYD
+VR0jBIGIMIGFgBTQwlvQpNTrBf18TA6nHi+gymhPOqFqpGgwZjELMAkGA1UEBhMC
+REUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ0wCwYDVQQKEwRI
+b21lMRUwEwYDVQQLEwxBcGFjaGUgV1NTNEoxDzANBgNVBAMTBldlcm5lcoIBADAN
+BgkqhkiG9w0BAQQFAAOBgQB8NeTnYxivJnccX8zmiSusjaL5cGCEWHVAEm6yN0cm
+kpde8SgGNRriSGuJ8/BzUq13zloBwITP5D6k7m6tk5lr7EgnDvSMySESdkPOHK/G
+LhzD644iKVhQ0g0BPhnfD1HqiDecZgih33FzESC3Ahk44S9T2Qsfy2JsdfpCECT/
+Sg==
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/03.pem b/trunk/keys/ca.db.certs/03.pem
new file mode 100644
index 0000000..4e91469
--- /dev/null
+++ b/trunk/keys/ca.db.certs/03.pem
@@ -0,0 +1,92 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 3 (0x3)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Mar  7 09:31:55 2004 GMT
+            Not After : Mar  7 09:31:55 2005 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=wernerdDSA
+        Subject Public Key Info:
+            Public Key Algorithm: dsaEncryption
+            DSA Public Key:
+                pub: 
+                    00:b1:0d:e9:65:0f:68:ec:6c:f0:10:af:c5:1c:42:
+                    53:c0:43:0e:ee:66:5b:33:81:53:9f:87:a2:ef:05:
+                    0e:1f:38:85:33:7e:9d:4b:d9:ba:ea:21:f4:a2:60:
+                    9d:4b:b0:2a:d4:1f:5b:cb:9f:8d:d3:45:46:ef:07:
+                    4c:a1:b9:2d:86:df:f0:81:6f:2a:36:37:b5:c3:8f:
+                    4e:06:e7:87:06:1c:d6:aa:93:10:d8:d7:9b:57:9d:
+                    2b:08:05:f5:8c:1a:fb:d2:64:dd:f4:d3:32:0f:72:
+                    e6:90:03:da:a5:19:60:54:90:be:d8:d7:58:3b:1d:
+                    02:70:61:28:06:dd:c6:f3:45
+                P:   
+                    00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                    e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                    51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                    c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                    6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                    10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                    c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                    54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                    f2:22:03:19:9d:d1:48:01:c7
+                Q:   
+                    00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                    84:0b:f0:58:1c:f5
+                G:   
+                    00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                    57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                    07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                    81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                    32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                    ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                    f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                    a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                    25:64:01:4c:3b:fe:cf:49:2a
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                0A:0E:82:F4:FE:57:60:75:CA:81:4F:78:27:3F:92:78:53:28:FF:88
+            X509v3 Authority Key Identifier: 
+                keyid:D0:C2:5B:D0:A4:D4:EB:05:FD:7C:4C:0E:A7:1E:2F:A0:CA:68:4F:3A
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:00
+
+    Signature Algorithm: md5WithRSAEncryption
+        7a:23:9b:92:0b:95:82:da:5c:f7:e1:7b:1c:76:53:68:17:3d:
+        af:ec:22:94:29:a0:56:5b:4a:24:b9:cb:a5:0d:09:f2:60:cc:
+        1d:48:94:ee:b5:48:f4:16:1c:6a:8c:c4:82:66:e6:05:63:54:
+        65:e6:71:de:20:f4:28:06:73:ea:a8:8b:d5:8a:a1:d9:07:98:
+        a7:84:00:14:2d:aa:03:92:93:02:49:e5:4c:06:72:1e:cd:df:
+        98:21:f3:a3:fc:eb:86:5d:ea:ec:69:7b:99:a4:cb:d7:9c:e4:
+        da:72:fe:f2:0a:d3:d4:96:a1:20:f5:96:c5:d9:81:52:f4:2a:
+        26:31
+-----BEGIN CERTIFICATE-----
+MIIESjCCA7OgAwIBAgIBAzANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA0MDMw
+NzA5MzE1NVoXDTA1MDMwNzA5MzE1NVowZTELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMRMwEQYDVQQDEwp3ZXJuZXJkRFNBMIIBuDCCASwGByqGSM44BAEw
+ggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2N
+WPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn
+xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUj
+C8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0H
+gmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuz
+pnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7P
+SSoDgYUAAoGBALEN6WUPaOxs8BCvxRxCU8BDDu5mWzOBU5+Hou8FDh84hTN+nUvZ
+uuoh9KJgnUuwKtQfW8ufjdNFRu8HTKG5LYbf8IFvKjY3tcOPTgbnhwYc1qqTENjX
+m1edKwgF9Ywa+9Jk3fTTMg9y5pAD2qUZYFSQvtjXWDsdAnBhKAbdxvNFo4HuMIHr
+MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENl
+cnRpZmljYXRlMB0GA1UdDgQWBBQKDoL0/ldgdcqBT3gnP5J4Uyj/iDCBkAYDVR0j
+BIGIMIGFgBTQwlvQpNTrBf18TA6nHi+gymhPOqFqpGgwZjELMAkGA1UEBhMCREUx
+DzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ0wCwYDVQQKEwRIb21l
+MRUwEwYDVQQLEwxBcGFjaGUgV1NTNEoxDzANBgNVBAMTBldlcm5lcoIBADANBgkq
+hkiG9w0BAQQFAAOBgQB6I5uSC5WC2lz34XscdlNoFz2v7CKUKaBWW0okuculDQny
+YMwdSJTutUj0FhxqjMSCZuYFY1Rl5nHeIPQoBnPqqIvViqHZB5inhAAULaoDkpMC
+SeVMBnIezd+YIfOj/OuGXersaXuZpMvXnOTacv7yCtPUlqEg9ZbF2YFS9ComMQ==
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/06.pem b/trunk/keys/ca.db.certs/06.pem
new file mode 100644
index 0000000..8d3395a
--- /dev/null
+++ b/trunk/keys/ca.db.certs/06.pem
@@ -0,0 +1,64 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 6 (0x6)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Mar 10 16:10:24 2006 GMT
+            Not After : Mar  9 16:10:24 2008 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=werner
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1023 bit)
+                Modulus (1023 bit):
+                    72:0b:f1:36:fc:53:b6:20:5b:0e:1f:cc:2c:c6:3f:
+                    3e:f1:75:cc:25:4e:8f:ef:ec:b9:a0:70:95:ad:9a:
+                    6e:2c:03:1c:33:41:4b:4c:c3:22:5e:8d:96:4c:d9:
+                    cb:29:8b:0d:90:2d:7f:7c:1e:e6:27:dd:b1:cc:cc:
+                    b9:45:c0:99:56:4e:92:46:a1:92:ad:68:0c:7c:04:
+                    fd:50:1a:f0:08:9a:f3:56:4d:4b:55:cc:ac:95:cc:
+                    f2:4c:ce:40:e2:ad:63:fc:79:19:03:8f:cc:17:37:
+                    4f:4f:40:27:b2:84:83:41:3e:c9:7d:8a:17:44:6c:
+                    4c:38:09:63:a2:a0:08:3d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                E4:88:F1:D3:7B:E6:47:03:0F:95:C0:B6:91:1F:7F:15:6D:41:F1:84
+            X509v3 Authority Key Identifier: 
+                keyid:D0:C2:5B:D0:A4:D4:EB:05:FD:7C:4C:0E:A7:1E:2F:A0:CA:68:4F:3A
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:00
+
+    Signature Algorithm: md5WithRSAEncryption
+        54:50:d9:76:0c:0f:40:f5:8d:f7:46:1a:6f:c9:f4:e3:f7:b8:
+        e0:b8:dc:fa:67:36:74:c2:92:84:f9:ba:8c:d2:b5:5b:cd:a9:
+        38:bf:57:2d:42:0f:78:df:9b:56:5b:0c:1f:a0:53:1f:fc:cf:
+        46:e8:04:1b:9c:87:23:23:79:20:ac:6a:af:a3:29:79:4a:ab:
+        46:a5:4f:12:93:97:9b:94:24:4d:e9:8e:78:25:34:6d:24:8b:
+        b7:c1:f0:0e:18:ef:88:51:44:91:30:0b:79:14:36:74:9f:c2:
+        b8:25:70:9e:5d:a9:60:da:7b:85:d9:cc:14:11:25:85:32:52:
+        ad:09
+-----BEGIN CERTIFICATE-----
+MIIDKzCCApSgAwIBAgIBBjANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA2MDMx
+MDE2MTAyNFoXDTA4MDMwOTE2MTAyNFowYTELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMQ8wDQYDVQQDEwZ3ZXJuZXIwgZ4wDQYJKoZIhvcNAQEBBQADgYwA
+MIGIAoGAcgvxNvxTtiBbDh/MLMY/PvF1zCVOj+/suaBwla2abiwDHDNBS0zDIl6N
+lkzZyymLDZAtf3we5ifdsczMuUXAmVZOkkahkq1oDHwE/VAa8Aia81ZNS1XMrJXM
+8kzOQOKtY/x5GQOPzBc3T09AJ7KEg0E+yX2KF0RsTDgJY6KgCD0CAwEAAaOB7jCB
+6zAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
+ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU5Ijx03vmRwMPlcC2kR9/FW1B8YQwgZAGA1Ud
+IwSBiDCBhYAU0MJb0KTU6wX9fEwOpx4voMpoTzqhaqRoMGYxCzAJBgNVBAYTAkRF
+MQ8wDQYDVQQIEwZCYXllcm4xDzANBgNVBAcTBk11bmljaDENMAsGA1UEChMESG9t
+ZTEVMBMGA1UECxMMQXBhY2hlIFdTUzRKMQ8wDQYDVQQDEwZXZXJuZXKCAQAwDQYJ
+KoZIhvcNAQEEBQADgYEAVFDZdgwPQPWN90Yab8n04/e44Ljc+mc2dMKShPm6jNK1
+W82pOL9XLUIPeN+bVlsMH6BTH/zPRugEG5yHIyN5IKxqr6MpeUqrRqVPEpOXm5Qk
+TemOeCU0bSSLt8HwDhjviFFEkTALeRQ2dJ/CuCVwnl2pYNp7hdnMFBElhTJSrQk=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/07.pem b/trunk/keys/ca.db.certs/07.pem
new file mode 100644
index 0000000..a7079af
--- /dev/null
+++ b/trunk/keys/ca.db.certs/07.pem
@@ -0,0 +1,92 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 7 (0x7)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Mar 10 16:10:37 2006 GMT
+            Not After : Mar  9 16:10:37 2008 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=wernerDSA
+        Subject Public Key Info:
+            Public Key Algorithm: dsaEncryption
+            DSA Public Key:
+                pub: 
+                    00:f1:9d:7d:ba:7c:8e:bb:2d:d4:ef:06:e8:9d:8f:
+                    55:d2:54:d5:fd:31:0a:2d:e7:a1:10:b8:cc:a0:3f:
+                    60:5a:07:04:4d:2c:e2:14:81:a6:a7:48:4f:9a:b8:
+                    5a:8c:8a:94:c8:69:4a:e7:7a:80:6a:5a:c5:f9:58:
+                    1e:43:7d:bd:e3:d1:79:4f:b8:00:33:77:31:ed:c1:
+                    aa:3f:a7:8a:5c:a4:dd:1a:98:0e:cc:02:ce:e7:41:
+                    05:f6:5c:fc:7e:e8:06:18:1f:57:ea:16:69:25:99:
+                    71:2d:b1:73:ff:36:f2:ee:bb:4a:0a:80:85:39:84:
+                    f8:8b:eb:d8:f5:ef:ff:9b:fe
+                P:   
+                    00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                    e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                    51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                    c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                    6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                    10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                    c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                    54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                    f2:22:03:19:9d:d1:48:01:c7
+                Q:   
+                    00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                    84:0b:f0:58:1c:f5
+                G:   
+                    00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                    57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                    07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                    81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                    32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                    ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                    f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                    a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                    25:64:01:4c:3b:fe:cf:49:2a
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                7D:D4:B3:14:1D:F8:86:93:29:91:B3:B7:7F:76:DB:06:05:6B:63:44
+            X509v3 Authority Key Identifier: 
+                keyid:D0:C2:5B:D0:A4:D4:EB:05:FD:7C:4C:0E:A7:1E:2F:A0:CA:68:4F:3A
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:00
+
+    Signature Algorithm: md5WithRSAEncryption
+        76:b9:1c:89:97:28:3d:df:81:b8:29:fd:84:9c:e1:ae:19:db:
+        18:53:cc:87:dc:13:90:6c:f9:40:64:a4:23:92:f7:65:06:de:
+        b4:88:b0:c9:35:61:7d:d6:57:3e:de:3d:d5:83:6f:78:78:74:
+        cb:f6:84:0b:24:de:02:97:5e:51:b3:e7:8f:6a:e9:cb:5f:78:
+        f4:41:8d:75:55:a5:05:ae:f2:42:c5:ff:c4:39:06:ae:75:fa:
+        c2:2e:dd:3d:bc:12:c9:5b:a5:f0:18:e4:f4:33:2a:b9:cf:95:
+        38:b8:11:21:10:5a:3b:68:b8:e1:14:35:14:28:28:4b:a5:bb:
+        fd:20
+-----BEGIN CERTIFICATE-----
+MIIESTCCA7KgAwIBAgIBBzANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA2MDMx
+MDE2MTAzN1oXDTA4MDMwOTE2MTAzN1owZDELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMRIwEAYDVQQDEwl3ZXJuZXJEU0EwggG4MIIBLAYHKoZIzjgEATCC
+AR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y
++r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fG
+qKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSML
+zLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeC
+Z1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om
+dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9J
+KgOBhQACgYEA8Z19unyOuy3U7wbonY9V0lTV/TEKLeehELjMoD9gWgcETSziFIGm
+p0hPmrhajIqUyGlK53qAalrF+VgeQ32949F5T7gAM3cx7cGqP6eKXKTdGpgOzALO
+50EF9lz8fugGGB9X6hZpJZlxLbFz/zby7rtKCoCFOYT4i+vY9e//m/6jge4wgesw
+CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFH3UsxQd+IaTKZGzt3922wYFa2NEMIGQBgNVHSME
+gYgwgYWAFNDCW9Ck1OsF/XxMDqceL6DKaE86oWqkaDBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggEAMA0GCSqG
+SIb3DQEBBAUAA4GBAHa5HImXKD3fgbgp/YSc4a4Z2xhTzIfcE5Bs+UBkpCOS92UG
+3rSIsMk1YX3WVz7ePdWDb3h4dMv2hAsk3gKXXlGz549q6ctfePRBjXVVpQWu8kLF
+/8Q5Bq51+sIu3T28EslbpfAY5PQzKrnPlTi4ESEQWjtouOEUNRQoKEulu/0g
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/08.pem b/trunk/keys/ca.db.certs/08.pem
new file mode 100644
index 0000000..9809308
--- /dev/null
+++ b/trunk/keys/ca.db.certs/08.pem
@@ -0,0 +1,65 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 8 (0x8)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Mar 10 17:01:56 2006 GMT
+            Not After : Mar  9 17:01:56 2008 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=werner
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1023 bit)
+                Modulus (1023 bit):
+                    72:0b:f1:36:fc:53:b6:20:5b:0e:1f:cc:2c:c6:3f:
+                    3e:f1:75:cc:25:4e:8f:ef:ec:b9:a0:70:95:ad:9a:
+                    6e:2c:03:1c:33:41:4b:4c:c3:22:5e:8d:96:4c:d9:
+                    cb:29:8b:0d:90:2d:7f:7c:1e:e6:27:dd:b1:cc:cc:
+                    b9:45:c0:99:56:4e:92:46:a1:92:ad:68:0c:7c:04:
+                    fd:50:1a:f0:08:9a:f3:56:4d:4b:55:cc:ac:95:cc:
+                    f2:4c:ce:40:e2:ad:63:fc:79:19:03:8f:cc:17:37:
+                    4f:4f:40:27:b2:84:83:41:3e:c9:7d:8a:17:44:6c:
+                    4c:38:09:63:a2:a0:08:3d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                E4:88:F1:D3:7B:E6:47:03:0F:95:C0:B6:91:1F:7F:15:6D:41:F1:84
+            X509v3 Authority Key Identifier: 
+                keyid:D9:95:2A:4A:3F:76:D0:87:A8:B1:F0:FF:84:B8:C0:7A:11:B9:31:76
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:E6:78:00:61:07:BC:DA:46
+
+    Signature Algorithm: md5WithRSAEncryption
+        26:5b:a1:b6:20:09:b4:c9:11:79:92:f9:d8:91:e1:52:75:18:
+        46:3f:47:87:59:69:e0:e5:da:ea:25:8a:d8:b3:8e:95:8f:f9:
+        43:c0:55:b1:24:cb:1b:1d:31:96:1b:a4:25:14:b6:20:8f:40:
+        a9:e8:f1:a5:2e:41:fc:1c:b8:23:1f:ee:aa:88:39:d0:9f:d0:
+        ce:29:05:f0:24:f0:02:5b:66:26:5f:49:c1:09:89:59:2a:95:
+        0a:86:70:b3:ba:14:2a:3a:9e:15:e7:18:69:b0:1e:e2:04:90:
+        3a:68:b6:f8:77:a8:98:c6:7a:b5:15:ee:87:fd:90:af:71:21:
+        a1:b8
+-----BEGIN CERTIFICATE-----
+MIIDMzCCApygAwIBAgIBCDANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA2MDMx
+MDE3MDE1NloXDTA4MDMwOTE3MDE1NlowYTELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMQ8wDQYDVQQDEwZ3ZXJuZXIwgZ4wDQYJKoZIhvcNAQEBBQADgYwA
+MIGIAoGAcgvxNvxTtiBbDh/MLMY/PvF1zCVOj+/suaBwla2abiwDHDNBS0zDIl6N
+lkzZyymLDZAtf3we5ifdsczMuUXAmVZOkkahkq1oDHwE/VAa8Aia81ZNS1XMrJXM
+8kzOQOKtY/x5GQOPzBc3T09AJ7KEg0E+yX2KF0RsTDgJY6KgCD0CAwEAAaOB9jCB
+8zAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
+ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU5Ijx03vmRwMPlcC2kR9/FW1B8YQwgZgGA1Ud
+IwSBkDCBjYAU2ZUqSj920IeosfD/hLjAehG5MXahaqRoMGYxCzAJBgNVBAYTAkRF
+MQ8wDQYDVQQIEwZCYXllcm4xDzANBgNVBAcTBk11bmljaDENMAsGA1UEChMESG9t
+ZTEVMBMGA1UECxMMQXBhY2hlIFdTUzRKMQ8wDQYDVQQDEwZXZXJuZXKCCQDmeABh
+B7zaRjANBgkqhkiG9w0BAQQFAAOBgQAmW6G2IAm0yRF5kvnYkeFSdRhGP0eHWWng
+5drqJYrYs46Vj/lDwFWxJMsbHTGWG6QlFLYgj0Cp6PGlLkH8HLgjH+6qiDnQn9DO
+KQXwJPACW2YmX0nBCYlZKpUKhnCzuhQqOp4V5xhpsB7iBJA6aLb4d6iYxnq1Fe6H
+/ZCvcSGhuA==
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/09.pem b/trunk/keys/ca.db.certs/09.pem
new file mode 100644
index 0000000..77d847d
--- /dev/null
+++ b/trunk/keys/ca.db.certs/09.pem
@@ -0,0 +1,93 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 9 (0x9)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Mar 10 17:02:07 2006 GMT
+            Not After : Mar  9 17:02:07 2008 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=wernerDSA
+        Subject Public Key Info:
+            Public Key Algorithm: dsaEncryption
+            DSA Public Key:
+                pub: 
+                    00:f1:9d:7d:ba:7c:8e:bb:2d:d4:ef:06:e8:9d:8f:
+                    55:d2:54:d5:fd:31:0a:2d:e7:a1:10:b8:cc:a0:3f:
+                    60:5a:07:04:4d:2c:e2:14:81:a6:a7:48:4f:9a:b8:
+                    5a:8c:8a:94:c8:69:4a:e7:7a:80:6a:5a:c5:f9:58:
+                    1e:43:7d:bd:e3:d1:79:4f:b8:00:33:77:31:ed:c1:
+                    aa:3f:a7:8a:5c:a4:dd:1a:98:0e:cc:02:ce:e7:41:
+                    05:f6:5c:fc:7e:e8:06:18:1f:57:ea:16:69:25:99:
+                    71:2d:b1:73:ff:36:f2:ee:bb:4a:0a:80:85:39:84:
+                    f8:8b:eb:d8:f5:ef:ff:9b:fe
+                P:   
+                    00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                    e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                    51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                    c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                    6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                    10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                    c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                    54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                    f2:22:03:19:9d:d1:48:01:c7
+                Q:   
+                    00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                    84:0b:f0:58:1c:f5
+                G:   
+                    00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                    57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                    07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                    81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                    32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                    ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                    f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                    a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                    25:64:01:4c:3b:fe:cf:49:2a
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                7D:D4:B3:14:1D:F8:86:93:29:91:B3:B7:7F:76:DB:06:05:6B:63:44
+            X509v3 Authority Key Identifier: 
+                keyid:D9:95:2A:4A:3F:76:D0:87:A8:B1:F0:FF:84:B8:C0:7A:11:B9:31:76
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:E6:78:00:61:07:BC:DA:46
+
+    Signature Algorithm: md5WithRSAEncryption
+        23:fa:01:b9:01:68:54:a4:8a:51:26:0b:b5:7c:17:5b:f0:1c:
+        03:05:f8:30:7d:ac:56:1e:46:18:ad:bc:42:cd:52:85:14:43:
+        77:2a:ee:ee:66:cc:05:96:b4:37:af:25:04:1e:b5:f8:bb:34:
+        db:2e:b8:3e:2c:58:00:57:92:b4:91:3b:40:e3:e0:f5:9b:7e:
+        b2:10:28:97:ee:78:34:9f:70:48:22:bb:3f:14:05:a6:34:fb:
+        0c:3e:58:7c:91:7e:48:70:1e:9d:fd:e5:0b:32:6a:96:83:7d:
+        a4:ce:4f:ac:54:a3:fa:8f:cb:f0:3b:a3:29:f2:9e:c3:23:5a:
+        10:ab
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBCTANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA2MDMx
+MDE3MDIwN1oXDTA4MDMwOTE3MDIwN1owZDELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMRIwEAYDVQQDEwl3ZXJuZXJEU0EwggG4MIIBLAYHKoZIzjgEATCC
+AR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y
++r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fG
+qKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSML
+zLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeC
+Z1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om
+dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9J
+KgOBhQACgYEA8Z19unyOuy3U7wbonY9V0lTV/TEKLeehELjMoD9gWgcETSziFIGm
+p0hPmrhajIqUyGlK53qAalrF+VgeQ32949F5T7gAM3cx7cGqP6eKXKTdGpgOzALO
+50EF9lz8fugGGB9X6hZpJZlxLbFz/zby7rtKCoCFOYT4i+vY9e//m/6jgfYwgfMw
+CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFH3UsxQd+IaTKZGzt3922wYFa2NEMIGYBgNVHSME
+gZAwgY2AFNmVKko/dtCHqLHw/4S4wHoRuTF2oWqkaDBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkA5ngAYQe8
+2kYwDQYJKoZIhvcNAQEEBQADgYEAI/oBuQFoVKSKUSYLtXwXW/AcAwX4MH2sVh5G
+GK28Qs1ShRRDdyru7mbMBZa0N68lBB61+Ls02y64PixYAFeStJE7QOPg9Zt+shAo
+l+54NJ9wSCK7PxQFpjT7DD5YfJF+SHAenf3lCzJqloN9pM5PrFSj+o/L8DujKfKe
+wyNaEKs=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/0A.pem b/trunk/keys/ca.db.certs/0A.pem
new file mode 100644
index 0000000..555d2c6
--- /dev/null
+++ b/trunk/keys/ca.db.certs/0A.pem
@@ -0,0 +1,65 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 10 (0xa)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Mar 10 17:04:55 2006 GMT
+            Not After : Mar  9 17:04:55 2008 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=werner
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1023 bit)
+                Modulus (1023 bit):
+                    72:0b:f1:36:fc:53:b6:20:5b:0e:1f:cc:2c:c6:3f:
+                    3e:f1:75:cc:25:4e:8f:ef:ec:b9:a0:70:95:ad:9a:
+                    6e:2c:03:1c:33:41:4b:4c:c3:22:5e:8d:96:4c:d9:
+                    cb:29:8b:0d:90:2d:7f:7c:1e:e6:27:dd:b1:cc:cc:
+                    b9:45:c0:99:56:4e:92:46:a1:92:ad:68:0c:7c:04:
+                    fd:50:1a:f0:08:9a:f3:56:4d:4b:55:cc:ac:95:cc:
+                    f2:4c:ce:40:e2:ad:63:fc:79:19:03:8f:cc:17:37:
+                    4f:4f:40:27:b2:84:83:41:3e:c9:7d:8a:17:44:6c:
+                    4c:38:09:63:a2:a0:08:3d
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                E4:88:F1:D3:7B:E6:47:03:0F:95:C0:B6:91:1F:7F:15:6D:41:F1:84
+            X509v3 Authority Key Identifier: 
+                keyid:D9:95:2A:4A:3F:76:D0:87:A8:B1:F0:FF:84:B8:C0:7A:11:B9:31:76
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:E6:78:00:61:07:BC:DA:46
+
+    Signature Algorithm: md5WithRSAEncryption
+        27:b1:a2:69:2d:50:38:f6:9c:b1:bd:b9:81:a3:c3:60:25:0f:
+        7f:82:b9:63:16:7a:0c:2b:cc:fa:45:78:ff:9b:b9:f0:96:aa:
+        28:d0:c0:98:d5:fe:bd:81:79:1e:2d:96:8e:a3:0a:bb:d8:ca:
+        cf:c4:cb:d6:56:3a:cf:a7:a8:08:26:dd:97:54:29:9e:eb:93:
+        8d:87:9d:3b:5c:22:9f:94:b9:43:de:e1:05:74:67:00:f5:d1:
+        ca:1f:70:26:00:13:63:01:25:6c:ed:61:6e:20:19:76:68:21:
+        ef:0a:f0:42:e2:2c:1c:13:23:82:7c:d4:2e:a9:38:0c:73:07:
+        a8:2c
+-----BEGIN CERTIFICATE-----
+MIIDMzCCApygAwIBAgIBCjANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA2MDMx
+MDE3MDQ1NVoXDTA4MDMwOTE3MDQ1NVowYTELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMQ8wDQYDVQQDEwZ3ZXJuZXIwgZ4wDQYJKoZIhvcNAQEBBQADgYwA
+MIGIAoGAcgvxNvxTtiBbDh/MLMY/PvF1zCVOj+/suaBwla2abiwDHDNBS0zDIl6N
+lkzZyymLDZAtf3we5ifdsczMuUXAmVZOkkahkq1oDHwE/VAa8Aia81ZNS1XMrJXM
+8kzOQOKtY/x5GQOPzBc3T09AJ7KEg0E+yX2KF0RsTDgJY6KgCD0CAwEAAaOB9jCB
+8zAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD
+ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU5Ijx03vmRwMPlcC2kR9/FW1B8YQwgZgGA1Ud
+IwSBkDCBjYAU2ZUqSj920IeosfD/hLjAehG5MXahaqRoMGYxCzAJBgNVBAYTAkRF
+MQ8wDQYDVQQIEwZCYXllcm4xDzANBgNVBAcTBk11bmljaDENMAsGA1UEChMESG9t
+ZTEVMBMGA1UECxMMQXBhY2hlIFdTUzRKMQ8wDQYDVQQDEwZXZXJuZXKCCQDmeABh
+B7zaRjANBgkqhkiG9w0BAQQFAAOBgQAnsaJpLVA49pyxvbmBo8NgJQ9/grljFnoM
+K8z6RXj/m7nwlqoo0MCY1f69gXkeLZaOowq72MrPxMvWVjrPp6gIJt2XVCme65ON
+h507XCKflLlD3uEFdGcA9dHKH3AmABNjASVs7WFuIBl2aCHvCvBC4iwcEyOCfNQu
+qTgMcweoLA==
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/0B.pem b/trunk/keys/ca.db.certs/0B.pem
new file mode 100644
index 0000000..c4fdb92
--- /dev/null
+++ b/trunk/keys/ca.db.certs/0B.pem
@@ -0,0 +1,93 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 11 (0xb)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Mar 10 17:05:01 2006 GMT
+            Not After : Mar  9 17:05:01 2008 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=wernerDSA
+        Subject Public Key Info:
+            Public Key Algorithm: dsaEncryption
+            DSA Public Key:
+                pub: 
+                    00:f1:9d:7d:ba:7c:8e:bb:2d:d4:ef:06:e8:9d:8f:
+                    55:d2:54:d5:fd:31:0a:2d:e7:a1:10:b8:cc:a0:3f:
+                    60:5a:07:04:4d:2c:e2:14:81:a6:a7:48:4f:9a:b8:
+                    5a:8c:8a:94:c8:69:4a:e7:7a:80:6a:5a:c5:f9:58:
+                    1e:43:7d:bd:e3:d1:79:4f:b8:00:33:77:31:ed:c1:
+                    aa:3f:a7:8a:5c:a4:dd:1a:98:0e:cc:02:ce:e7:41:
+                    05:f6:5c:fc:7e:e8:06:18:1f:57:ea:16:69:25:99:
+                    71:2d:b1:73:ff:36:f2:ee:bb:4a:0a:80:85:39:84:
+                    f8:8b:eb:d8:f5:ef:ff:9b:fe
+                P:   
+                    00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                    e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                    51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                    c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                    6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                    10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                    c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                    54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                    f2:22:03:19:9d:d1:48:01:c7
+                Q:   
+                    00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                    84:0b:f0:58:1c:f5
+                G:   
+                    00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                    57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                    07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                    81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                    32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                    ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                    f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                    a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                    25:64:01:4c:3b:fe:cf:49:2a
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                7D:D4:B3:14:1D:F8:86:93:29:91:B3:B7:7F:76:DB:06:05:6B:63:44
+            X509v3 Authority Key Identifier: 
+                keyid:D9:95:2A:4A:3F:76:D0:87:A8:B1:F0:FF:84:B8:C0:7A:11:B9:31:76
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:E6:78:00:61:07:BC:DA:46
+
+    Signature Algorithm: md5WithRSAEncryption
+        a9:ce:af:60:82:7e:95:4f:e8:b8:06:a3:9e:c2:1b:3a:45:f1:
+        d7:27:c5:52:90:fe:35:e5:b0:33:c7:52:f7:4e:a5:2d:9b:76:
+        22:d1:c0:e2:03:40:0c:4c:62:99:28:62:41:58:0d:27:8f:44:
+        3a:71:8f:f9:4b:14:44:90:2e:01:6c:4c:17:e3:2a:ac:f0:58:
+        a2:3d:e8:91:7c:8a:a2:58:2f:26:b4:c3:b7:c3:85:69:66:5a:
+        53:da:e7:16:61:7b:0d:13:d7:ba:5e:32:08:e2:ae:64:63:cc:
+        ea:c7:13:be:bb:47:fd:af:ed:e8:da:a4:bd:60:25:41:8c:44:
+        9b:89
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBCzANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA2MDMx
+MDE3MDUwMVoXDTA4MDMwOTE3MDUwMVowZDELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMRIwEAYDVQQDEwl3ZXJuZXJEU0EwggG4MIIBLAYHKoZIzjgEATCC
+AR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y
++r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fG
+qKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSML
+zLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeC
+Z1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om
+dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9J
+KgOBhQACgYEA8Z19unyOuy3U7wbonY9V0lTV/TEKLeehELjMoD9gWgcETSziFIGm
+p0hPmrhajIqUyGlK53qAalrF+VgeQ32949F5T7gAM3cx7cGqP6eKXKTdGpgOzALO
+50EF9lz8fugGGB9X6hZpJZlxLbFz/zby7rtKCoCFOYT4i+vY9e//m/6jgfYwgfMw
+CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFH3UsxQd+IaTKZGzt3922wYFa2NEMIGYBgNVHSME
+gZAwgY2AFNmVKko/dtCHqLHw/4S4wHoRuTF2oWqkaDBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkA5ngAYQe8
+2kYwDQYJKoZIhvcNAQEEBQADgYEAqc6vYIJ+lU/ouAajnsIbOkXx1yfFUpD+NeWw
+M8dS906lLZt2ItHA4gNADEximShiQVgNJ49EOnGP+UsURJAuAWxMF+MqrPBYoj3o
+kXyKolgvJrTDt8OFaWZaU9rnFmF7DRPXul4yCOKuZGPM6scTvrtH/a/t6NqkvWAl
+QYxEm4k=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/0C.pem b/trunk/keys/ca.db.certs/0C.pem
new file mode 100644
index 0000000..211f7c5
--- /dev/null
+++ b/trunk/keys/ca.db.certs/0C.pem
@@ -0,0 +1,65 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 12 (0xc)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Mar 10 17:07:22 2006 GMT
+            Not After : Mar  9 17:07:22 2008 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=Werner
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:90:a9:4a:94:71:77:ca:03:bd:df:4d:3d:1c:50:
+                    9a:a0:b4:a1:30:3f:34:2d:44:aa:d5:0a:b1:42:46:
+                    5b:c2:d1:3b:b3:66:b6:82:8c:d0:9b:43:b7:8b:06:
+                    7f:66:0e:e7:b2:0e:07:59:c0:b2:9f:77:3b:a6:ed:
+                    39:e0:b4:82:67:aa:de:2a:ba:66:0d:a2:b3:4c:47:
+                    21:ff:33:b2:82:b6:68:83:fa:9d:d1:e0:04:be:6b:
+                    5a:f8:a9:e8:77:76:1f:06:92:26:12:f9:59:1e:65:
+                    45:8c:a5:29:55:72:5b:b4:1a:6e:d2:d8:79:9b:98:
+                    6f:94:88:90:e8:aa:a2:72:7f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                C0:92:B0:AC:F1:AA:27:F4:C7:28:77:A2:0E:41:80:7A:B7:9F:5B:F0
+            X509v3 Authority Key Identifier: 
+                keyid:D9:95:2A:4A:3F:76:D0:87:A8:B1:F0:FF:84:B8:C0:7A:11:B9:31:76
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:E6:78:00:61:07:BC:DA:46
+
+    Signature Algorithm: md5WithRSAEncryption
+        cf:54:02:2d:7c:bf:3c:b2:8c:d3:54:16:9d:57:e0:fa:ef:4f:
+        fe:18:72:18:70:08:5d:8d:84:15:39:fa:02:a6:71:85:95:e7:
+        0d:7c:c2:69:24:f8:35:ba:ee:a1:2e:c2:a7:31:cb:95:71:20:
+        98:31:e4:60:52:94:f6:06:cc:0e:e0:b8:ae:27:a0:18:6e:eb:
+        bc:f1:2d:2d:90:ba:25:f6:86:de:2b:e2:bc:c8:d2:6e:9f:a4:
+        e2:d9:ad:94:49:9d:88:fc:93:b1:2c:72:77:a5:49:7d:3a:6e:
+        62:ba:c4:13:cc:ff:90:ac:0d:8d:85:65:0f:36:56:8f:04:7a:
+        74:b9
+-----BEGIN CERTIFICATE-----
+MIIDNDCCAp2gAwIBAgIBDDANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA2MDMx
+MDE3MDcyMloXDTA4MDMwOTE3MDcyMlowYTELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMQ8wDQYDVQQDEwZXZXJuZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAJCpSpRxd8oDvd9NPRxQmqC0oTA/NC1EqtUKsUJGW8LRO7NmtoKM0JtD
+t4sGf2YO57IOB1nAsp93O6btOeC0gmeq3iq6Zg2is0xHIf8zsoK2aIP6ndHgBL5r
+Wvip6Hd2HwaSJhL5WR5lRYylKVVyW7QabtLYeZuYb5SIkOiqonJ/AgMBAAGjgfYw
+gfMwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQg
+Q2VydGlmaWNhdGUwHQYDVR0OBBYEFMCSsKzxqif0xyh3og5BgHq3n1vwMIGYBgNV
+HSMEgZAwgY2AFNmVKko/dtCHqLHw/4S4wHoRuTF2oWqkaDBmMQswCQYDVQQGEwJE
+RTEPMA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhv
+bWUxFTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkA5ngA
+YQe82kYwDQYJKoZIhvcNAQEEBQADgYEAz1QCLXy/PLKM01QWnVfg+u9P/hhyGHAI
+XY2EFTn6AqZxhZXnDXzCaST4NbruoS7CpzHLlXEgmDHkYFKU9gbMDuC4riegGG7r
+vPEtLZC6JfaG3ivivMjSbp+k4tmtlEmdiPyTsSxyd6VJfTpuYrrEE8z/kKwNjYVl
+DzZWjwR6dLk=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/0D.pem b/trunk/keys/ca.db.certs/0D.pem
new file mode 100644
index 0000000..8ec586d
--- /dev/null
+++ b/trunk/keys/ca.db.certs/0D.pem
@@ -0,0 +1,93 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 13 (0xd)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Mar 10 17:07:29 2006 GMT
+            Not After : Mar  9 17:07:29 2008 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=WernerDSA
+        Subject Public Key Info:
+            Public Key Algorithm: dsaEncryption
+            DSA Public Key:
+                pub: 
+                    00:88:da:f5:b5:f9:81:6d:2d:19:c6:ee:63:bc:15:
+                    e2:08:e3:77:18:4b:20:84:ea:3d:5f:82:a4:65:73:
+                    8b:4a:e3:d6:42:70:7e:5b:da:91:71:db:01:2a:dd:
+                    0c:1b:bb:22:46:31:f9:09:9b:e4:6a:ff:00:f5:dd:
+                    2b:f6:ea:9e:ca:e3:0a:aa:1c:5e:8f:be:6d:ab:57:
+                    60:d0:7f:1d:b4:91:40:d5:44:c4:b9:29:49:a4:18:
+                    fd:31:7a:af:d2:b5:df:9f:c4:20:78:8e:a5:48:b0:
+                    f1:e4:92:67:61:d1:be:76:b2:d7:d9:d9:40:f8:f1:
+                    7e:d2:51:62:3a:02:eb:2c:2d
+                P:   
+                    00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                    e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                    51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                    c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                    6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                    10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                    c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                    54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                    f2:22:03:19:9d:d1:48:01:c7
+                Q:   
+                    00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                    84:0b:f0:58:1c:f5
+                G:   
+                    00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                    57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                    07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                    81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                    32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                    ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                    f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                    a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                    25:64:01:4c:3b:fe:cf:49:2a
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                93:A5:0D:37:7D:E9:1F:88:58:29:D5:8E:21:CE:E1:E4:17:5C:ED:DC
+            X509v3 Authority Key Identifier: 
+                keyid:D9:95:2A:4A:3F:76:D0:87:A8:B1:F0:FF:84:B8:C0:7A:11:B9:31:76
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:E6:78:00:61:07:BC:DA:46
+
+    Signature Algorithm: md5WithRSAEncryption
+        81:07:ab:24:e4:30:da:49:e0:30:8f:63:ca:54:65:af:37:2c:
+        f8:3e:b0:d2:88:60:6d:b9:16:e9:90:e5:db:d6:c2:db:79:0a:
+        2c:1c:fb:d3:cb:f2:a7:fb:60:dc:ee:1c:92:a6:fc:58:da:3c:
+        85:3e:21:05:c7:57:74:20:37:e1:3e:d7:19:de:60:5a:0d:dc:
+        60:aa:14:40:8f:e1:cf:3b:be:97:cb:18:22:19:8f:43:e7:37:
+        0f:68:f8:d9:89:98:b3:8d:b1:76:a3:e7:00:b3:c5:68:38:78:
+        da:d3:b5:63:b2:0b:0a:57:f5:98:0c:de:01:09:5b:8b:ee:12:
+        17:8e
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBDTANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA2MDMx
+MDE3MDcyOVoXDTA4MDMwOTE3MDcyOVowZDELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMRIwEAYDVQQDEwlXZXJuZXJEU0EwggG4MIIBLAYHKoZIzjgEATCC
+AR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y
++r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fG
+qKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSML
+zLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeC
+Z1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om
+dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9J
+KgOBhQACgYEAiNr1tfmBbS0Zxu5jvBXiCON3GEsghOo9X4KkZXOLSuPWQnB+W9qR
+cdsBKt0MG7siRjH5CZvkav8A9d0r9uqeyuMKqhxej75tq1dg0H8dtJFA1UTEuSlJ
+pBj9MXqv0rXfn8QgeI6lSLDx5JJnYdG+drLX2dlA+PF+0lFiOgLrLC2jgfYwgfMw
+CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFJOlDTd96R+IWCnVjiHO4eQXXO3cMIGYBgNVHSME
+gZAwgY2AFNmVKko/dtCHqLHw/4S4wHoRuTF2oWqkaDBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkA5ngAYQe8
+2kYwDQYJKoZIhvcNAQEEBQADgYEAgQerJOQw2kngMI9jylRlrzcs+D6w0ohgbbkW
+6ZDl29bC23kKLBz708vyp/tg3O4ckqb8WNo8hT4hBcdXdCA34T7XGd5gWg3cYKoU
+QI/hzzu+l8sYIhmPQ+c3D2j42YmYs42xdqPnALPFaDh42tO1Y7ILClf1mAzeAQlb
+i+4SF44=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/0E.pem b/trunk/keys/ca.db.certs/0E.pem
new file mode 100644
index 0000000..5f57964
--- /dev/null
+++ b/trunk/keys/ca.db.certs/0E.pem
@@ -0,0 +1,65 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 14 (0xe)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Apr  4 19:20:01 2008 GMT
+            Not After : Apr  4 19:20:01 2010 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=Werner
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:83:0f:ed:d5:f1:69:5f:b1:30:81:13:2b:0c:84:
+                    ff:d4:9c:f3:7b:4e:25:d0:b2:40:6c:d5:38:6f:fb:
+                    24:2f:eb:6e:3a:66:37:a9:d0:24:4e:1c:d5:c9:b4:
+                    09:8b:a3:2d:0f:04:77:8d:9c:6a:56:99:1e:ec:18:
+                    54:01:29:8f:ef:71:bc:18:b2:65:53:33:e8:f5:41:
+                    f8:81:15:04:23:11:95:50:74:fd:0e:7a:71:f4:09:
+                    84:16:53:a7:b1:ca:2e:7d:39:40:91:ee:0f:02:49:
+                    fd:73:b9:71:9e:7b:ad:61:7a:67:62:f7:9d:c1:ed:
+                    e9:e8:af:bc:11:9a:a4:b3:19
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                A2:3D:00:CA:A7:14:92:0E:6F:F6:78:CB:92:51:D0:82:40:CE:E1:EC
+            X509v3 Authority Key Identifier: 
+                keyid:D2:7A:D8:87:17:51:5D:D6:7E:08:E9:B4:62:BF:E0:55:59:80:9E:BF
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:C2:BC:B4:0E:8B:70:1B:B1
+
+    Signature Algorithm: md5WithRSAEncryption
+        04:6f:22:87:5b:3f:ad:f7:04:48:b6:1f:37:fb:56:0c:48:6a:
+        d8:25:ea:7a:72:09:37:bb:83:03:ea:51:9d:e9:99:88:6f:7b:
+        42:95:f7:e7:af:a9:3b:cc:a3:91:a1:49:f8:e1:ad:88:51:cd:
+        64:ce:1b:8b:89:1e:bb:4c:7a:f1:bf:2c:69:41:f2:c1:26:d1:
+        8f:3e:60:4c:fb:84:46:ed:f2:b7:8a:a2:ba:7b:cb:df:2d:23:
+        29:d9:da:05:5c:2a:83:d6:89:c8:7f:92:66:ab:00:ec:f4:d9:
+        56:8d:02:f3:2f:3d:de:a7:ef:0f:ba:8d:45:ff:e4:f1:69:22:
+        24:28
+-----BEGIN CERTIFICATE-----
+MIIDNDCCAp2gAwIBAgIBDjANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA4MDQw
+NDE5MjAwMVoXDTEwMDQwNDE5MjAwMVowYTELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMQ8wDQYDVQQDEwZXZXJuZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAIMP7dXxaV+xMIETKwyE/9Sc83tOJdCyQGzVOG/7JC/rbjpmN6nQJE4c
+1cm0CYujLQ8Ed42calaZHuwYVAEpj+9xvBiyZVMz6PVB+IEVBCMRlVB0/Q56cfQJ
+hBZTp7HKLn05QJHuDwJJ/XO5cZ57rWF6Z2L3ncHt6eivvBGapLMZAgMBAAGjgfYw
+gfMwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQg
+Q2VydGlmaWNhdGUwHQYDVR0OBBYEFKI9AMqnFJIOb/Z4y5JR0IJAzuHsMIGYBgNV
+HSMEgZAwgY2AFNJ62IcXUV3WfgjptGK/4FVZgJ6/oWqkaDBmMQswCQYDVQQGEwJE
+RTEPMA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhv
+bWUxFTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkAwry0
+DotwG7EwDQYJKoZIhvcNAQEEBQADgYEABG8ih1s/rfcESLYfN/tWDEhq2CXqenIJ
+N7uDA+pRnemZiG97QpX356+pO8yjkaFJ+OGtiFHNZM4bi4keu0x68b8saUHywSbR
+jz5gTPuERu3yt4qiunvL3y0jKdnaBVwqg9aJyH+SZqsA7PTZVo0C8y893qfvD7qN
+Rf/k8WkiJCg=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/0F.pem b/trunk/keys/ca.db.certs/0F.pem
new file mode 100644
index 0000000..ae89dad
--- /dev/null
+++ b/trunk/keys/ca.db.certs/0F.pem
@@ -0,0 +1,93 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 15 (0xf)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Apr  4 19:20:17 2008 GMT
+            Not After : Apr  4 19:20:17 2010 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=WernerDSA
+        Subject Public Key Info:
+            Public Key Algorithm: dsaEncryption
+            DSA Public Key:
+                pub: 
+                    00:b8:0e:dd:18:df:90:ea:73:22:24:cf:e8:20:8a:
+                    f8:af:bd:9d:42:f4:84:dc:9e:8b:f1:6f:70:7f:f3:
+                    fb:e1:29:7f:a6:d9:9e:48:97:80:c3:99:79:0b:34:
+                    10:95:46:b1:68:7f:2d:b3:71:57:d2:17:f8:40:9b:
+                    b2:49:6c:26:ad:3d:36:e0:27:46:f5:2d:62:af:c2:
+                    e7:83:19:a6:47:72:a6:0f:ab:8d:3b:72:99:c9:5d:
+                    7d:d8:54:85:c5:0b:38:da:2f:ee:77:c1:21:25:22:
+                    dd:ca:01:32:a8:66:bc:c6:81:d9:cb:d4:09:d8:d1:
+                    ae:b5:f2:c9:c4:4b:9e:b6:8c
+                P:   
+                    00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                    e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                    51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                    c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                    6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                    10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                    c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                    54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                    f2:22:03:19:9d:d1:48:01:c7
+                Q:   
+                    00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                    84:0b:f0:58:1c:f5
+                G:   
+                    00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                    57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                    07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                    81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                    32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                    ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                    f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                    a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                    25:64:01:4c:3b:fe:cf:49:2a
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                6C:31:82:3D:76:DA:97:6D:88:C3:A0:F3:C8:97:A6:17:C9:BC:4B:AC
+            X509v3 Authority Key Identifier: 
+                keyid:D2:7A:D8:87:17:51:5D:D6:7E:08:E9:B4:62:BF:E0:55:59:80:9E:BF
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:C2:BC:B4:0E:8B:70:1B:B1
+
+    Signature Algorithm: md5WithRSAEncryption
+        83:03:c8:50:b2:0e:29:b2:22:18:ac:26:4d:05:4a:0f:68:d8:
+        6b:80:41:45:90:20:a3:1d:03:d5:c2:69:48:15:ac:52:2e:3f:
+        2f:8a:9a:26:ab:00:5e:53:44:a3:ef:fe:c0:66:44:9b:a8:fa:
+        02:79:4c:fe:81:8c:d7:2f:24:4a:78:ee:d3:31:08:8a:d7:2e:
+        19:de:9a:57:27:ea:a6:f3:a6:c6:3c:2f:72:0f:3e:7d:d1:25:
+        2d:19:3f:d4:85:06:45:e6:7b:84:d9:1d:0e:35:58:cc:98:d9:
+        3d:a5:7c:5a:33:7a:a4:9d:d2:29:76:28:1b:15:14:2b:40:be:
+        0d:92
+-----BEGIN CERTIFICATE-----
+MIIEUTCCA7qgAwIBAgIBDzANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA4MDQw
+NDE5MjAxN1oXDTEwMDQwNDE5MjAxN1owZDELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMRIwEAYDVQQDEwlXZXJuZXJEU0EwggG4MIIBLAYHKoZIzjgEATCC
+AR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y
++r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fG
+qKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSML
+zLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeC
+Z1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om
+dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9J
+KgOBhQACgYEAuA7dGN+Q6nMiJM/oIIr4r72dQvSE3J6L8W9wf/P74Sl/ptmeSJeA
+w5l5CzQQlUaxaH8ts3FX0hf4QJuySWwmrT024CdG9S1ir8LngxmmR3KmD6uNO3KZ
+yV192FSFxQs42i/ud8EhJSLdygEyqGa8xoHZy9QJ2NGutfLJxEuetoyjgfYwgfMw
+CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFGwxgj122pdtiMOg88iXphfJvEusMIGYBgNVHSME
+gZAwgY2AFNJ62IcXUV3WfgjptGK/4FVZgJ6/oWqkaDBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkAwry0Dotw
+G7EwDQYJKoZIhvcNAQEEBQADgYEAgwPIULIOKbIiGKwmTQVKD2jYa4BBRZAgox0D
+1cJpSBWsUi4/L4qaJqsAXlNEo+/+wGZEm6j6AnlM/oGM1y8kSnju0zEIitcuGd6a
+VyfqpvOmxjwvcg8+fdElLRk/1IUGReZ7hNkdDjVYzJjZPaV8WjN6pJ3SKXYoGxUU
+K0C+DZI=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/10.pem b/trunk/keys/ca.db.certs/10.pem
new file mode 100644
index 0000000..48034c7
--- /dev/null
+++ b/trunk/keys/ca.db.certs/10.pem
@@ -0,0 +1,65 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 16 (0x10)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Apr  4 19:32:18 2008 GMT
+            Not After : Apr  4 19:32:18 2010 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=Werner
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:83:65:2f:7f:e4:d0:7f:f3:be:49:e9:06:d2:e8:
+                    f2:3c:d7:c3:1f:c8:25:4f:c2:19:2b:fa:32:ca:89:
+                    67:67:f2:67:a9:29:2e:55:c2:b9:20:54:67:fb:5f:
+                    91:dc:69:bb:38:58:ab:f4:9c:ec:0f:1c:b0:89:3d:
+                    80:37:fd:45:46:eb:84:ad:2a:2b:0d:15:3f:a0:e8:
+                    08:82:63:4b:92:1e:37:e3:5e:26:4c:7c:62:39:b3:
+                    2c:f9:99:a8:b6:1b:34:f5:eb:fe:1c:bc:09:1a:d1:
+                    e8:2a:8b:4d:34:a4:07:0a:04:27:e7:03:91:f6:6b:
+                    74:7d:bf:6c:d0:f4:14:42:19
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                54:99:5E:FD:08:E5:B1:BB:5C:F1:30:8F:29:70:1B:79:66:64:67:62
+            X509v3 Authority Key Identifier: 
+                keyid:BF:C5:B0:71:E8:94:62:0C:69:C5:35:4D:95:BF:F3:C0:5D:D8:42:FA
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:B8:12:0E:01:62:75:F6:6C
+
+    Signature Algorithm: md5WithRSAEncryption
+        52:25:21:ff:03:91:55:c4:18:5f:12:21:d7:78:77:c3:60:6d:
+        83:a2:a3:da:0e:95:e9:83:b4:52:d7:3f:80:46:16:c1:3d:f5:
+        d0:2d:8e:ba:ba:0a:03:0c:28:1d:aa:4c:20:85:a2:25:17:25:
+        20:08:80:f0:79:db:d1:2b:ff:a6:eb:87:60:3e:06:e0:d5:85:
+        76:25:63:46:8a:dd:f7:47:99:25:ee:34:34:c1:ab:b9:19:a5:
+        a8:84:48:18:62:82:bf:ec:2f:dc:4e:94:c7:57:16:5b:ce:b6:
+        7f:91:fd:13:2a:dc:a1:c9:1e:d8:ff:b7:18:d0:06:cb:cd:ef:
+        82:10
+-----BEGIN CERTIFICATE-----
+MIIDNDCCAp2gAwIBAgIBEDANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA4MDQw
+NDE5MzIxOFoXDTEwMDQwNDE5MzIxOFowYTELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMQ8wDQYDVQQDEwZXZXJuZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAINlL3/k0H/zvknpBtLo8jzXwx/IJU/CGSv6MsqJZ2fyZ6kpLlXCuSBU
+Z/tfkdxpuzhYq/Sc7A8csIk9gDf9RUbrhK0qKw0VP6DoCIJjS5IeN+NeJkx8Yjmz
+LPmZqLYbNPXr/hy8CRrR6CqLTTSkBwoEJ+cDkfZrdH2/bND0FEIZAgMBAAGjgfYw
+gfMwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQg
+Q2VydGlmaWNhdGUwHQYDVR0OBBYEFFSZXv0I5bG7XPEwjylwG3lmZGdiMIGYBgNV
+HSMEgZAwgY2AFL/FsHHolGIMacU1TZW/88Bd2EL6oWqkaDBmMQswCQYDVQQGEwJE
+RTEPMA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhv
+bWUxFTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkAuBIO
+AWJ19mwwDQYJKoZIhvcNAQEEBQADgYEAUiUh/wORVcQYXxIh13h3w2Btg6Kj2g6V
+6YO0Utc/gEYWwT310C2OuroKAwwoHapMIIWiJRclIAiA8Hnb0Sv/puuHYD4G4NWF
+diVjRord90eZJe40NMGruRmlqIRIGGKCv+wv3E6Ux1cWW862f5H9Eyrcocke2P+3
+GNAGy83vghA=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.certs/11.pem b/trunk/keys/ca.db.certs/11.pem
new file mode 100644
index 0000000..0418d1c
--- /dev/null
+++ b/trunk/keys/ca.db.certs/11.pem
@@ -0,0 +1,93 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 17 (0x11)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Apr  4 19:32:28 2008 GMT
+            Not After : Apr  4 19:32:28 2010 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=WernerDSA
+        Subject Public Key Info:
+            Public Key Algorithm: dsaEncryption
+            DSA Public Key:
+                pub: 
+                    13:ab:7a:33:39:58:6d:23:85:8b:31:cc:36:8c:4d:
+                    a1:1e:72:b7:f7:ba:16:b7:d5:13:3b:3b:00:24:4a:
+                    96:07:1c:c4:0f:b6:cd:c3:fa:48:10:ea:a9:46:94:
+                    a1:50:9e:67:bd:f7:80:8c:09:7d:89:f8:fe:bf:ce:
+                    29:4d:80:62:23:b7:12:23:96:d4:f8:2e:da:94:1f:
+                    ab:6c:d2:11:9a:2a:6a:d6:92:96:57:3c:bc:45:98:
+                    9e:e7:1f:ab:58:fd:5d:d1:2d:c7:eb:4b:e8:9f:19:
+                    70:ea:dd:c8:c6:b4:a4:4f:3e:78:63:a6:50:4c:f9:
+                    7c:52:db:14:2b:dc:87:2a
+                P:   
+                    00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                    e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                    51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                    c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                    6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                    10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                    c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                    54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                    f2:22:03:19:9d:d1:48:01:c7
+                Q:   
+                    00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                    84:0b:f0:58:1c:f5
+                G:   
+                    00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                    57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                    07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                    81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                    32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                    ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                    f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                    a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                    25:64:01:4c:3b:fe:cf:49:2a
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                C3:EB:D7:FD:B4:B3:CA:02:9F:3E:D8:3D:A5:76:3B:36:97:3E:E6:62
+            X509v3 Authority Key Identifier: 
+                keyid:BF:C5:B0:71:E8:94:62:0C:69:C5:35:4D:95:BF:F3:C0:5D:D8:42:FA
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:B8:12:0E:01:62:75:F6:6C
+
+    Signature Algorithm: md5WithRSAEncryption
+        29:53:ca:fe:b0:ea:67:c9:31:2c:fa:13:12:2a:67:ee:35:71:
+        c1:a1:9e:90:45:45:1c:8e:37:84:3b:ce:41:de:b5:d2:4d:da:
+        ef:cb:5f:72:1d:06:e8:2e:c2:4c:2e:72:88:3a:1c:c2:13:93:
+        6f:8f:04:eb:9f:85:72:e1:35:1a:04:9e:27:66:c4:e9:e6:4e:
+        df:eb:8b:24:5e:74:12:f1:34:a1:b0:5d:59:9f:fd:45:c8:f9:
+        26:e9:f3:94:4a:d7:7d:4f:2f:76:92:77:f4:89:bf:21:86:39:
+        6e:74:d7:fa:8d:45:bf:00:38:b5:ab:17:43:e0:94:c7:51:e0:
+        e2:a3
+-----BEGIN CERTIFICATE-----
+MIIEUDCCA7mgAwIBAgIBETANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA4MDQw
+NDE5MzIyOFoXDTEwMDQwNDE5MzIyOFowZDELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMRIwEAYDVQQDEwlXZXJuZXJEU0EwggG3MIIBLAYHKoZIzjgEATCC
+AR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y
++r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fG
+qKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSML
+zLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeC
+Z1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om
+dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9J
+KgOBhAACgYATq3ozOVhtI4WLMcw2jE2hHnK397oWt9UTOzsAJEqWBxzED7bNw/pI
+EOqpRpShUJ5nvfeAjAl9ifj+v84pTYBiI7cSI5bU+C7alB+rbNIRmipq1pKWVzy8
+RZie5x+rWP1d0S3H60vonxlw6t3IxrSkTz54Y6ZQTPl8UtsUK9yHKqOB9jCB8zAJ
+BgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0
+aWZpY2F0ZTAdBgNVHQ4EFgQUw+vX/bSzygKfPtg9pXY7Npc+5mIwgZgGA1UdIwSB
+kDCBjYAUv8WwceiUYgxpxTVNlb/zwF3YQvqhaqRoMGYxCzAJBgNVBAYTAkRFMQ8w
+DQYDVQQIEwZCYXllcm4xDzANBgNVBAcTBk11bmljaDENMAsGA1UEChMESG9tZTEV
+MBMGA1UECxMMQXBhY2hlIFdTUzRKMQ8wDQYDVQQDEwZXZXJuZXKCCQC4Eg4BYnX2
+bDANBgkqhkiG9w0BAQQFAAOBgQApU8r+sOpnyTEs+hMSKmfuNXHBoZ6QRUUcjjeE
+O85B3rXSTdrvy19yHQboLsJMLnKIOhzCE5NvjwTrn4Vy4TUaBJ4nZsTp5k7f64sk
+XnQS8TShsF1Zn/1FyPkm6fOUStd9Ty92knf0ib8hhjludNf6jUW/ADi1qxdD4JTH
+UeDiow==
+-----END CERTIFICATE-----
diff --git a/trunk/keys/ca.db.index b/trunk/keys/ca.db.index
new file mode 100644
index 0000000..5c0fae1
--- /dev/null
+++ b/trunk/keys/ca.db.index
@@ -0,0 +1,17 @@
+E	050228105117Z		01	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=werner
+E	050228120029Z		02	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=wernerd
+E	050307093155Z		03	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=wernerdDSA
+V	060309222536Z		04	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=wernerdDSA
+V	060309223016Z		05	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=wernerd
+V	080309161024Z		06	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=werner
+V	080309161037Z		07	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=wernerDSA
+V	080309170156Z		08	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=werner
+V	080309170207Z		09	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=wernerDSA
+V	080309170455Z		0A	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=werner
+V	080309170501Z		0B	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=wernerDSA
+V	080309170722Z		0C	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=Werner
+V	080309170729Z		0D	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=WernerDSA
+V	100404192001Z		0E	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=Werner
+V	100404192017Z		0F	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=WernerDSA
+V	100404193218Z		10	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=Werner
+V	100404193228Z		11	unknown	/C=DE/ST=Bayern/L=Munich/O=Apache/OU=WSS4J/CN=WernerDSA
diff --git a/trunk/keys/ca.db.index.attr b/trunk/keys/ca.db.index.attr
new file mode 100644
index 0000000..3a7e39e
--- /dev/null
+++ b/trunk/keys/ca.db.index.attr
@@ -0,0 +1 @@
+unique_subject = no
diff --git a/trunk/keys/ca.db.serial b/trunk/keys/ca.db.serial
new file mode 100644
index 0000000..48082f7
--- /dev/null
+++ b/trunk/keys/ca.db.serial
@@ -0,0 +1 @@
+12
diff --git a/trunk/keys/ca.key b/trunk/keys/ca.key
new file mode 100644
index 0000000..9909879
--- /dev/null
+++ b/trunk/keys/ca.key
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6DA21E161F9EF0BF
+
+QlIo6z9lYaqLSYm66f/4PgWsoBxls2uJkAp0IgQfxqftC9cZpkyYOeD//2JYtyWR
+/09V6Nx4tcRF3JPCXx+BoX11oNZr1ze+1Tgt6ZmIETrKrW4oS69W43q0JiKcHYcP
+3gTZASnBU+KkPEVcyN+XNP/6UURP0Y5P+IgQj8FEi0LSh3RVGXLwsVmeXo0vkGvH
++U+GrGW4h25udkqt62O2gi34XdBBuIMUaLl9wMJ+M/oTzP91v213JGMoVLd3N7Cf
+S24rPb/pabcz+wIPKW2RU8Fgssun4pIRIjOujbzONo7OgoeIXM+n4zNyFa34E5ub
+iLKYOiS8pFkWLKXPxSRTAweWKfyoWNYaGbsSxrJHMLiRplHlHveJdbBJ5Y1h7OEs
+9+UqxZNXX1lMyzueC5TewoSUEkiFw+5Fmrw9N3m5v5oZOdFD/dWeysHimUPQS+zg
+sn7mnY/M3VbPCMWbK4RLs3/ABZxFhmMDZWXRFXSXk+jXqt2mWBKJPALBTbNHFDsm
+05fX0HD+IjRtODSjluK9dpnegS8EdJT5yG2J/Jhr2MzSPe2PlyvnrMXZ+MDWz5XJ
+TWLsn5c3A6FsvIFbCRb/QxfZldT6d/33A6vxSpYHOfti4de7Yw32TlRmYr8F3DLA
+BCHiVcCKzMRiJAbYRsCyKWWttdKV9fixNDhzvDNboMJf/duum8op4ALKaZsaBvq6
+BfY6kmckqStZDJs/ytlnjDnAPBBpJML+vBIbo24n1d3X1mvIVwCADqMspfqr3Ukg
+hACyMhPB+fNx+mUqgW+Sf77ffD62ktyoR5StxsbwJuZqqqghOjAvTg==
+-----END RSA PRIVATE KEY-----
diff --git a/trunk/keys/cert.crt b/trunk/keys/cert.crt
new file mode 100644
index 0000000..bb9b089
--- /dev/null
+++ b/trunk/keys/cert.crt
Binary files differ
diff --git a/trunk/keys/cert.pem b/trunk/keys/cert.pem
new file mode 100644
index 0000000..48034c7
--- /dev/null
+++ b/trunk/keys/cert.pem
@@ -0,0 +1,65 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 16 (0x10)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Apr  4 19:32:18 2008 GMT
+            Not After : Apr  4 19:32:18 2010 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=Werner
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (1024 bit)
+                Modulus (1024 bit):
+                    00:83:65:2f:7f:e4:d0:7f:f3:be:49:e9:06:d2:e8:
+                    f2:3c:d7:c3:1f:c8:25:4f:c2:19:2b:fa:32:ca:89:
+                    67:67:f2:67:a9:29:2e:55:c2:b9:20:54:67:fb:5f:
+                    91:dc:69:bb:38:58:ab:f4:9c:ec:0f:1c:b0:89:3d:
+                    80:37:fd:45:46:eb:84:ad:2a:2b:0d:15:3f:a0:e8:
+                    08:82:63:4b:92:1e:37:e3:5e:26:4c:7c:62:39:b3:
+                    2c:f9:99:a8:b6:1b:34:f5:eb:fe:1c:bc:09:1a:d1:
+                    e8:2a:8b:4d:34:a4:07:0a:04:27:e7:03:91:f6:6b:
+                    74:7d:bf:6c:d0:f4:14:42:19
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                54:99:5E:FD:08:E5:B1:BB:5C:F1:30:8F:29:70:1B:79:66:64:67:62
+            X509v3 Authority Key Identifier: 
+                keyid:BF:C5:B0:71:E8:94:62:0C:69:C5:35:4D:95:BF:F3:C0:5D:D8:42:FA
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:B8:12:0E:01:62:75:F6:6C
+
+    Signature Algorithm: md5WithRSAEncryption
+        52:25:21:ff:03:91:55:c4:18:5f:12:21:d7:78:77:c3:60:6d:
+        83:a2:a3:da:0e:95:e9:83:b4:52:d7:3f:80:46:16:c1:3d:f5:
+        d0:2d:8e:ba:ba:0a:03:0c:28:1d:aa:4c:20:85:a2:25:17:25:
+        20:08:80:f0:79:db:d1:2b:ff:a6:eb:87:60:3e:06:e0:d5:85:
+        76:25:63:46:8a:dd:f7:47:99:25:ee:34:34:c1:ab:b9:19:a5:
+        a8:84:48:18:62:82:bf:ec:2f:dc:4e:94:c7:57:16:5b:ce:b6:
+        7f:91:fd:13:2a:dc:a1:c9:1e:d8:ff:b7:18:d0:06:cb:cd:ef:
+        82:10
+-----BEGIN CERTIFICATE-----
+MIIDNDCCAp2gAwIBAgIBEDANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA4MDQw
+NDE5MzIxOFoXDTEwMDQwNDE5MzIxOFowYTELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMQ8wDQYDVQQDEwZXZXJuZXIwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBAINlL3/k0H/zvknpBtLo8jzXwx/IJU/CGSv6MsqJZ2fyZ6kpLlXCuSBU
+Z/tfkdxpuzhYq/Sc7A8csIk9gDf9RUbrhK0qKw0VP6DoCIJjS5IeN+NeJkx8Yjmz
+LPmZqLYbNPXr/hy8CRrR6CqLTTSkBwoEJ+cDkfZrdH2/bND0FEIZAgMBAAGjgfYw
+gfMwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQg
+Q2VydGlmaWNhdGUwHQYDVR0OBBYEFFSZXv0I5bG7XPEwjylwG3lmZGdiMIGYBgNV
+HSMEgZAwgY2AFL/FsHHolGIMacU1TZW/88Bd2EL6oWqkaDBmMQswCQYDVQQGEwJE
+RTEPMA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhv
+bWUxFTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyggkAuBIO
+AWJ19mwwDQYJKoZIhvcNAQEEBQADgYEAUiUh/wORVcQYXxIh13h3w2Btg6Kj2g6V
+6YO0Utc/gEYWwT310C2OuroKAwwoHapMIIWiJRclIAiA8Hnb0Sv/puuHYD4G4NWF
+diVjRord90eZJe40NMGruRmlqIRIGGKCv+wv3E6Ux1cWW862f5H9Eyrcocke2P+3
+GNAGy83vghA=
+-----END CERTIFICATE-----
diff --git a/trunk/keys/cert.req b/trunk/keys/cert.req
new file mode 100644
index 0000000..18a9db1
--- /dev/null
+++ b/trunk/keys/cert.req
@@ -0,0 +1,10 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIIBoTCCAQoCAQAwYTELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVu
+aWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNVBAsTBVdTUzRKMQ8wDQYDVQQDEwZXZXJuZXIwgZ8w
+DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAINlL3/k0H/zvknpBtLo8jzXwx/IJU/CGSv6MsqJZ2fy
+Z6kpLlXCuSBUZ/tfkdxpuzhYq/Sc7A8csIk9gDf9RUbrhK0qKw0VP6DoCIJjS5IeN+NeJkx8Yjmz
+LPmZqLYbNPXr/hy8CRrR6CqLTTSkBwoEJ+cDkfZrdH2/bND0FEIZAgMBAAGgADANBgkqhkiG9w0B
+AQQFAAOBgQAcUGekc0IcK+SRB/9UPWZobKBFE9GtgCg7Q8GWTeKTzEgjGx8JHRtGuRmg1E8bRqUu
+5UncpH6tOyQJppYSsCoZG5wsR0cVXKuK6jdtlzITfbUNhwved/mXVIOI9Prsv3rWjCYXLsCm94pz
+NfUhXd2CIWFfEHTmYtqNOuKeirVErA==
+-----END NEW CERTIFICATE REQUEST-----
diff --git a/trunk/keys/certDSA.crt b/trunk/keys/certDSA.crt
new file mode 100644
index 0000000..9b9d3a7
--- /dev/null
+++ b/trunk/keys/certDSA.crt
Binary files differ
diff --git a/trunk/keys/certDSA.pem b/trunk/keys/certDSA.pem
new file mode 100644
index 0000000..0418d1c
--- /dev/null
+++ b/trunk/keys/certDSA.pem
@@ -0,0 +1,93 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 17 (0x11)
+        Signature Algorithm: md5WithRSAEncryption
+        Issuer: C=DE, ST=Bayern, L=Munich, O=Home, OU=Apache WSS4J, CN=Werner
+        Validity
+            Not Before: Apr  4 19:32:28 2008 GMT
+            Not After : Apr  4 19:32:28 2010 GMT
+        Subject: C=DE, ST=Bayern, L=Munich, O=Apache, OU=WSS4J, CN=WernerDSA
+        Subject Public Key Info:
+            Public Key Algorithm: dsaEncryption
+            DSA Public Key:
+                pub: 
+                    13:ab:7a:33:39:58:6d:23:85:8b:31:cc:36:8c:4d:
+                    a1:1e:72:b7:f7:ba:16:b7:d5:13:3b:3b:00:24:4a:
+                    96:07:1c:c4:0f:b6:cd:c3:fa:48:10:ea:a9:46:94:
+                    a1:50:9e:67:bd:f7:80:8c:09:7d:89:f8:fe:bf:ce:
+                    29:4d:80:62:23:b7:12:23:96:d4:f8:2e:da:94:1f:
+                    ab:6c:d2:11:9a:2a:6a:d6:92:96:57:3c:bc:45:98:
+                    9e:e7:1f:ab:58:fd:5d:d1:2d:c7:eb:4b:e8:9f:19:
+                    70:ea:dd:c8:c6:b4:a4:4f:3e:78:63:a6:50:4c:f9:
+                    7c:52:db:14:2b:dc:87:2a
+                P:   
+                    00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                    e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                    51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                    c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                    6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                    10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                    c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                    54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                    f2:22:03:19:9d:d1:48:01:c7
+                Q:   
+                    00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                    84:0b:f0:58:1c:f5
+                G:   
+                    00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                    57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                    07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                    81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                    32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                    ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                    f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                    a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                    25:64:01:4c:3b:fe:cf:49:2a
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                C3:EB:D7:FD:B4:B3:CA:02:9F:3E:D8:3D:A5:76:3B:36:97:3E:E6:62
+            X509v3 Authority Key Identifier: 
+                keyid:BF:C5:B0:71:E8:94:62:0C:69:C5:35:4D:95:BF:F3:C0:5D:D8:42:FA
+                DirName:/C=DE/ST=Bayern/L=Munich/O=Home/OU=Apache WSS4J/CN=Werner
+                serial:B8:12:0E:01:62:75:F6:6C
+
+    Signature Algorithm: md5WithRSAEncryption
+        29:53:ca:fe:b0:ea:67:c9:31:2c:fa:13:12:2a:67:ee:35:71:
+        c1:a1:9e:90:45:45:1c:8e:37:84:3b:ce:41:de:b5:d2:4d:da:
+        ef:cb:5f:72:1d:06:e8:2e:c2:4c:2e:72:88:3a:1c:c2:13:93:
+        6f:8f:04:eb:9f:85:72:e1:35:1a:04:9e:27:66:c4:e9:e6:4e:
+        df:eb:8b:24:5e:74:12:f1:34:a1:b0:5d:59:9f:fd:45:c8:f9:
+        26:e9:f3:94:4a:d7:7d:4f:2f:76:92:77:f4:89:bf:21:86:39:
+        6e:74:d7:fa:8d:45:bf:00:38:b5:ab:17:43:e0:94:c7:51:e0:
+        e2:a3
+-----BEGIN CERTIFICATE-----
+MIIEUDCCA7mgAwIBAgIBETANBgkqhkiG9w0BAQQFADBmMQswCQYDVQQGEwJERTEP
+MA0GA1UECBMGQmF5ZXJuMQ8wDQYDVQQHEwZNdW5pY2gxDTALBgNVBAoTBEhvbWUx
+FTATBgNVBAsTDEFwYWNoZSBXU1M0SjEPMA0GA1UEAxMGV2VybmVyMB4XDTA4MDQw
+NDE5MzIyOFoXDTEwMDQwNDE5MzIyOFowZDELMAkGA1UEBhMCREUxDzANBgNVBAgT
+BkJheWVybjEPMA0GA1UEBxMGTXVuaWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNV
+BAsTBVdTUzRKMRIwEAYDVQQDEwlXZXJuZXJEU0EwggG3MIIBLAYHKoZIzjgEATCC
+AR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlFXUAiUftZPY1Y
++r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fG
+qKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSML
+zLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeC
+Z1FZV4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7Om
+dZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9J
+KgOBhAACgYATq3ozOVhtI4WLMcw2jE2hHnK397oWt9UTOzsAJEqWBxzED7bNw/pI
+EOqpRpShUJ5nvfeAjAl9ifj+v84pTYBiI7cSI5bU+C7alB+rbNIRmipq1pKWVzy8
+RZie5x+rWP1d0S3H60vonxlw6t3IxrSkTz54Y6ZQTPl8UtsUK9yHKqOB9jCB8zAJ
+BgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0
+aWZpY2F0ZTAdBgNVHQ4EFgQUw+vX/bSzygKfPtg9pXY7Npc+5mIwgZgGA1UdIwSB
+kDCBjYAUv8WwceiUYgxpxTVNlb/zwF3YQvqhaqRoMGYxCzAJBgNVBAYTAkRFMQ8w
+DQYDVQQIEwZCYXllcm4xDzANBgNVBAcTBk11bmljaDENMAsGA1UEChMESG9tZTEV
+MBMGA1UECxMMQXBhY2hlIFdTUzRKMQ8wDQYDVQQDEwZXZXJuZXKCCQC4Eg4BYnX2
+bDANBgkqhkiG9w0BAQQFAAOBgQApU8r+sOpnyTEs+hMSKmfuNXHBoZ6QRUUcjjeE
+O85B3rXSTdrvy19yHQboLsJMLnKIOhzCE5NvjwTrn4Vy4TUaBJ4nZsTp5k7f64sk
+XnQS8TShsF1Zn/1FyPkm6fOUStd9Ty92knf0ib8hhjludNf6jUW/ADi1qxdD4JTH
+UeDiow==
+-----END CERTIFICATE-----
diff --git a/trunk/keys/certDSA.req b/trunk/keys/certDSA.req
new file mode 100644
index 0000000..ca0f9f8
--- /dev/null
+++ b/trunk/keys/certDSA.req
@@ -0,0 +1,13 @@
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIICaDCCAiYCAQAwZDELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGTXVu
+aWNoMQ8wDQYDVQQKEwZBcGFjaGUxDjAMBgNVBAsTBVdTUzRKMRIwEAYDVQQDEwlXZXJuZXJEU0Ew
+ggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZRJmlF
+XUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fG
+qKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL
+8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkW
+cSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQiaiD
+3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAACgYATq3ozOVhtI4WLMcw2jE2hHnK397oWt9UTOzsA
+JEqWBxzED7bNw/pIEOqpRpShUJ5nvfeAjAl9ifj+v84pTYBiI7cSI5bU+C7alB+rbNIRmipq1pKW
+Vzy8RZie5x+rWP1d0S3H60vonxlw6t3IxrSkTz54Y6ZQTPl8UtsUK9yHKqAAMAsGByqGSM44BAMF
+AAMvADAsAhQPRzLS5+6NSxFgg6L/FgMiYH/LrAIUTgYEAJFsUguKvJqtsno2MMhSSrY=
+-----END NEW CERTIFICATE REQUEST-----
diff --git a/trunk/keys/genCAKey.sh b/trunk/keys/genCAKey.sh
new file mode 100644
index 0000000..d59986f
--- /dev/null
+++ b/trunk/keys/genCAKey.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+openssl req -x509 -newkey rsa:1024 -keyout CAKey.pem -out CA.pem -config ca.config
+
diff --git a/trunk/keys/genCertRequest.sh b/trunk/keys/genCertRequest.sh
new file mode 100644
index 0000000..243788a
--- /dev/null
+++ b/trunk/keys/genCertRequest.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+# Export the key as a request (use security as the password)
+"$JAVA_HOME/bin/keytool" -keystore wss4j.keystore -alias wss4jCert -certreq -file cert.req
+"$JAVA_HOME/bin/keytool" -keystore wss4j.keystore -alias wss4jCertDSA -certreq -file certDSA.req
diff --git a/trunk/keys/genKeystore.sh b/trunk/keys/genKeystore.sh
new file mode 100644
index 0000000..bfb679c
--- /dev/null
+++ b/trunk/keys/genKeystore.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+#
+# Clean out the server and client keystores
+rm wss4j.keystore
+
+# Generate the key that will be used for wss4j
+# (use security as the password)
+"$JAVA_HOME/bin/keytool" -genkey -alias wss4jCert -keyalg RSA -keystore wss4j.keystore -dname "CN=Werner,OU=WSS4J,O=Apache,L=Munich,ST=Bayern,C=DE"
+"$JAVA_HOME/bin/keytool" -genkey -alias wss4jCertDSA -keystore wss4j.keystore -dname "CN=WernerDSA,OU=WSS4J,O=Apache,L=Munich,ST=Bayern,C=DE"
+
diff --git a/trunk/keys/k.bat b/trunk/keys/k.bat
new file mode 100644
index 0000000..c951c5d
--- /dev/null
+++ b/trunk/keys/k.bat
@@ -0,0 +1 @@
+keytool -genkey -keyalg rsa -keysize 2048 -validity 730 -alias dims -keystore .keystore
\ No newline at end of file
diff --git a/trunk/keys/key.bat b/trunk/keys/key.bat
new file mode 100644
index 0000000..3685550
--- /dev/null
+++ b/trunk/keys/key.bat
@@ -0,0 +1,5 @@
+SET PATH=C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin;%PATH%
+DEL /F selfcert.*
+makecert -sky exchange -r -n "CN=Davanum Srinivas" -b 01/01/2000 -e 01/01/2099 -sv selfcert.pvk selfcert.cer
+cert2spc selfcert.cer selfcert.spc
+pvkimprt -PFX selfcert.spc selfcert.pvk
\ No newline at end of file
diff --git a/trunk/keys/keystore.p12 b/trunk/keys/keystore.p12
new file mode 100644
index 0000000..7aad86f
--- /dev/null
+++ b/trunk/keys/keystore.p12
Binary files differ
diff --git a/trunk/keys/selfcert.pfx b/trunk/keys/selfcert.pfx
new file mode 100644
index 0000000..8b7d5ce
--- /dev/null
+++ b/trunk/keys/selfcert.pfx
Binary files differ
diff --git a/trunk/keys/signConvertImportCert.sh b/trunk/keys/signConvertImportCert.sh
new file mode 100644
index 0000000..0e38300
--- /dev/null
+++ b/trunk/keys/signConvertImportCert.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+# Sign the server certificate request with the CA using the command 
+# (again, "security" is the PEM pass phrase):
+openssl ca -config ca.config -policy policy_anything -days 730 -out cert.pem -infiles cert.req
+openssl ca -config ca.config -policy policy_anything -days 730 -out certDSA.pem -infiles certDSA.req
+
+# Convert the server certificate from PEM (plain text format) to DER (binary) format:
+# openssl x509 -outform DER -in CA.pem -out CA.crt
+openssl x509 -outform DER -in cert.pem -out cert.crt
+openssl x509 -outform DER -in certDSA.pem -out certDSA.crt
+
+# import the CA and server certificate into wss4j's keystore (note that 
+# importing the server certificate results in the keystore's wss4j 
+# certificate being updated with the new signature):
+# "$JAVA_HOME/bin/keytool" -import -file ca.crt -keystore wss4j.keystore
+"$JAVA_HOME/bin/keytool" -import -alias wss4jCert -file cert.crt -keystore wss4j.keystore
+"$JAVA_HOME/bin/keytool" -import -alias wss4jCertDSA -file certDSA.crt -keystore wss4j.keystore
+
diff --git a/trunk/keys/wss4j.keystore b/trunk/keys/wss4j.keystore
new file mode 100644
index 0000000..5b6497a
--- /dev/null
+++ b/trunk/keys/wss4j.keystore
Binary files differ
diff --git a/trunk/keys/x509.PFX.MSFT b/trunk/keys/x509.PFX.MSFT
new file mode 100644
index 0000000..98be0df
--- /dev/null
+++ b/trunk/keys/x509.PFX.MSFT
Binary files differ
diff --git a/trunk/keys/x509.keystore.SUN b/trunk/keys/x509.keystore.SUN
new file mode 100644
index 0000000..318ca8b
--- /dev/null
+++ b/trunk/keys/x509.keystore.SUN
Binary files differ
diff --git a/trunk/keys/x509.txt.BC b/trunk/keys/x509.txt.BC
new file mode 100644
index 0000000..91de954
--- /dev/null
+++ b/trunk/keys/x509.txt.BC
@@ -0,0 +1,38 @@
+-----BEGIN CERTIFICATE-----
+MIIDxDCCAy2gAwIBAgIBADANBgkqhkiG9w0BAQUFADCBozELMAkGA1UEBhMCVVMx
+FjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxDzANBgNVBAcTBlNoYXJvbjEcMBoGA1UE
+ChMTQ29tcHV0ZXIgQXNzb2NpYXRlczEPMA0GA1UECxMGY2EuY29tMRowGAYDVQQD
+FBFwb3N0bWFzdGVyQGNhLmNvbTEgMB4GCSqGSIb3DQEJARYRcG9zdG1hc3RlckBj
+YS5jb20wHhcNMDMwNTA1MjMxNTQzWhcNMDQwNTA0MjMxNTQzWjCBozELMAkGA1UE
+BhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxDzANBgNVBAcTBlNoYXJvbjEc
+MBoGA1UEChMTQ29tcHV0ZXIgQXNzb2NpYXRlczEPMA0GA1UECxMGY2EuY29tMRow
+GAYDVQQDFBFwb3N0bWFzdGVyQGNhLmNvbTEgMB4GCSqGSIb3DQEJARYRcG9zdG1h
+c3RlckBjYS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKkewCBrpOAI
+a0ZZD4SJgTGcqQHoadt8G0WvgVxQhio5A1vSHlsA9JJP6DlsGDBw3IInNWwRI6mv
+uZ++dfB2+q8Uo8CuHaqd23jMH3LQl4VRdWF6PG4KO1FvYlMkOsBJb1CXoNzbBX33
+d2/C6aTW7Tlrg+sFfGL5CQ6smTVIC0QtAgMBAAGjggEEMIIBADAdBgNVHQ4EFgQU
+zsX+6j5MER9d6WIRNmi7s0KbfGcwgdAGA1UdIwSByDCBxYAUzsX+6j5MER9d6WIR
+Nmi7s0KbfGehgamkgaYwgaMxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNo
+dXNldHRzMQ8wDQYDVQQHEwZTaGFyb24xHDAaBgNVBAoTE0NvbXB1dGVyIEFzc29j
+aWF0ZXMxDzANBgNVBAsTBmNhLmNvbTEaMBgGA1UEAxQRcG9zdG1hc3RlckBjYS5j
+b20xIDAeBgkqhkiG9w0BCQEWEXBvc3RtYXN0ZXJAY2EuY29tggEAMAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAAKSjYoFyNclkuVMUk17QAUOijXEDwXOL
+xGVVXzRs8fPnskSYOTfZ1j03Kjlf9UIXY20QD74aNfeYOZxLk72NXnXeyjkzJFWD
+Qxrvzlhu093ZC83TAAIwLM0ZRj3ru+BmGpz5JheODWMhOHlUQhi7c/RKflIaXBjY
+JPRT6IUCi7w=
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQCpHsAga6TgCGtGWQ+EiYExnKkB6GnbfBtFr4FcUIYqOQNb0h5b
+APSST+g5bBgwcNyCJzVsESOpr7mfvnXwdvqvFKPArh2qndt4zB9y0JeFUXVhejxu
+CjtRb2JTJDrASW9Ql6Dc2wV993dvwumk1u05a4PrBXxi+QkOrJk1SAtELQIDAQAB
+AoGAU53rmlv+mfIvsAmKvZoK8Y+mlFXoOOfkyBCdYhpCK5Ai0/xQm+geBFVT2UhT
+sWer7wIZzMOwoU5L9eqCf5EkIiw9aGzlu4N3HJcJhTtNOTFe6G2PMBP0SdPuYEpd
+w7bOWkbMNtAqYTRoNyrXGdJjPpVccFhotunxDRsaYouOEPUCQQDgDiWKt4mvyhSG
+1OUPJ2pSvkuIG4cCOBmu89JEfy/z02T+uoRj45EpTl5QrUgQzpay0xMhzISgVjq8
+d76yP4QXAkEAwTuC5anE/YAl/WVRihVZNO15cOky6h06W2wPdtpiDoEGvgErvNRI
+qoii0KcPtWLJHPS2AV5jWqqCHoK8q8UwWwJAIjRmrM+qOGj8Sz0zHuYgiDM+6q9x
+I/iWiyvz3LsiAfIyx+SHk4xJO+oX4e8iQlaXkQNCN3W2hZfEbcNGHIYvzwJBAKw/
+lGuNbmBbP4ImMw1YAnE/zyVre0teSor8RLy55vbu5UeyW36z7SK3Mgu1IDecm5II
+QcXukbpcjCkOeYjU+kkCQQDa966ynJGTkdg+ObsoPilztiwqDEZRwEAfkmXt4Edq
+2C7EEyQptJYhG9UFJqVggsP9Yq5MLcynKkKF0YGWDVXM
+-----END RSA PRIVATE KEY-----
diff --git a/trunk/keys/x509v1.keystore b/trunk/keys/x509v1.keystore
new file mode 100644
index 0000000..9d82933
--- /dev/null
+++ b/trunk/keys/x509v1.keystore
Binary files differ
diff --git a/trunk/legal/LICENSE.axis b/trunk/legal/LICENSE.axis
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/trunk/legal/LICENSE.axis
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
diff --git a/trunk/legal/LICENSE.bouncycastle b/trunk/legal/LICENSE.bouncycastle
new file mode 100644
index 0000000..cbef4fc
--- /dev/null
+++ b/trunk/legal/LICENSE.bouncycastle
@@ -0,0 +1,7 @@
+Copyright (c) 2000 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
diff --git a/trunk/legal/LICENSE.commons-codec b/trunk/legal/LICENSE.commons-codec
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/trunk/legal/LICENSE.commons-codec
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
diff --git a/trunk/legal/LICENSE.commons-discovery b/trunk/legal/LICENSE.commons-discovery
new file mode 100644
index 0000000..2fd9d81
--- /dev/null
+++ b/trunk/legal/LICENSE.commons-discovery
@@ -0,0 +1,54 @@
+/*

+ * The Apache Software License, Version 1.1

+ *

+ * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights

+ * reserved.

+ *

+ * Redistribution and use in source and binary forms, with or without

+ * modification, are permitted provided that the following conditions

+ * are met:

+ *

+ * 1. Redistributions of source code must retain the above copyright

+ *    notice, this list of conditions and the following disclaimer.

+ *

+ * 2. Redistributions in binary form must reproduce the above copyright

+ *    notice, this list of conditions and the following disclaimer in

+ *    the documentation and/or other materials provided with the

+ *    distribution.

+ *

+ * 3. The end-user documentation included with the redistribution, if

+ *    any, must include the following acknowlegement:

+ *       "This product includes software developed by the

+ *        Apache Software Foundation (http://www.apache.org/)."

+ *    Alternately, this acknowlegement may appear in the software itself,

+ *    if and wherever such third-party acknowlegements normally appear.

+ *

+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software

+ *    Foundation" must not be used to endorse or promote products derived

+ *    from this software without prior written permission. For written

+ *    permission, please contact apache@apache.org.

+ *

+ * 5. Products derived from this software may not be called "Apache"

+ *    nor may "Apache" appear in their names without prior written

+ *    permission of the Apache Group.

+ *

+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED

+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES

+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR

+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF

+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,

+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT

+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

+ * SUCH DAMAGE.

+ * ====================================================================

+ *

+ * This software consists of voluntary contributions made by many

+ * individuals on behalf of the Apache Software Foundation.  For more

+ * information on the Apache Software Foundation, please see

+ * <http://www.apache.org/>.

+ *

+ */

diff --git a/trunk/legal/LICENSE.commons-logging b/trunk/legal/LICENSE.commons-logging
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/trunk/legal/LICENSE.commons-logging
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
diff --git a/trunk/legal/LICENSE.jaf b/trunk/legal/LICENSE.jaf
new file mode 100644
index 0000000..bb4fb49
--- /dev/null
+++ b/trunk/legal/LICENSE.jaf
@@ -0,0 +1,173 @@
+                           Sun Microsystems, Inc.
+                        Binary Code License Agreement
+
+READ THE TERMS OF THIS AGREEMENT AND ANY PROVIDED SUPPLEMENTAL LICENSE TERMS
+(COLLECTIVELY "AGREEMENT") CAREFULLY BEFORE OPENING THE SOFTWARE MEDIA
+PACKAGE.  BY OPENING THE SOFTWARE MEDIA PACKAGE, YOU AGREE TO THE TERMS OF
+THIS AGREEMENT.  IF YOU ARE ACCESSING THE SOFTWARE ELECTRONICALLY, INDICATE
+YOUR ACCEPTANCE OF THESE TERMS BY SELECTING THE "ACCEPT" BUTTON AT THE END
+OF THIS AGREEMENT.  IF YOU DO NOT AGREE TO ALL THESE TERMS, PROMPTLY RETURN
+THE UNUSED SOFTWARE TO YOUR PLACE OF PURCHASE FOR A REFUND OR, IF THE
+SOFTWARE IS ACCESSED ELECTRONICALLY, SELECT THE "DECLINE" BUTTON AT THE END
+OF THIS AGREEMENT.
+
+1.  LICENSE TO USE.  Sun grants you a non-exclusive and non-transferable
+license for the internal use only of the accompanying software and
+documentation and any error corrections provided by Sun (collectively
+"Software"), by the number of users and the class of computer hardware for
+which the corresponding fee has been paid.
+
+2.  RESTRICTIONS.  Software is confidential and copyrighted. Title to
+Software and all associated intellectual property rights is retained by Sun
+and/or its licensors.  Except as specifically authorized in any Supplemental
+License Terms, you may not make copies of Software, other than a single copy
+of Software for archival purposes.  Unless enforcement is prohibited by
+applicable law, you may not modify, decompile, or reverse engineer
+Software.  You acknowledge that Software is not designed, licensed or
+intended for use in the design, construction, operation or maintenance of
+any nuclear facility.  Sun disclaims any express or implied warranty of
+fitness for such uses.  No right, title or interest in or to any trademark,
+service mark, logo or trade name of Sun or its licensors is granted under
+this Agreement.
+
+3. LIMITED WARRANTY.  Sun warrants to you that for a period of ninety (90)
+days from the date of purchase, as evidenced by a copy of the receipt, the
+media on which Software is furnished (if any) will be free of defects in
+materials and workmanship under normal use.  Except for the foregoing,
+Software is provided "AS IS".  Your exclusive remedy and Sun's entire
+liability under this limited warranty will be at Sun's option to replace
+Software media or refund the fee paid for Software.
+
+4.  DISCLAIMER OF WARRANTY.  UNLESS SPECIFIED IN THIS AGREEMENT, ALL EXPRESS
+OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED
+WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT THESE DISCLAIMERS
+ARE HELD TO BE LEGALLY INVALID.
+
+5.  LIMITATION OF LIABILITY.  TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
+EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR
+DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+DAMAGES, HOWEVER CAUSED REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT
+OF OR RELATED TO THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  In no event will Sun's
+liability to you, whether in contract, tort (including negligence), or
+otherwise, exceed the amount paid by you for Software under this Agreement.
+The foregoing limitations will apply even if the above stated warranty fails
+of its essential purpose.
+
+6.  Termination.  This Agreement is effective until terminated.  You may
+terminate this Agreement at any time by destroying all copies of Software.
+This Agreement will terminate immediately without notice from Sun if you
+fail to comply with any provision of this Agreement.  Upon Termination, you
+must destroy all copies of Software.
+
+7. Export Regulations. All Software and technical data delivered under this
+Agreement are subject to US export control laws and may be subject to export
+or import regulations in other countries.  You agree to comply strictly with
+all such laws and regulations and acknowledge that you have the
+responsibility to obtain such licenses to export, re-export, or import as
+may be required after delivery to you.
+
+8.   U.S. Government Restricted Rights.  If Software is being acquired by or
+on behalf of the U.S. Government or by a U.S. Government prime contractor or
+subcontractor (at any tier), then the Government's rights in Software and
+accompanying documentation will be only as set forth in this Agreement; this
+is in accordance with 48 CFR 227.7201 through 227.7202-4 (for Department of
+Defense (DOD) acquisitions) and with 48 CFR 2.101 and 12.212 (for non-DOD
+acquisitions).
+
+9.  Governing Law.  Any action related to this Agreement will be governed by
+California law and controlling U.S. federal law.  No choice of law rules of
+any jurisdiction will apply.
+
+10.  Severability. If any provision of this Agreement is held to be
+unenforceable, this Agreement will remain in effect with the provision
+omitted, unless omission would frustrate the intent of the parties, in which
+case this Agreement will immediately terminate.
+
+11.  Integration.  This Agreement is the entire agreement between you and
+Sun relating to its subject matter.  It supersedes all prior or
+contemporaneous oral or written communications, proposals, representations
+and warranties and prevails over any conflicting or additional terms of any
+quote, order, acknowledgment, or other communication between the parties
+relating to its subject matter during the term of this Agreement.  No
+modification of this Agreement will be binding, unless in writing and signed
+by an authorized representative of each party.
+
+                           JAVA OPTIONAL PACKAGE
+
+              JAVABEANS(TM) ACTIVATION FRAMEWORK, VERSION 1.0.2
+                         SUPPLEMENTAL LICENSE TERMS
+
+These supplemental license terms ("Supplemental Terms") add to or modify the
+terms of the Binary Code License Agreement (collectively, the "Agreement").
+Capitalized terms not defined in these Supplemental Terms shall have the
+same meanings ascribed to them in the Agreement. These Supplemental Terms
+shall supersede any inconsistent or conflicting terms in the Agreement, or
+in any license contained within the Software.
+
+1. Software Internal Use and Development License Grant.  Subject to the
+terms and conditions of this Agreement, including, but not limited to
+Section 3 (Java(TM) Technology Restrictions) of these Supplemental Terms,
+Sun grants you a non-exclusive, non-transferable, limited license to
+reproduce internally and use internally the binary form of the Software,
+complete and unmodified, for the sole purpose of designing, developing and
+testing your Java applets and applications ("Programs").
+
+2. License to Distribute Software.  In addition to the license granted in
+Section 1 (Software Internal Use and Development License Grant) of these
+Supplemental Terms, subject to the terms and conditions of this Agreement,
+including but not limited to, Section 3 (Java Technology Restrictions) of
+these Supplemental Terms, Sun grants you a non-exclusive, non-transferable,
+limited license to reproduce and distribute the Software in binary code form
+only, provided that you (i) distribute the Software complete and unmodified
+and only bundled as part of your Programs, (ii) do not distribute additional
+software intended to replace any component(s) of the Software, (iii) do not
+remove or alter any proprietary legends or notices contained in the
+Software, (iv) only distribute the Software subject to a license agreement
+that protects Sun's interests consistent with the terms contained in this
+Agreement, and (v) agree to defend and indemnify Sun and its licensors from
+and against any damages, costs, liabilities, settlement amounts and/or
+expenses (including attorneys' fees) incurred in connection with any claim,
+lawsuit or action by any third party that arises or results from the use or
+distribution of any and all Programs and/or Software.
+
+3. Java Technology Restrictions. You may not modify the Java Platform
+Interface ("JPI", identified as classes contained within the "java" package
+or any subpackages of the "java" package), by creating additional classes
+within the JPI or otherwise causing the addition to or modification of the
+classes in the JPI.  In the event that you create an additional class and
+associated API(s) which (i) extends the functionality of the Java platform,
+and (ii) is exposed to third party software developers for the purpose of
+developing additional software which invokes such additional API, you must
+promptly publish broadly an accurate specification for such API for free use
+by all developers.  You may not create, or authorize your licensees to
+create additional classes, interfaces, or subpackages that are in any way
+identified as "java", "javax", "sun" or similar convention as specified by
+Sun in any naming convention designation.
+
+4. No Support. Sun is under no obligation to support the Software or to
+provide you with updates or error corrections. You acknowledge that the
+Software may have defects or deficiencies which cannot or will not be
+corrected by Sun.
+
+5. Trademarks and Logos. You acknowledge and agree as between you and Sun
+that Sun owns the SUN, SOLARIS, JAVA, JINI, FORTE, and iPLANET trademarks
+and all SUN, SOLARIS, JAVA, JINI, FORTE, and iPLANET-related trademarks,
+service marks, logos and other brand designations ("Sun Marks"), and you
+agree to comply with the Sun Trademark and Logo Usage Requirements currently
+located at http://www.sun.com/policies/trademarks. Any use you make of the
+Sun Marks inures to Sun's benefit.
+
+6. Source Code. Software may contain source code that is provided solely for
+reference purposes pursuant to the terms of this Agreement.  Source code may
+not be redistributed unless expressly provided for in this Agreement.
+
+7. Termination for Infringement.  Either party may terminate this Agreement
+immediately should any Software become, or in either party's opinion be
+likely to become, the subject of a claim of infringement of any intellectual
+property right.
+
+For inquiries please contact: Sun Microsystems, Inc.  901 San Antonio Road,
+Palo Alto, California 94303
+(LFI#115020/Form ID#011801)
diff --git a/trunk/legal/LICENSE.javamail b/trunk/legal/LICENSE.javamail
new file mode 100644
index 0000000..2173c8c
--- /dev/null
+++ b/trunk/legal/LICENSE.javamail
@@ -0,0 +1,170 @@
+                          Sun Microsystems, Inc.
+                       Binary Code License Agreement
+
+READ THE TERMS OF THIS AGREEMENT AND ANY PROVIDED SUPPLEMENTAL LICENSE
+TERMS (COLLECTIVELY "AGREEMENT") CAREFULLY BEFORE OPENING THE SOFTWARE
+MEDIA PACKAGE.  BY OPENING THE SOFTWARE MEDIA PACKAGE, YOU AGREE TO THE
+TERMS OF THIS AGREEMENT.  IF YOU ARE ACCESSING THE SOFTWARE ELECTRONICALLY,
+INDICATE YOUR ACCEPTANCE OF THESE TERMS BY SELECTING THE "ACCEPT" BUTTON AT
+THE END OF THIS AGREEMENT.  IF YOU DO NOT AGREE TO ALL THESE TERMS,
+PROMPTLY RETURN THE UNUSED SOFTWARE TO YOUR PLACE OF PURCHASE FOR A REFUND
+OR, IF THE SOFTWARE IS ACCESSED ELECTRONICALLY, SELECT THE "DECLINE" BUTTON
+AT THE END OF THIS AGREEMENT.
+
+1.  LICENSE TO USE.  Sun grants you a non-exclusive and non-transferable
+license for the internal use only of the accompanying software and
+documentation and any error corrections provided by Sun (collectively
+"Software"), by the number of users and the class of computer hardware for
+which the corresponding fee has been paid.
+
+2.  RESTRICTIONS.  Software is confidential and copyrighted. Title to
+Software and all associated intellectual property rights is retained by Sun
+and/or its licensors.  Except as specifically authorized in any
+Supplemental License Terms, you may not make copies of Software, other than
+a single copy of Software for archival purposes.  Unless enforcement is
+prohibited by applicable law, you may not modify, decompile, or reverse
+engineer Software.  You acknowledge that Software is not designed, licensed
+or intended for use in the design, construction, operation or maintenance
+of any nuclear facility.  Sun disclaims any express or implied warranty of
+fitness for such uses.  No right, title or interest in or to any trademark,
+service mark, logo or trade name of Sun or its licensors is granted under
+this Agreement.
+
+3. LIMITED WARRANTY.  Sun warrants to you that for a period of ninety (90)
+days from the date of purchase, as evidenced by a copy of the receipt, the
+media on which Software is furnished (if any) will be free of defects in
+materials and workmanship under normal use.  Except for the foregoing,
+Software is provided "AS IS".  Your exclusive remedy and Sun's entire
+liability under this limited warranty will be at Sun's option to replace
+Software media or refund the fee paid for Software.
+
+4.  DISCLAIMER OF WARRANTY.  UNLESS SPECIFIED IN THIS AGREEMENT, ALL
+EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
+ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT THESE
+DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.
+
+5.  LIMITATION OF LIABILITY.  TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
+EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR
+DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
+DAMAGES, HOWEVER CAUSED REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT
+OF OR RELATED TO THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  In no event will Sun's
+liability to you, whether in contract, tort (including negligence), or
+otherwise, exceed the amount paid by you for Software under this
+Agreement.  The foregoing limitations will apply even if the above stated
+warranty fails of its essential purpose.
+
+6.  Termination.  This Agreement is effective until terminated.  You may
+terminate this Agreement at any time by destroying all copies of Software.
+This Agreement will terminate immediately without notice from Sun if you
+fail to comply with any provision of this Agreement.  Upon Termination, you
+must destroy all copies of Software.
+
+7. Export Regulations. All Software and technical data delivered under this
+Agreement are subject to US export control laws and may be subject to
+export or import regulations in other countries.  You agree to comply
+strictly with all such laws and regulations and acknowledge that you have
+the responsibility to obtain such licenses to export, re-export, or import
+as may be required after delivery to you.
+
+8.   U.S. Government Restricted Rights.  If Software is being acquired by
+or on behalf of the U.S. Government or by a U.S. Government prime
+contractor or subcontractor (at any tier), then the Government's rights in
+Software and accompanying documentation will be only as set forth in this
+Agreement; this is in accordance with 48 CFR 227.7201 through 227.7202-4
+(for Department of Defense (DOD) acquisitions) and with 48 CFR 2.101 and
+12.212 (for non-DOD acquisitions).
+
+9.  Governing Law.  Any action related to this Agreement will be governed
+by California law and controlling U.S. federal law.  No choice of law rules
+of any jurisdiction will apply.
+
+10.  Severability. If any provision of this Agreement is held to be
+unenforceable, this Agreement will remain in effect with the provision
+omitted, unless omission would frustrate the intent of the parties, in
+which case this Agreement will immediately terminate.
+
+11.  Integration.  This Agreement is the entire agreement between you and
+Sun relating to its subject matter.  It supersedes all prior or
+contemporaneous oral or written communications, proposals, representations
+and warranties and prevails over any conflicting or additional terms of any
+quote, order, acknowledgment, or other communication between the parties
+relating to its subject matter during the term of this Agreement.  No
+modification of this Agreement will be binding, unless in writing and
+signed by an authorized representative of each party.
+
+
+                           JAVAMAIL, VERSION 1.3
+                         SUPPLEMENTAL LICENSE TERMS
+
+These supplemental license terms ("Supplemental Terms") add to or modify
+the terms of the Binary Code License Agreement (collectively, the
+"Agreement"). Capitalized terms not defined in these Supplemental Terms
+shall have the same meanings ascribed to them in the Agreement. These
+Supplemental Terms shall supersede any inconsistent or conflicting terms in
+the Agreement, or in any license contained within the Software.
+
+1. Software Internal Use and Development License Grant.  Subject to the
+terms and conditions of this Agreement, including, but not limited to
+Section 3 (Java(TM) Technology Restrictions) of these Supplemental Terms,
+Sun grants you a non-exclusive, non-transferable, limited license to
+reproduce internally and use internally the binary form of the Software,
+complete and unmodified, for the sole purpose of designing, developing and
+testing your Java applets and applications ("Programs").
+
+2. License to Distribute Software. Subject to the terms and conditions of
+this Agreement, including, but not limited to Section 3 (Java (TM)
+Technology Restrictions) of these Supplemental Terms, Sun grants you a
+non-exclusive, non-transferable, limited license to reproduce and
+distribute the Software in binary code form only, provided that (i) you
+distribute the Software complete and unmodified and only bundled as part
+of, and for the sole purpose of  running, your Java applets or applications
+("Programs"), (ii) the Programs add significant and primary functionality
+to the Software, (iii) you do not distribute additional software intended
+to replace any component(s) of the Software, (iv) you do not remove or
+alter any proprietary legends or notices contained in the Software, (v) you
+only distribute the Software subject to a license agreement that protects
+Sun's interests consistent with the terms contained in this Agreement, and
+(vi) you agree to defend and indemnify Sun and its licensors from and
+against any damages, costs, liabilities, settlement amounts and/or expenses
+(including attorneys' fees) incurred in connection with any claim, lawsuit
+or action by any third party that arises or results from the use or
+distribution of any and all Programs and/or Software.
+
+3. Java Technology Restrictions. You may not modify the Java Platform
+Interface ("JPI", identified as classes contained within the "java" package
+or any subpackages of the "java" package), by creating additional classes
+within the JPI or otherwise causing the addition to or modification of the
+classes in the JPI.  In the event that you create an additional class and
+associated API(s) which (i) extends the functionality of the Java platform,
+and (ii) is exposed to third party software developers for the purpose of
+developing additional software which invokes such additional API, you must
+promptly publish broadly an accurate specification for such API for free
+use by all developers.  You may not create, or authorize your licensees to
+create additional classes, interfaces, or subpackages that are in any way
+identified as "java", "javax", "sun" or similar convention as specified by
+Sun in any naming convention designation.
+
+4. Trademarks and Logos. You acknowledge and agree as between you and Sun
+that Sun owns the SUN, SOLARIS, JAVA, JINI, FORTE, STAROFFICE, STARPORTAL
+and iPLANET trademarks and all SUN, SOLARIS, JAVA, JINI, FORTE, STAROFFICE,
+STARPORTAL and iPLANET-related trademarks, service marks, logos and other
+brand designations ("Sun Marks"), and you agree to comply with the Sun
+Trademark and Logo Usage Requirements currently located at
+http://www.sun.com/policies/trademarks. Any use you make of the Sun Marks
+inures to Sun's benefit.
+
+5. Source Code. Software may contain source code that is provided solely
+for reference purposes pursuant to the terms of this Agreement.  Source
+code may not be redistributed unless expressly provided for in this
+Agreement.
+
+6. Termination for Infringement.  Either party may terminate this Agreement
+immediately should any Software become, or in either party's opinion be
+likely to become, the subject of a claim of infringement of any
+intellectual property right.
+
+For inquiries please contact: Sun Microsystems, Inc., 4150 Network Circle,
+Santa Clara, California 95054, U.S.A
+(LFI#114176/Form ID#011801)
diff --git a/trunk/legal/LICENSE.junit b/trunk/legal/LICENSE.junit
new file mode 100644
index 0000000..fbd1e20
--- /dev/null
+++ b/trunk/legal/LICENSE.junit
@@ -0,0 +1,185 @@
+
+IBM Public License Version 1.0 
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS IBM PUBLIC 
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE 
+PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 
+1. DEFINITIONS 
+
+"Contribution" means: 
+  a) in the case of International Business Machines Corporation ("IBM"), 
+  the Original Program, and 
+  b) in the case of each Contributor, 
+  i) changes to the Program, and
+  ii) additions to the Program;
+  where such changes and/or additions to the Program originate from and 
+  are distributed by that particular Contributor. A Contribution 
+  'originates' from a Contributor if it was added to the Program by such 
+  Contributor itself or anyone acting on such Contributor's behalf. 
+  Contributions do not include additions to the Program which: (i) are 
+  separate modules of software distributed in conjunction with the Program 
+  under their own license agreement, and (ii) are not derivative works of 
+  the Program.
+"Contributor" means IBM and any other entity that distributes the Program. 
+
+"Licensed Patents " mean patent claims licensable by a Contributor which 
+are necessarily infringed by the use or sale of its Contribution alone or 
+when combined with the Program. 
+"Original Program" means the original version of the software accompanying 
+this Agreement as released by IBM, including source code, object code and 
+documentation, if any. 
+"Program" means the Original Program and Contributions. 
+"Recipient" means anyone who receives the Program under this Agreement, 
+including all Contributors. 
+2. GRANT OF RIGHTS 
+  a) Subject to the terms of this Agreement, each Contributor hereby 
+  grants Recipient a non-exclusive, worldwide, royalty-free copyright 
+  license to reproduce, prepare derivative works of, publicly display, 
+  publicly perform, distribute and sublicense the Contribution of such 
+  Contributor, if any, and such derivative works, in source code and 
+  object code form.
+  b) Subject to the terms of this Agreement, each Contributor hereby 
+  grants Recipient a non-exclusive, worldwide, royalty-free patent license 
+  under Licensed Patents to make, use, sell, offer to sell, import and 
+  otherwise transfer the Contribution of such Contributor, if any, in 
+  source code and object code form. This patent license shall apply to the 
+  combination of the Contribution and the Program if, at the time the 
+  Contribution is added by the Contributor, such addition of the 
+  Contribution causes such combination to be covered by the Licensed 
+  Patents. The patent license shall not apply to any other combinations 
+  which include the Contribution. No hardware per se is licensed 
+  hereunder. 
+  c) Recipient understands that although each Contributor grants the 
+  licenses to its Contributions set forth herein, no assurances are 
+  provided by any Contributor that the Program does not infringe the 
+  patent or other intellectual property rights of any other entity. Each 
+  Contributor disclaims any liability to Recipient for claims brought by 
+  any other entity based on infringement of intellectual property rights 
+  or otherwise. As a condition to exercising the rights and licenses 
+  granted hereunder, each Recipient hereby assumes sole responsibility to 
+  secure any other intellectual property rights needed, if any. For 
+  example, if a third party patent license is required to allow Recipient 
+  to distribute the Program, it is Recipient's responsibility to acquire 
+  that license before distributing the Program.
+  d) Each Contributor represents that to its knowledge it has sufficient 
+  copyright rights in its Contribution, if any, to grant the copyright 
+  license set forth in this Agreement. 
+3. REQUIREMENTS 
+A Contributor may choose to distribute the Program in object code form 
+under its own license agreement, provided that: 
+  a) it complies with the terms and conditions of this Agreement; and
+  b) its license agreement:
+  i) effectively disclaims on behalf of all Contributors all warranties 
+  and conditions, express and implied, including warranties or conditions 
+  of title and non-infringement, and implied warranties or conditions of 
+  merchantability and fitness for a particular purpose; 
+  ii) effectively excludes on behalf of all Contributors all liability for 
+  damages, including direct, indirect, special, incidental and 
+  consequential damages, such as lost profits; 
+  iii) states that any provisions which differ from this Agreement are 
+  offered by that Contributor alone and not by any other party; and
+  iv) states that source code for the Program is available from such 
+  Contributor, and informs licensees how to obtain it in a reasonable 
+  manner on or through a medium customarily used for software exchange.
+When the Program is made available in source code form: 
+  a) it must be made available under this Agreement; and 
+  b) a copy of this Agreement must be included with each copy of the 
+  Program. 
+Each Contributor must include the following in a conspicuous location in 
+the Program: 
+  Copyright © {date here}, International Business Machines Corporation and 
+  others. All Rights Reserved. 
+In addition, each Contributor must identify itself as the originator of 
+its Contribution, if any, in a manner that reasonably allows subsequent 
+Recipients to identify the originator of the Contribution. 
+4. COMMERCIAL DISTRIBUTION 
+Commercial distributors of software may accept certain responsibilities 
+with respect to end users, business partners and the like. While this 
+license is intended to facilitate the commercial use of the Program, the 
+Contributor who includes the Program in a commercial product offering 
+should do so in a manner which does not create potential liability for 
+other Contributors. Therefore, if a Contributor includes the Program in a 
+commercial product offering, such Contributor ("Commercial Contributor") 
+hereby agrees to defend and indemnify every other Contributor 
+("Indemnified Contributor") against any losses, damages and costs 
+(collectively "Losses") arising from claims, lawsuits and other legal 
+actions brought by a third party against the Indemnified Contributor to 
+the extent caused by the acts or omissions of such Commercial Contributor 
+in connection with its distribution of the Program in a commercial product 
+offering. The obligations in this section do not apply to any claims or 
+Losses relating to any actual or alleged intellectual property 
+infringement. In order to qualify, an Indemnified Contributor must: a) 
+promptly notify the Commercial Contributor in writing of such claim, and 
+b) allow the Commercial Contributor to control, and cooperate with the 
+Commercial Contributor in, the defense and any related settlement 
+negotiations. The Indemnified Contributor may participate in any such 
+claim at its own expense. 
+For example, a Contributor might include the Program in a commercial 
+product offering, Product X. That Contributor is then a Commercial 
+Contributor. If that Commercial Contributor then makes performance claims, 
+or offers warranties related to Product X, those performance claims and 
+warranties are such Commercial Contributor's responsibility alone. Under 
+this section, the Commercial Contributor would have to defend claims 
+against the other Contributors related to those performance claims and 
+warranties, and if a court requires any other Contributor to pay any 
+damages as a result, the Commercial Contributor must pay those damages. 
+5. NO WARRANTY 
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED 
+ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER 
+EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR 
+CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A 
+PARTICULAR PURPOSE. Each Recipient is solely responsible for determining 
+the appropriateness of using and distributing the Program and assumes all 
+risks associated with its exercise of rights under this Agreement, 
+including but not limited to the risks and costs of program errors, 
+compliance with applicable laws, damage to or loss of data, programs or 
+equipment, and unavailability or interruption of operations. 
+6. DISCLAIMER OF LIABILITY 
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, 
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING 
+WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF 
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION 
+OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF 
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+7. GENERAL 
+If any provision of this Agreement is invalid or unenforceable under 
+applicable law, it shall not affect the validity or enforceability of the 
+remainder of the terms of this Agreement, and without further action by 
+the parties hereto, such provision shall be reformed to the minimum extent 
+necessary to make such provision valid and enforceable. 
+If Recipient institutes patent litigation against a Contributor with 
+respect to a patent applicable to software (including a cross-claim or 
+counterclaim in a lawsuit), then any patent licenses granted by that 
+Contributor to such Recipient under this Agreement shall terminate as of 
+the date such litigation is filed. In addition, If Recipient institutes 
+patent litigation against any entity (including a cross-claim or 
+counterclaim in a lawsuit) alleging that the Program itself (excluding 
+combinations of the Program with other software or hardware) infringes 
+such Recipient's patent(s), then such Recipient's rights granted under 
+Section 2(b) shall terminate as of the date such litigation is filed. 
+All Recipient's rights under this Agreement shall terminate if it fails to 
+comply with any of the material terms or conditions of this Agreement and 
+does not cure such failure in a reasonable period of time after becoming 
+aware of such noncompliance. If all Recipient's rights under this 
+Agreement terminate, Recipient agrees to cease use and distribution of the 
+Program as soon as reasonably practicable. However, Recipient's 
+obligations under this Agreement and any licenses granted by Recipient 
+relating to the Program shall continue and survive. 
+IBM may publish new versions (including revisions) of this Agreement from 
+time to time. Each new version of the Agreement will be given a 
+distinguishing version number. The Program (including Contributions) may 
+always be distributed subject to the version of the Agreement under which 
+it was received. In addition, after a new version of the Agreement is 
+published, Contributor may elect to distribute the Program (including its 
+Contributions) under the new version. No one other than IBM has the right 
+to modify this Agreement. Except as expressly stated in Sections 2(a) and 
+2(b) above, Recipient receives no rights or licenses to the intellectual 
+property of any Contributor under this Agreement, whether expressly, by 
+implication, estoppel or otherwise. All rights in the Program not 
+expressly granted under this Agreement are reserved. 
+This Agreement is governed by the laws of the State of New York and the 
+intellectual property laws of the United States of America. No party to 
+this Agreement will bring a legal action under this Agreement more than 
+one year after the cause of action arose. Each party waives its rights to 
+a jury trial in any resulting litigation. 
diff --git a/trunk/legal/LICENSE.log4j b/trunk/legal/LICENSE.log4j
new file mode 100644
index 0000000..007db57
--- /dev/null
+++ b/trunk/legal/LICENSE.log4j
@@ -0,0 +1,48 @@
+/*
+ * ============================================================================
+ *                   The Apache Software License, Version 1.1
+ * ============================================================================
+ * 
+ *    Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modifica-
+ * tion, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of  source code must  retain the above copyright  notice,
+ *    this list of conditions and the following disclaimer.
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * 3. The end-user documentation included with the redistribution, if any, must
+ *    include  the following  acknowledgment:  "This product includes  software
+ *    developed  by the  Apache Software Foundation  (http://www.apache.org/)."
+ *    Alternately, this  acknowledgment may  appear in the software itself,  if
+ *    and wherever such third-party acknowledgments normally appear.
+ * 
+ * 4. The names "log4j" and  "Apache Software Foundation"  must not be used to
+ *    endorse  or promote  products derived  from this  software without  prior
+ *    written permission. For written permission, please contact
+ *    apache@apache.org.
+ * 
+ * 5. Products  derived from this software may not  be called "Apache", nor may
+ *    "Apache" appear  in their name,  without prior written permission  of the
+ *    Apache Software Foundation.
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
+ * APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
+ * DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
+ * ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
+ * (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * This software  consists of voluntary contributions made  by many individuals
+ * on  behalf of the Apache Software  Foundation.  For more  information on the 
+ * Apache Software Foundation, please see <http://www.apache.org/>.
+ *
+ */
diff --git a/trunk/legal/LICENSE.opensaml b/trunk/legal/LICENSE.opensaml
new file mode 100644
index 0000000..becbdf3
--- /dev/null
+++ b/trunk/legal/LICENSE.opensaml
@@ -0,0 +1,47 @@
+The OpenSAML License, Version 1. 
+Copyright (c) 2002 
+University Corporation for Advanced Internet Development, Inc. 
+All rights reserved
+
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this 
+list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, 
+this list of conditions and the following disclaimer in the documentation 
+and/or other materials provided with the distribution, if any, must include 
+the following acknowledgment: "This product includes software developed by 
+the University Corporation for Advanced Internet Development 
+<http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
+may appear in the software itself, if and wherever such third-party 
+acknowledgments normally appear.
+
+Neither the name of OpenSAML nor the names of its contributors, nor 
+Internet2, nor the University Corporation for Advanced Internet Development, 
+Inc., nor UCAID may be used to endorse or promote products derived from this 
+software without specific prior written permission. For written permission, 
+please contact opensaml@opensaml.org
+
+Products derived from this software may not be called OpenSAML, Internet2, 
+UCAID, or the University Corporation for Advanced Internet Development, nor 
+may OpenSAML appear in their name, without prior written permission of the 
+University Corporation for Advanced Internet Development.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
+OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
+IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
+CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/trunk/legal/LICENSE.security b/trunk/legal/LICENSE.security
new file mode 100644
index 0000000..16b47ec
--- /dev/null
+++ b/trunk/legal/LICENSE.security
@@ -0,0 +1,54 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2002 The Apache Software Foundation.  All rights 
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:  
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache XML-Security" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written 
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
diff --git a/trunk/legal/LICENSE.wsdl4j b/trunk/legal/LICENSE.wsdl4j
new file mode 100644
index 0000000..709c2d4
--- /dev/null
+++ b/trunk/legal/LICENSE.wsdl4j
@@ -0,0 +1,91 @@
+Common Public License  
+ 
+ Common Public License Version 0.5 
+ 
+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 
+ 
+ 
+ 1. DEFINITIONS 
+ 
+ "Contribution" means: 
+ 
+ a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and 
+ b) in the case of each subsequent Contributor:
+ i) changes to the Program, and
+ ii) additions to the Program;
+ where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
+ 
+ "Contributor" means any person or entity that distributes the Program. 
+ 
+ 
+ "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. 
+ 
+ 
+ "Program" means the Contributions distributed in accordance with this Agreement. 
+ 
+ 
+ "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 
+ 
+ 
+ 2. GRANT OF RIGHTS 
+ 
+ a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
+ b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
+ c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
+ d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 
+ 3. REQUIREMENTS 
+ 
+ A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: 
+ 
+ a) it complies with the terms and conditions of this Agreement; and
+ b) its license agreement:
+ i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; 
+ ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; 
+ iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
+ iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. 
+ When the Program is made available in source code form: 
+ 
+ a) it must be made available under this Agreement; and 
+ b) a copy of this Agreement must be included with each copy of the Program. 
+ 
+ Contributors may not remove or alter any copyright notices contained within the Program. 
+ 
+ 
+ 
+ Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 
+ 
+ 
+ 4. COMMERCIAL DISTRIBUTION 
+ 
+ Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. 
+ 
+ 
+ For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 
+ 
+ 
+ 5. NO WARRANTY 
+ 
+ EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 
+ 
+ 
+ 6. DISCLAIMER OF LIABILITY 
+ 
+ EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
+ 
+ 
+ 7. GENERAL 
+ 
+ If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. 
+ 
+ 
+ If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. 
+ 
+ 
+ All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. 
+ 
+ 
+ Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. 
+ 
+ 
+ This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. 
+ 
\ No newline at end of file
diff --git a/trunk/legal/LICENSE.xalan b/trunk/legal/LICENSE.xalan
new file mode 100644
index 0000000..21156a6
--- /dev/null
+++ b/trunk/legal/LICENSE.xalan
@@ -0,0 +1,55 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999 The Apache Software Foundation.  All rights 
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:  
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xalan" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written 
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
diff --git a/trunk/legal/LICENSE.xerces b/trunk/legal/LICENSE.xerces
new file mode 100644
index 0000000..b37087c
--- /dev/null
+++ b/trunk/legal/LICENSE.xerces
@@ -0,0 +1,56 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation.  All rights 
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:  
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Xerces" and "Apache Software Foundation" must
+ *    not be used to endorse or promote products derived from this
+ *    software without prior written permission. For written 
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    nor may "Apache" appear in their name, without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, International
+ * Business Machines, Inc., http://www.ibm.com.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
diff --git a/trunk/legal/LICENSE.xml-apis b/trunk/legal/LICENSE.xml-apis
new file mode 100644
index 0000000..930145f
--- /dev/null
+++ b/trunk/legal/LICENSE.xml-apis
@@ -0,0 +1,5 @@
+
+xml-apis is covered by The Apache Software License, Version 1.1
+
+FIXME: Put license text in here once it is available at
+       http://cvs.apache.org/viewcvs.cgi/xml-commons/
diff --git a/trunk/lib/addressing-1.0.jar b/trunk/lib/addressing-1.0.jar
new file mode 100644
index 0000000..9cdca98
--- /dev/null
+++ b/trunk/lib/addressing-1.0.jar
Binary files differ
diff --git a/trunk/lib/axis-1.4.jar b/trunk/lib/axis-1.4.jar
new file mode 100644
index 0000000..20b09a5
--- /dev/null
+++ b/trunk/lib/axis-1.4.jar
Binary files differ
diff --git a/trunk/lib/axis-ant-1.4.jar b/trunk/lib/axis-ant-1.4.jar
new file mode 100644
index 0000000..17527ff
--- /dev/null
+++ b/trunk/lib/axis-ant-1.4.jar
Binary files differ
diff --git a/trunk/lib/axis-jaxrpc-1.4.jar b/trunk/lib/axis-jaxrpc-1.4.jar
new file mode 100644
index 0000000..a2c13d9
--- /dev/null
+++ b/trunk/lib/axis-jaxrpc-1.4.jar
Binary files differ
diff --git a/trunk/lib/axis-saaj-1.4.jar b/trunk/lib/axis-saaj-1.4.jar
new file mode 100644
index 0000000..4ea696e
--- /dev/null
+++ b/trunk/lib/axis-saaj-1.4.jar
Binary files differ
diff --git a/trunk/lib/bcprov-jdk14-140.jar b/trunk/lib/bcprov-jdk14-140.jar
new file mode 100644
index 0000000..2bfb790
--- /dev/null
+++ b/trunk/lib/bcprov-jdk14-140.jar
Binary files differ
diff --git a/trunk/lib/commons-codec-1.3.jar b/trunk/lib/commons-codec-1.3.jar
new file mode 100644
index 0000000..957b675
--- /dev/null
+++ b/trunk/lib/commons-codec-1.3.jar
Binary files differ
diff --git a/trunk/lib/commons-discovery-0.2.jar b/trunk/lib/commons-discovery-0.2.jar
new file mode 100644
index 0000000..b885548
--- /dev/null
+++ b/trunk/lib/commons-discovery-0.2.jar
Binary files differ
diff --git a/trunk/lib/commons-logging-1.1.jar b/trunk/lib/commons-logging-1.1.jar
new file mode 100644
index 0000000..2ff9bbd
--- /dev/null
+++ b/trunk/lib/commons-logging-1.1.jar
Binary files differ
diff --git a/trunk/lib/junit-3.8.1.jar b/trunk/lib/junit-3.8.1.jar
new file mode 100644
index 0000000..674d71e
--- /dev/null
+++ b/trunk/lib/junit-3.8.1.jar
Binary files differ
diff --git a/trunk/lib/log4j-1.2.9.jar b/trunk/lib/log4j-1.2.9.jar
new file mode 100644
index 0000000..a6568b0
--- /dev/null
+++ b/trunk/lib/log4j-1.2.9.jar
Binary files differ
diff --git a/trunk/lib/opensaml-1.1.jar b/trunk/lib/opensaml-1.1.jar
new file mode 100644
index 0000000..852f133
--- /dev/null
+++ b/trunk/lib/opensaml-1.1.jar
Binary files differ
diff --git a/trunk/lib/serializer-2.7.1.jar b/trunk/lib/serializer-2.7.1.jar
new file mode 100644
index 0000000..99f98db
--- /dev/null
+++ b/trunk/lib/serializer-2.7.1.jar
Binary files differ
diff --git a/trunk/lib/wsdl4j-1.5.1.jar b/trunk/lib/wsdl4j-1.5.1.jar
new file mode 100644
index 0000000..c6254ee
--- /dev/null
+++ b/trunk/lib/wsdl4j-1.5.1.jar
Binary files differ
diff --git a/trunk/lib/xalan-2.7.1.jar b/trunk/lib/xalan-2.7.1.jar
new file mode 100644
index 0000000..458fa73
--- /dev/null
+++ b/trunk/lib/xalan-2.7.1.jar
Binary files differ
diff --git a/trunk/lib/xmlsec-1.4.2.jar b/trunk/lib/xmlsec-1.4.2.jar
new file mode 100644
index 0000000..6753cec
--- /dev/null
+++ b/trunk/lib/xmlsec-1.4.2.jar
Binary files differ
diff --git a/trunk/maven.xml b/trunk/maven.xml
new file mode 100644
index 0000000..d9a3ba3
--- /dev/null
+++ b/trunk/maven.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- $Revision$ $Date$ -->
+
+<project default="jar"
+    xmlns:j="jelly:core"
+    xmlns:maven="jelly:maven"
+    xmlns:deploy="deploy"
+    xmlns:ant="jelly:ant">
+
+    <path id="test.classpath">
+        <path refid="maven.dependency.classpath"/>
+        <pathelement path="${maven.build.dest}"/>
+        <pathelement path="target/classes"/>
+        <pathelement path="target/test-classes"/>
+    </path>
+
+    <preGoal name="java:compile">
+        <ant:path id="classpath.libraries">
+            <ant:fileset dir="./lib">
+                <ant:include name="**/*.jar"/>
+            </ant:fileset>
+            <ant:pathelement path="${maven.build.dest}"/>
+            <ant:pathelement path="target/classes"/>
+        </ant:path>
+        <maven:addPath id="maven.dependency.classpath" refid="classpath.libraries"/>
+    </preGoal>
+
+    <preGoal name="test:compile">
+        <taskdef resource="axis-tasks.properties" classpathref="maven.dependency.classpath"/>
+
+        <property name="dir.wss4j" value="."/>
+        <property name="dir.interop" value="${dir.wss4j}/interop"/>
+        <property name="dir.interop2" value="${dir.wss4j}/test"/>
+        <property name="dir.work" value="${dir.wss4j}/target/work"/>
+        <property name="server" value="org/apache/ws/axis/oasis/ping"/>
+        <property name="client" value="org/apache/ws/axis/oasis"/>
+
+        <mkdir dir="${dir.work}"/>
+
+        <axis-wsdl2java
+            output="${dir.work}"
+            serverSide="yes"
+            testcase="no"
+            verbose="no"
+            url="${dir.interop}/ping.wsdl">
+            <mapping
+                namespace="http://xmlsoap.org/Ping"
+                package="org.apache.ws.axis.oasis.ping"/>
+        </axis-wsdl2java>
+
+        <copy todir="target/classes" overwrite="yes">
+          <fileset dir="${dir.interop}/${server}">
+            <include name="*.properties"/>
+          </fileset>
+        </copy>
+        <copy todir="${dir.work}/${server}" overwrite="yes">
+          <fileset dir="${dir.interop}/${server}">
+            <include name="*.java"/>
+            <include name="*.wsdd"/>
+          </fileset>
+        </copy>
+        <copy todir="${dir.work}/${client}" overwrite="yes">
+          <fileset dir="${dir.interop}/${client}">
+            <include name="*.java"/>
+            <include name="*.wsdd"/>
+          </fileset>
+        </copy>
+
+        <path id="wss4j.samples.set"
+              location="${basedir}/samples"/>
+        <path id="wss4j.generated.set"
+              location="${basedir}/target/work"/>
+        <maven:addPath id="maven.test.compile.src.set"
+                       refid="wss4j.samples.set"/>
+        <maven:addPath id="maven.test.compile.src.set"
+                       refid="wss4j.generated.set"/>
+    </preGoal>
+
+    <goal name="start-functional-test-http-server">
+        <ant:echo message="Starting http server."/>
+        <ant:java classname="org.apache.axis.transport.http.SimpleAxisServer" fork="true" spawn="yes" dir=".">
+            <ant:classpath refid="test.classpath"/>
+        </ant:java>
+    </goal>
+
+    <preGoal name="test:test">
+        <j:thread>
+          <attainGoal name="start-functional-test-http-server"/>
+        </j:thread>
+
+        <sleep seconds="2"/>
+
+        <path id="deploy.xml.files">
+            <fileset dir="./target/work">
+                <include name="**/deploy.wsdd"/>
+            </fileset>
+        </path>
+
+        <property name="deploy.xml.property" refid="deploy.xml.files"/>
+
+        <java classname="org.apache.axis.utils.Admin" fork="true">
+            <classpath refid="maven.dependency.classpath"/>
+            <arg value="client"/>
+            <arg file="./target/work/org/apache/ws/axis/oasis/Client_deploy.wsdd"/>
+        </java>
+        
+        <java classname="org.apache.axis.client.AdminClient" fork="yes">
+            <classpath refid="maven.dependency.classpath"/>
+            <arg line="${deploy.xml.property}"/>
+        </java>
+    </preGoal>
+
+    <postGoal name="test:test">
+        <echo message="Stopping http server."/>
+
+        <path id="undeploy.xml.files">
+            <fileset dir="./target/work">
+                <include name="**/undeploy.wsdd"/>
+            </fileset>
+        </path>
+
+        <property name="undeploy.xml.property" refid="deploy.xml.files"/>
+
+        <java classname="org.apache.axis.client.AdminClient" fork="yes">
+            <classpath refid="maven.dependency.classpath"/>
+            <arg line="${undeploy.xml.property}"/>
+        </java>
+
+
+        <java classname="org.apache.axis.client.AdminClient" fork="yes">
+            <classpath refid="maven.dependency.classpath"/>
+            <arg line="quit"/>
+        </java>
+    </postGoal>
+
+    <postGoal name="jar">
+        <ant:mkdir dir="${basedir}/target/lib"/>
+    </postGoal>
+    <!--
+    <preGoal name="xdoc:jelly-transform">
+      <attainGoal name="html2xdoc"/>
+    </preGoal>  
+    -->
+</project>
diff --git a/trunk/pom.xml b/trunk/pom.xml
new file mode 100644
index 0000000..abb4d2e
--- /dev/null
+++ b/trunk/pom.xml
@@ -0,0 +1,428 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<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.ws.security</groupId>

+    <artifactId>wss4j</artifactId>

+    <name>WSS4J</name>

+    <!-- <version>1.5.4</version> -->

+    <version>SNAPSHOT</version>

+    <description>

+        Apache WSS4J is an implementation of the Web Services Security

+        (WS-Security) being developed at OASIS Web Services Security TC.

+        WSS4J is a primarily a Java library that can be used to sign and

+        verify SOAP Messages with WS-Security information. WSS4J will

+        use Apache Axis and Apache XML-Security projects and will be

+        interoperable with JAX-RPC based server/clients and .NET

+        server/clients.

+    </description>

+    <url>http://ws.apache.org/wss4j/</url>

+    <issueManagement>

+        <system>JIRA</system>

+        <url>http://issues.apache.org/jira/browse/WSS</url>

+    </issueManagement>

+    <mailingLists>

+        <mailingList>

+            <name>WSS4J Developer List</name>

+            <subscribe>wss4j-dev-subscribe@ws.apache.org</subscribe>

+            <unsubscribe>

+                wss4j-dev-unsubscribe@ws.apache.org

+            </unsubscribe>

+            <post>wss4j-dev@ws.apache.org</post>

+            <archive>

+                http://mail-archives.apache.org/mod_mbox/ws-wss4j-dev/

+            </archive>

+            <otherArchives>

+                <otherArchive>http://www.nabble.com/WSS4J-f2398.html</otherArchive>

+            </otherArchives>

+        </mailingList>

+    </mailingLists>

+    <inceptionYear>2004</inceptionYear>

+    <!-- who the developers are for the project -->

+    <developers>

+        <developer>

+            <name>Davanum Srinivas</name>

+            <id>dims</id>

+            <email>dims@yahoo.com</email>

+            <organization></organization>

+        </developer>

+        <developer>

+            <name>Werner Dittmann</name>

+            <id>werner</id>

+            <email>werner@apache.org</email>

+            <organization></organization>

+        </developer>

+        <developer>

+            <name>Ias</name>

+            <id>ias</id>

+            <email>ias@apache.org</email>

+            <organization></organization>

+        </developer>

+        <developer>

+            <name>Ruchith Fernando</name>

+            <id>ruchithf</id>

+            <email>ruchithf@apache.org</email>

+            <organization></organization>

+        </developer>

+        <developer>

+            <name>Fred Dushin</name>

+            <id>fadushin</id>

+            <email>fadushin@apache.org</email>

+            <organization></organization>

+        </developer>

+        <developer>

+            <name>Colm O hEigeartaigh</name>

+            <id>coheigea</id>

+            <email>coheigea@apache.org</email>

+            <organization></organization>

+        </developer>

+    </developers>

+    <licenses>

+        <license>

+            <name>The Apache Software License, Version 2.0</name>

+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>

+            <distribution>repo</distribution>

+        </license>

+    </licenses>

+    <scm>

+        <connection>

+            scm:svn:http://svn.apache.org/repos/asf/webservices/wss4j/trunk/

+        </connection>

+        <developerConnection>

+            scm:svn:https://svn.apache.org/repos/asf/webservices/wss4j/trunk/

+        </developerConnection>

+        <url>http://svn.apache.org/viewvc/webservices/wss4j/trunk</url>

+    </scm>

+    <organization>

+        <name>Apache Software Foundation</name>

+        <url>http://www.apache.org/</url>

+    </organization>

+    

+    <build>

+        <sourceDirectory>src</sourceDirectory>

+        <resources>

+            <resource>

+                <directory>src</directory>

+                <includes>

+                    <include>org/**/errors.properties</include>

+                </includes>

+                <filtering>false</filtering>

+            </resource>

+        </resources>

+

+        <plugins>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-antrun-plugin</artifactId>

+                <version>1.2</version>

+                <executions>

+                    <execution>

+                        <id>prepareLicenseFiles</id>

+                        <phase>generate-resources</phase>

+                        <configuration>

+                            <tasks>

+                                <copy

+                                    todir="${project.build.outputDirectory}/META-INF">

+                                    <fileset dir="${basedir}">

+                                        <include name="LICENSE.txt" />

+                                        <include name="NOTICE.txt" />

+                                    </fileset>

+                                </copy>

+                            </tasks>

+                        </configuration>

+                        <goals>

+                            <goal>run</goal>

+                        </goals>

+                    </execution>

+                </executions>

+            </plugin>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-one-plugin</artifactId>

+                <version>1.2</version>

+                <executions>

+                    <execution>

+                        <goals>

+                            <goal>install-maven-one-repository</goal>

+                            <goal>deploy-maven-one-repository</goal>

+                        </goals>

+                    </execution>

+                </executions>

+                <configuration>

+                    <remoteRepositoryId>apache</remoteRepositoryId>

+                    <remoteRepositoryUrl>

+                        scpexe://people.apache.org/www/people.apache.org/repo/m1-snapshot-repository

+                    </remoteRepositoryUrl>

+                </configuration>

+            </plugin>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-release-plugin</artifactId>

+                <configuration>

+                    <tagBase>

+                        https://svn.apache.org/repos/asf/webservices/wss4j/tags/

+                    </tagBase>

+                </configuration>

+            </plugin>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-compiler-plugin</artifactId>

+                <version>2.0.2</version>

+                <configuration>

+                    <source>1.3</source>

+                    <target>1.3</target>

+                </configuration>

+            </plugin>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-assembly-plugin</artifactId>

+                <version>2.1</version>

+                <configuration>

+                    <descriptors>

+                        <descriptor>assembly/bin.xml</descriptor>

+                        <descriptor>assembly/src.xml</descriptor>

+                    </descriptors>

+                    <tarLongFileMode>gnu</tarLongFileMode>

+                </configuration>

+            </plugin>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-source-plugin</artifactId>

+                <version>2.0.4</version>

+                <executions>

+                    <execution>

+                        <goals>

+                            <goal>jar</goal>

+                        </goals>

+                    </execution>

+                </executions>

+                <configuration>

+                    <attach>true</attach>

+                </configuration>

+            </plugin>

+        </plugins>

+    </build>

+    

+    <profiles>

+        <profile>

+            <id>release</id>

+            <activation>

+                <property>

+                    <name>release</name>

+                    <value></value>

+                </property>

+            </activation>

+            <build>

+                <plugins>

+                    <plugin>

+                        <groupId>org.apache.maven.plugins</groupId>

+                        <artifactId>maven-javadoc-plugin</artifactId>

+                        <version>2.5</version>

+                        <executions>

+                            <execution>

+                                <goals>

+                                    <goal>jar</goal>

+                                </goals>

+                            </execution>

+                        </executions>

+                        <configuration>

+                            <attach>true</attach>

+                        </configuration>

+                    </plugin>

+                </plugins>

+            </build>

+        </profile>

+        <profile>

+            <id>jdk14</id>

+            <activation>

+                <activeByDefault>true</activeByDefault>

+                <jdk>1.4</jdk>

+            </activation>

+            <dependencies>

+                <dependency>

+                    <groupId>bouncycastle</groupId>

+                    <artifactId>bcprov-jdk14</artifactId>

+                    <version>${bcprov.jdk14.version}</version>

+                </dependency>

+            </dependencies>

+        </profile>

+        <profile>

+            <id>jdk15</id>

+            <activation>

+                <jdk>1.5</jdk>

+            </activation>

+            <dependencies>

+                <dependency>

+                    <groupId>bouncycastle</groupId>

+                    <artifactId>bcprov-jdk15</artifactId>

+                    <version>${bcprov.jdk15.version}</version>

+                </dependency>

+            </dependencies>

+        </profile>

+    </profiles>

+    

+    <properties>

+        <xmlsec.version>1.4.2</xmlsec.version>

+        <opensaml.version>1.1</opensaml.version>

+        <xml.apis.version>1.3.03</xml.apis.version>

+        <bcprov.jdk14.version>140</bcprov.jdk14.version>

+        <bcprov.jdk15.version>140</bcprov.jdk15.version>

+        <commons.logging.version>1.1</commons.logging.version>

+        <xalan.version>2.7.1</xalan.version>

+        <xerces.version>2.8.1</xerces.version>

+        <axis.version>1.4</axis.version>

+        <junit.version>3.8.1</junit.version>

+    </properties>

+    

+    <repositories>

+        <repository>

+            <releases>

+                <enabled>true</enabled>

+                <updatePolicy>always</updatePolicy>

+                <checksumPolicy>warn</checksumPolicy>

+            </releases>

+            <snapshots>

+                <enabled>false</enabled>

+                <updatePolicy>never</updatePolicy>

+                <checksumPolicy>warn</checksumPolicy>

+            </snapshots>

+            <id>apache-ws-snapshots2</id>

+            <name>Apache ws.zones - 2</name>

+            <url>http://ws.zones.apache.org/repository2/</url>

+        </repository>

+    </repositories>

+

+    <dependencies>

+        <dependency>

+            <groupId>commons-logging</groupId>

+            <artifactId>commons-logging</artifactId>

+            <version>${commons.logging.version}</version>

+        </dependency>

+        <dependency>

+            <groupId>org.apache.santuario</groupId>

+            <artifactId>xmlsec</artifactId>

+            <version>${xmlsec.version}</version>

+        </dependency>

+        <dependency>

+            <groupId>opensaml</groupId>

+            <artifactId>opensaml</artifactId>

+            <version>${opensaml.version}</version>

+        </dependency>

+        <dependency>

+            <groupId>org.apache.axis</groupId>

+            <artifactId>axis</artifactId>

+            <version>${axis.version}</version>

+            <scope>provided</scope>

+        </dependency>

+        <dependency>

+            <groupId>org.apache.axis</groupId>

+            <artifactId>axis-ant</artifactId>

+            <version>${axis.version}</version>

+            <scope>provided</scope>

+        </dependency>

+        <dependency>

+            <groupId>org.apache.axis</groupId>

+            <artifactId>axis-jaxrpc</artifactId>

+            <version>${axis.version}</version>

+            <scope>provided</scope>

+        </dependency>

+        <dependency>

+            <groupId>org.apache.axis</groupId>

+            <artifactId>axis-saaj</artifactId>

+            <version>${axis.version}</version>

+            <scope>provided</scope>

+        </dependency>

+        <dependency>

+            <groupId>xalan</groupId>

+            <artifactId>xalan</artifactId>

+            <version>${xalan.version}</version>

+        </dependency>

+        <dependency>

+            <groupId>xerces</groupId>

+            <artifactId>xercesImpl</artifactId>

+            <version>${xerces.version}</version>

+        </dependency>

+        <dependency>

+            <groupId>xml-apis</groupId>

+            <artifactId>xml-apis</artifactId>

+            <version>${xml.apis.version}</version>

+        </dependency>

+        <dependency>

+            <groupId>junit</groupId>

+            <artifactId>junit</artifactId>

+            <version>${junit.version}</version>

+        </dependency>

+    </dependencies>

+

+    <reporting>

+        <plugins>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-project-info-reports-plugin</artifactId>

+                <version>2.1</version>

+                <reportSets>

+                    <reportSet>

+                        <reports>

+                            <report>dependencies</report>

+                            <report>issue-tracking</report>

+                            <report>license</report>

+                            <report>mailing-list</report>

+                            <report>project-team</report>

+                            <report>scm</report>

+                        </reports>

+                    </reportSet>

+                </reportSets>

+            </plugin>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-javadoc-plugin</artifactId>

+                <version>2.5</version>

+            </plugin>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-changes-plugin</artifactId>

+                <version>2.0</version>

+                <configuration>

+                    <onlyCurrentVersion>true</onlyCurrentVersion>

+                    <resolutionIds>Any</resolutionIds>

+                    <statusIds>Resolved, Closed</statusIds>

+                    <sortColumnNames>Key</sortColumnNames>

+                </configuration>

+                <reportSets>

+                    <reportSet>

+                        <reports>

+                            <report>jira-report</report>

+                        </reports>

+                    </reportSet>

+                </reportSets>

+            </plugin>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-dependency-plugin</artifactId>

+                <version>2.0</version>

+            </plugin>

+            <plugin>

+                <groupId>org.apache.maven.plugins</groupId>

+                <artifactId>maven-jxr-plugin</artifactId>

+                <version>2.1</version>

+            </plugin>

+        </plugins>

+    </reporting>

+    

+    <distributionManagement>

+        <repository>

+            <id>apache-repo</id>

+            <name>Maven Central Repository</name>

+            <url>

+                scpexe://people.apache.org/www/people.apache.org/repo/m2-ibiblio-rsync-repository

+            </url>

+        </repository>

+        <site>

+            <id>website</id>

+            <url>

+                scpexe://people.apache.org/www/ws.apache.org/wss4j/

+            </url>

+        </site>

+    </distributionManagement>

+</project>

diff --git a/trunk/project.properties b/trunk/project.properties
new file mode 100644
index 0000000..1b1218c
--- /dev/null
+++ b/trunk/project.properties
@@ -0,0 +1,9 @@
+##
+## $Revision$ $Date$
+##
+
+maven.repo.remote=http://people.apache.org/~dims/maven, http://www.ibiblio.org/maven
+maven.xdoc.date=left
+maven.xdoc.version=${pom.currentVersion}
+maven.junit.fork=true
+#maven.html2xdoc.enabled=true
diff --git a/trunk/project.xml b/trunk/project.xml
new file mode 100644
index 0000000..be6c6ce
--- /dev/null
+++ b/trunk/project.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0"?>
+
+<project>
+
+  <!-- the version of maven's project object model -->
+  <pomVersion>3</pomVersion>
+  
+  <!-- a unique name for this project -->
+  <id>wss4j</id>
+  
+  <!-- a short but descriptive name for the project -->
+  <name>Apache WSS4J</name>
+  
+  <!-- The version of the project under development, e.g.
+       1.1, 1.2, 2.0-SNAPSHOT -->
+  <currentVersion>1.5</currentVersion>
+  
+  <!-- details about the organization that 'owns' the project -->
+  <organization>
+    <name>Apache Web Services</name>
+    <url>http://ws.apache.org/</url>
+    <logo>http://ws.apache.org/images/project-logo.jpg</logo>
+  </organization>
+  
+  <!-- the year the project started -->
+  <inceptionYear>2004</inceptionYear>
+  <package>org.apache.ws</package>
+  <logo></logo>
+  <description>
+    Apache WSS4J is an implementation of the Web Services Security (WS-Security) being developed at 
+    OASIS Web Services Security TC. WSS4J is a primarily a Java library that can be used to sign and 
+    verify SOAP Messages with WS-Security information. WSS4J will use Apache Axis and Apache XML-Security 
+    projects and will be interoperable with JAX-RPC based server/clients and .NET server/clients. 
+  </description>
+  <!-- a short description of what the project does -->
+  <shortDescription>
+    WS-Security implementation for Apache Axis
+  </shortDescription>
+
+  <!-- the project home page -->
+  <url>http://ws.apache.org/wss4j/</url>
+  <issueTrackingUrl>http://issues.apache.org/jira/browse/WSS</issueTrackingUrl>
+  <siteAddress>ws.apache.org</siteAddress>
+  <siteDirectory>/wss4j/</siteDirectory>
+  <distributionSite>www.apache.org</distributionSite>
+  <distributionDirectory>//dyn/closer.cgi/ws/wss4j/</distributionDirectory>
+
+  <!-- the version control repository and http url for online access
+       the connection element has the form:
+       scm:<system>:<system specific connection string> -->
+  <repository>
+    <connection>scm:svn:http://svn.apache.org:repos/asf/webservices:wss4j/trunk</connection>
+    <developerConnection>scm:svn:http://svn.apache.org:repos/asf/webservices:wss4j/trunk</developerConnection>
+    <url>http://svn.apache.org/viewcvs.cgi/webservices/wss4j/trunk?root=Apache-SVN</url>
+  </repository>
+
+  <!-- any mailing lists for the project -->
+    <mailingLists>
+        <mailingList>
+            <name>WSS4J Developer List</name>
+            <subscribe>wss4j-dev-subscribe@ws.apache.org</subscribe>
+            <unsubscribe>wss4j-dev-unsubscribe@ws.apache.org</unsubscribe>
+            <archive>http://mail-archives.apache.org/mod_mbox/ws-wss4j-dev/</archive>
+        </mailingList>
+    </mailingLists>
+  
+  <!-- who the developers are for the project -->
+  <developers>
+        <developer>
+            <name>Davanum Srinivas</name>
+            <id>dims</id>
+            <email>dims@yahoo.com</email>
+            <organization></organization>
+        </developer>
+        <developer>
+            <name>Werner Dittmann</name>
+            <id>werner</id>
+            <email>werner@apache.org</email>
+            <organization></organization>
+        </developer>
+        <developer>
+            <name>Ias</name>
+            <id>ias</id>
+            <email>ias@apache.org</email>
+            <organization></organization>
+        </developer>
+        <developer>
+            <name>Ruchith Fernando</name>
+            <id>ruchithf</id>
+            <email>ruchithf@apache.org</email>
+            <organization></organization>
+        </developer>
+  </developers>
+
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+  
+  <!-- build information for the project -->
+  <build>
+    <nagEmailAddress>wss4j-dev@ws.apache.org</nagEmailAddress>
+    <sourceDirectory>src</sourceDirectory>
+    <unitTestSourceDirectory>test</unitTestSourceDirectory>
+
+    <unitTest>
+      <includes>
+        <include>**/*PackageTests*.java</include>
+      </includes>
+      <excludes>
+          <exclude>**/wssec/PackageTests.java</exclude>
+          <exclude>**/interop/PackageTests.java</exclude>
+          <exclude>**/TestScenario7.java</exclude>
+      </excludes>
+    </unitTest>
+
+    <resources>
+      <resource>
+        <directory>src</directory>
+        <includes>
+          <include>**/*.properties</include>
+        </includes>
+      </resource>
+    </resources>
+  </build>
+
+    <!-- ============ -->
+    <!-- Dependencies -->
+    <!-- ============ -->
+
+    <dependencies>
+
+        <!-- Module Dependencies -->
+        <!--
+        <dependency>
+            <groupId>axis</groupId>
+            <artifactId>axis</artifactId>
+            <version>SNAPSHOT</version>
+            <properties>
+                <module>true</module>
+            </properties>
+        </dependency>
+        <dependency>
+            <groupId>axis</groupId>
+            <artifactId>commons-discovery</artifactId>
+            <version>SNAPSHOT</version>
+            <properties>
+                <module>true</module>
+            </properties>
+        </dependency>
+        <dependency>
+            <groupId>axis</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>SNAPSHOT</version>
+            <properties>
+                <module>true</module>
+            </properties>
+        </dependency>
+        <dependency>
+            <groupId>axis</groupId>
+            <artifactId>jaxrpc</artifactId>
+            <version>SNAPSHOT</version>
+            <properties>
+                <module>true</module>
+            </properties>
+        </dependency>
+        <dependency>
+            <groupId>axis</groupId>
+            <artifactId>saaj</artifactId>
+            <version>SNAPSHOT</version>
+            <properties>
+                <module>true</module>
+            </properties>
+        </dependency>
+        <dependency>
+            <groupId>axis</groupId>
+            <artifactId>wsdl4j</artifactId>
+            <version>SNAPSHOT</version>
+            <properties>
+                <module>true</module>
+            </properties>
+        </dependency>
+        -->
+    </dependencies>
+
+    <!-- ======= -->
+    <!-- Reports -->
+    <!-- ======= -->
+
+    <reports>
+        <report>maven-license-plugin</report>
+        <report>maven-checkstyle-plugin</report>
+        <report>maven-pmd-plugin</report>
+        <report>maven-jdepend-plugin</report>
+        <!--<report>maven-changelog-plugin</report> -->
+        <!-- <report>maven-statcvs-plugin</report> -->
+        <!-- <report>maven-file-activity-plugin</report> -->
+        <!-- <report>maven-developer-activity-plugin</report> -->
+        <report>maven-jxr-plugin</report>
+        <report>maven-javadoc-plugin</report>
+        <!-- <report>maven-junit-report-plugin</report> -->
+        <!-- <report>maven-clover-plugin</report> -->
+    </reports>
+    
+</project>
+
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/NStoPkg.properties b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/NStoPkg.properties
new file mode 100644
index 0000000..60245df
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/NStoPkg.properties
@@ -0,0 +1 @@
+uri\:axis_sec=org.apache.ws.axis.samples.wssec.doall.axisSec
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/PWCallback.java b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/PWCallback.java
new file mode 100644
index 0000000..8224512
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/PWCallback.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/**
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com)
+ */
+
+package org.apache.ws.axis.samples.wssec.doall;
+
+import org.apache.ws.security.WSPasswordCallback;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+public class PWCallback implements CallbackHandler {
+
+    /* (non-Javadoc)
+     * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
+     */
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(
+                    callbacks[i],
+                    "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/Tester.java b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/Tester.java
new file mode 100644
index 0000000..f446cc2
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/Tester.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.samples.wssec.doall;
+
+import org.apache.axis.utils.Options;
+import org.apache.ws.axis.samples.wssec.doall.axisSec.SecPort;
+import org.apache.ws.axis.samples.wssec.doall.axisSec.SecServiceLocator;
+
+
+public class Tester
+{
+
+    private static final java.lang.String address =
+    "http://localhost:8081/axis/services/SecHttp";
+
+
+    public static void main(String [] args) throws Exception {
+        Options opts = new Options(args);
+
+        /*
+          * Start to prepare service call. Once this is done, several
+          * calls can be made on the port (see below)
+         *
+          * Fist: get the service locator. This implements the functionality
+          * to get a client stub (aka port).
+          */
+        SecServiceLocator service = new SecServiceLocator();
+        /* 
+          * this is a JAX-RPC compliant call. It uses a preconfigured
+          * endpoint address (usually contained in the WSDL). Note the
+          * cast.
+          *
+        SecPort port = (SwaPort)service.getPort(SwaPortType.class);
+         */
+
+        /*
+          * Here we use an Axis specific call that allows to override the
+          * port address (service endpoint address) with an own URL. Comes
+          * in handy for testing.
+          */
+        java.net.URL endpoint;
+            try {
+                endpoint = new java.net.URL(address);
+            }
+            catch (java.net.MalformedURLException e) {
+                throw new javax.xml.rpc.ServiceException(e);
+            }
+
+        SecPort port = (SecPort)service.getSecHttp(endpoint);
+        /*
+          * At this point all preparations are done. Using the port we can
+          * now perform as many calls as necessary.
+          */
+    
+         // perform call
+        String result = port.secSend("AppName");
+        System.out.println(result);
+        
+        if (opts.isFlagSet('t') > 0) {
+            long startTime = System.currentTimeMillis();
+            for (int i = 0; i < 20; i++)
+                port.secSend("AppName");
+            long endTime = System.currentTimeMillis();
+            System.out.println("Time used: " + (endTime - startTime) + "ms");
+        }
+    }
+}
\ No newline at end of file
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecBindingImpl.java b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecBindingImpl.java
new file mode 100644
index 0000000..6e3173a
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecBindingImpl.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/**
+ * SecBindingImpl.java
+ *
+ * This file was auto-generated from WSDL
+ * by the Apache Axis 1.2dev Oct 27, 2003 (02:34:09 EST) WSDL2Java emitter.
+ */
+
+package org.apache.ws.axis.samples.wssec.doall.axisSec;
+
+public class SecBindingImpl implements org.apache.ws.axis.samples.wssec.doall.axisSec.SecPort{
+    public java.lang.String secSend(java.lang.String applicationName) throws java.rmi.RemoteException {
+        return applicationName;
+    }
+
+}
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecBindingStub.java b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecBindingStub.java
new file mode 100644
index 0000000..554f705
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecBindingStub.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/**
+ * SecBindingStub.java
+ *
+ * This file was auto-generated from WSDL
+ * by the Apache Axis 1.2dev Oct 27, 2003 (02:34:09 EST) WSDL2Java emitter.
+ */
+
+package org.apache.ws.axis.samples.wssec.doall.axisSec;
+
+public class SecBindingStub extends org.apache.axis.client.Stub implements org.apache.ws.axis.samples.wssec.doall.axisSec.SecPort {
+    private java.util.Vector cachedSerClasses = new java.util.Vector();
+    private java.util.Vector cachedSerQNames = new java.util.Vector();
+    private java.util.Vector cachedSerFactories = new java.util.Vector();
+    private java.util.Vector cachedDeserFactories = new java.util.Vector();
+
+    static org.apache.axis.description.OperationDesc [] _operations;
+
+    static {
+        _operations = new org.apache.axis.description.OperationDesc[1];
+        _initOperationDesc1();
+    }
+
+    private static void _initOperationDesc1(){
+        org.apache.axis.description.OperationDesc oper;
+        oper = new org.apache.axis.description.OperationDesc();
+        oper.setName("secSend");
+        oper.addParameter(new javax.xml.namespace.QName("", "applicationName"), new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"), java.lang.String.class, org.apache.axis.description.ParameterDesc.IN, false, false);
+        oper.setReturnType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
+        oper.setReturnClass(java.lang.String.class);
+        oper.setReturnQName(new javax.xml.namespace.QName("", "return"));
+        oper.setStyle(org.apache.axis.constants.Style.RPC);
+        oper.setUse(org.apache.axis.constants.Use.LITERAL);
+        _operations[0] = oper;
+
+    }
+
+    public SecBindingStub() throws org.apache.axis.AxisFault {
+         this(null);
+    }
+
+    public SecBindingStub(java.net.URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
+         this(service);
+         super.cachedEndpoint = endpointURL;
+    }
+
+    public SecBindingStub(javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
+        if (service == null) {
+            super.service = new org.apache.axis.client.Service();
+        } else {
+            super.service = service;
+        }
+    }
+
+    private org.apache.axis.client.Call createCall() throws java.rmi.RemoteException {
+        try {
+            org.apache.axis.client.Call _call =
+                    (org.apache.axis.client.Call) super.service.createCall();
+            if (super.maintainSessionSet) {
+                _call.setMaintainSession(super.maintainSession);
+            }
+            if (super.cachedUsername != null) {
+                _call.setUsername(super.cachedUsername);
+            }
+            if (super.cachedPassword != null) {
+                _call.setPassword(super.cachedPassword);
+            }
+            if (super.cachedEndpoint != null) {
+                _call.setTargetEndpointAddress(super.cachedEndpoint);
+            }
+            if (super.cachedTimeout != null) {
+                _call.setTimeout(super.cachedTimeout);
+            }
+            if (super.cachedPortName != null) {
+                _call.setPortName(super.cachedPortName);
+            }
+            java.util.Enumeration keys = super.cachedProperties.keys();
+            while (keys.hasMoreElements()) {
+                java.lang.String key = (java.lang.String) keys.nextElement();
+                _call.setProperty(key, super.cachedProperties.get(key));
+            }
+            return _call;
+        }
+        catch (java.lang.Throwable t) {
+            throw new org.apache.axis.AxisFault("Failure trying to get the Call object", t);
+        }
+    }
+
+    public java.lang.String secSend(java.lang.String applicationName) throws java.rmi.RemoteException {
+        if (super.cachedEndpoint == null) {
+            throw new org.apache.axis.NoEndPointException();
+        }
+        org.apache.axis.client.Call _call = createCall();
+        _call.setOperation(_operations[0]);
+        _call.setUseSOAPAction(true);
+        _call.setSOAPActionURI("secSend");
+        _call.setEncodingStyle(null);
+        _call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
+        _call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
+        _call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
+        _call.setOperationName(new javax.xml.namespace.QName("", "secSend"));
+
+        setRequestHeaders(_call);
+        setAttachments(_call);
+        java.lang.Object _resp = _call.invoke(new java.lang.Object[] {applicationName});
+
+        if (_resp instanceof java.rmi.RemoteException) {
+            throw (java.rmi.RemoteException)_resp;
+        }
+        else {
+            extractAttachments(_call);
+            try {
+                return (java.lang.String) _resp;
+            } catch (java.lang.Exception _exception) {
+                return (java.lang.String) org.apache.axis.utils.JavaUtils.convert(_resp, java.lang.String.class);
+            }
+        }
+    }
+
+}
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecPort.java b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecPort.java
new file mode 100644
index 0000000..c4876be
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecPort.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/**
+ * SecPort.java
+ *
+ * This file was auto-generated from WSDL
+ * by the Apache Axis 1.2dev Oct 27, 2003 (02:34:09 EST) WSDL2Java emitter.
+ */
+
+package org.apache.ws.axis.samples.wssec.doall.axisSec;
+
+public interface SecPort extends java.rmi.Remote {
+    public java.lang.String secSend(java.lang.String applicationName) throws java.rmi.RemoteException;
+}
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecService.java b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecService.java
new file mode 100644
index 0000000..bf4711b
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecService.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/**
+ * SecService.java
+ *
+ * This file was auto-generated from WSDL
+ * by the Apache Axis 1.2dev Oct 27, 2003 (02:34:09 EST) WSDL2Java emitter.
+ */
+
+package org.apache.ws.axis.samples.wssec.doall.axisSec;
+
+public interface SecService extends javax.xml.rpc.Service {
+    public java.lang.String getSecHttpAddress();
+
+    public org.apache.ws.axis.samples.wssec.doall.axisSec.SecPort getSecHttp() throws javax.xml.rpc.ServiceException;
+
+    public org.apache.ws.axis.samples.wssec.doall.axisSec.SecPort getSecHttp(java.net.URL portAddress) throws javax.xml.rpc.ServiceException;
+}
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecServiceLocator.java b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecServiceLocator.java
new file mode 100644
index 0000000..a010d90
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/SecServiceLocator.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/**
+ * SecServiceLocator.java
+ *
+ * This file was auto-generated from WSDL
+ * by the Apache Axis 1.2dev Oct 27, 2003 (02:34:09 EST) WSDL2Java emitter.
+ */
+
+package org.apache.ws.axis.samples.wssec.doall.axisSec;
+
+public class SecServiceLocator extends org.apache.axis.client.Service implements org.apache.ws.axis.samples.wssec.doall.axisSec.SecService {
+
+    // Use to get a proxy class for SecHttp
+    private java.lang.String SecHttp_address = "http://localhost:8081/axis/services/secHttp";
+
+    public java.lang.String getSecHttpAddress() {
+        return SecHttp_address;
+    }
+
+    // The WSDD service name defaults to the port name.
+    private java.lang.String SecHttpWSDDServiceName = "SecHttp";
+
+    public java.lang.String getSecHttpWSDDServiceName() {
+        return SecHttpWSDDServiceName;
+    }
+
+    public void setSecHttpWSDDServiceName(java.lang.String name) {
+        SecHttpWSDDServiceName = name;
+    }
+
+    public org.apache.ws.axis.samples.wssec.doall.axisSec.SecPort getSecHttp() throws javax.xml.rpc.ServiceException {
+       java.net.URL endpoint;
+        try {
+            endpoint = new java.net.URL(SecHttp_address);
+        }
+        catch (java.net.MalformedURLException e) {
+            throw new javax.xml.rpc.ServiceException(e);
+        }
+        return getSecHttp(endpoint);
+    }
+
+    public org.apache.ws.axis.samples.wssec.doall.axisSec.SecPort getSecHttp(java.net.URL portAddress) throws javax.xml.rpc.ServiceException {
+        try {
+            org.apache.ws.axis.samples.wssec.doall.axisSec.SecBindingStub _stub = new org.apache.ws.axis.samples.wssec.doall.axisSec.SecBindingStub(portAddress, this);
+            _stub.setPortName(getSecHttpWSDDServiceName());
+            return _stub;
+        }
+        catch (org.apache.axis.AxisFault e) {
+            return null;
+        }
+    }
+
+    public void setSecHttpEndpointAddress(java.lang.String address) {
+        SecHttp_address = address;
+    }
+
+    /**
+     * For the given interface, get the stub implementation.
+     * If this service has no port for the given interface,
+     * then ServiceException is thrown.
+     */
+    public java.rmi.Remote getPort(Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
+        try {
+            if (org.apache.ws.axis.samples.wssec.doall.axisSec.SecPort.class.isAssignableFrom(serviceEndpointInterface)) {
+                org.apache.ws.axis.samples.wssec.doall.axisSec.SecBindingStub _stub = new org.apache.ws.axis.samples.wssec.doall.axisSec.SecBindingStub(new java.net.URL(SecHttp_address), this);
+                _stub.setPortName(getSecHttpWSDDServiceName());
+                return _stub;
+            }
+        }
+        catch (java.lang.Throwable t) {
+            throw new javax.xml.rpc.ServiceException(t);
+        }
+        throw new javax.xml.rpc.ServiceException("There is no stub implementation for the interface:  " + (serviceEndpointInterface == null ? "null" : serviceEndpointInterface.getName()));
+    }
+
+    /**
+     * For the given interface, get the stub implementation.
+     * If this service has no port for the given interface,
+     * then ServiceException is thrown.
+     */
+    public java.rmi.Remote getPort(javax.xml.namespace.QName portName, Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
+        if (portName == null) {
+            return getPort(serviceEndpointInterface);
+        }
+        String inputPortName = portName.getLocalPart();
+        if ("SecHttp".equals(inputPortName)) {
+            return getSecHttp();
+        }
+        else  {
+            java.rmi.Remote _stub = getPort(serviceEndpointInterface);
+            ((org.apache.axis.client.Stub) _stub).setPortName(portName);
+            return _stub;
+        }
+    }
+
+    public javax.xml.namespace.QName getServiceName() {
+        return new javax.xml.namespace.QName("uri:axis_sec", "secService");
+    }
+
+    private java.util.HashSet ports = null;
+
+    public java.util.Iterator getPorts() {
+        if (ports == null) {
+            ports = new java.util.HashSet();
+            ports.add(new javax.xml.namespace.QName("SecHttp"));
+        }
+        return ports.iterator();
+    }
+
+    /**
+    * Set the endpoint address for the specified port name.
+    */
+    public void setEndpointAddress(java.lang.String portName, java.lang.String address) throws javax.xml.rpc.ServiceException {
+        if ("SecHttp".equals(portName)) {
+            setSecHttpEndpointAddress(address);
+        }
+        else { // Unknown Port Name
+            throw new javax.xml.rpc.ServiceException(" Cannot set Endpoint Address for Unknown Port" + portName);
+        }
+    }
+
+    /**
+    * Set the endpoint address for the specified port name.
+    */
+    public void setEndpointAddress(javax.xml.namespace.QName portName, java.lang.String address) throws javax.xml.rpc.ServiceException {
+        setEndpointAddress(portName.getLocalPart(), address);
+    }
+
+}
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/deploy.wsdd b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/deploy.wsdd
new file mode 100644
index 0000000..ba16bc1
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/deploy.wsdd
@@ -0,0 +1,27 @@
+<!-- Use this file to deploy some handlers/chains and services      -->
+<!-- Two ways to do this:                                           -->
+<!--   java org.apache.axis.client.AdminClient deploy.wsdd          -->
+<!--      after the axis server is running                          -->
+<!-- or                                                             -->
+<!--   java org.apache.axis.utils.Admin client|server deploy.wsdd   -->
+<!--      from the same directory that the Axis engine runs         -->
+
+<deployment
+    xmlns="http://xml.apache.org/axis/wsdd/"
+    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
+
+  <!-- Services from secService WSDL service -->
+
+  <service name="SecHttp" provider="java:RPC" style="rpc" use="literal">
+      <parameter name="wsdlTargetNamespace" value="uri:axis_sec"/>
+      <parameter name="wsdlServiceElement" value="secService"/>
+      <parameter name="wsdlServicePort" value="SecHttp"/>
+      <parameter name="className" value="org.apache.ws.axis.samples.wssec.doall.axisSec.SecBindingImpl"/>
+      <parameter name="wsdlPortType" value="secPort"/>
+      <operation name="secSend" qname="secSend" returnQName="return" returnType="rtns:string" xmlns:rtns="http://www.w3.org/2001/XMLSchema" >
+        <parameter name="applicationName" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema"/>
+      </operation>
+      <parameter name="allowedMethods" value="secSend"/>
+
+  </service>
+</deployment>
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/undeploy.wsdd b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/undeploy.wsdd
new file mode 100644
index 0000000..1886f0c
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/axisSec/undeploy.wsdd
@@ -0,0 +1,15 @@
+<!-- Use this file to undeploy some handlers/chains and services    -->
+<!-- Two ways to do this:                                           -->
+<!--   java org.apache.axis.client.AdminClient undeploy.wsdd        -->
+<!--      after the axis server is running                          -->
+<!-- or                                                             -->
+<!--   java org.apache.axis.utils.Admin client|server undeploy.wsdd -->
+<!--      from the same directory that the Axis engine runs         -->
+
+<undeployment
+    xmlns="http://xml.apache.org/axis/wsdd/">
+
+  <!-- Services from secService WSDL service -->
+
+  <service name="SecHttp"/>
+</undeployment>
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/build.xml b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/build.xml
new file mode 100644
index 0000000..1977623
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/build.xml
@@ -0,0 +1,68 @@
+<project name="Axis_SecDoAll" default="wsdl2java" basedir=".">
+    <description>
+        generate files from WSDL description, also target to deploy
+        the service in a runing Axis (probably in Tomcat or alike)
+    </description>
+
+  <!-- The following setting assumes that all necessary libs (jars)
+    are located in a lib directory directly under wss4j. First set
+    a reference to the wss4j relative to this working directory -->
+  <property name="dir.wss4j" value="../../../../../../../.." />
+  <property name="dir.libs"  value="${dir.wss4j}/lib" />
+
+  <!-- Base directory where to put generated java files -->
+  <property name="WSDLGenFiles" location="${dir.wss4j}/samples" />
+  <!-- where to find the SwA WSDL files -->
+  <property name="WSDLDir" location="${basedir}" />
+
+  <!--
+   Directory of the generated Java files
+  -->
+  <property name="sec" value="org/apache/ws/axis/samples/wssec/doall/axisSec" />
+
+    <path id="classpath.libraries" description=" 3rd party and Axis libs">
+      <fileset dir="${dir.libs}">
+        <include name="**/*.jar"/>
+	<!-- <pathelement path="${java.class.path}"/> -->
+      </fileset>
+    </path>
+  
+  <target name="clientdeploy">
+    <java classname="org.apache.axis.utils.Admin" fork="true">
+      <classpath refid="classpath.libraries" />
+      <arg value="client"/>
+      <arg file="${WSDLDir}/client_deploy.wsdd" />
+    </java>
+  </target>
+
+  <target name="serverdeploy">
+    <java classname="org.apache.axis.client.AdminClient" fork="true">
+      <classpath refid="classpath.libraries" />
+      <arg file="${WSDLDir}/server_deploy.wsdd" />
+    </java>
+  </target>
+
+  <target name="serverundeploy">
+    <java classname="org.apache.axis.client.AdminClient" fork="true">
+      <classpath refid="classpath.libraries" />
+     <arg file="${WSDLGenFiles}/${sec}/undeploy.wsdd" />
+    </java>
+  </target>
+
+  <target name="wsdl2java">
+    <java classname="org.apache.axis.wsdl.WSDL2Java" fork="true">
+      <classpath refid="classpath.libraries" />
+      <arg value="-f" /> 
+      <arg file="${WSDLDir}/NStoPkg.properties" /> 
+      <arg value="-S true" />
+      <arg value="-o" />
+      <arg file="${WSDLGenFiles}" />
+      <arg file="${WSDLDir}/sec.wsdl" />
+    </java>
+  </target>
+
+  <target name="clean"
+        description="clean up" >
+    <delete dir="${WSDLGenFiles}/${sec}"/>
+  </target>
+</project>
\ No newline at end of file
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/client-config.wsdd b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/client-config.wsdd
new file mode 100644
index 0000000..5612729
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/client-config.wsdd
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
+ <service name="SecHttp">
+  <requestFlow>
+   <handler name="DoSecuritySender" type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/>
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
+    <!-- <parameter name="action" value="Signature"/> -->
+	<!-- <parameter name="action" value="Encrypt Signatur"/> -->
+    <parameter name="action" value="Signature Encrypt"/>
+    <!-- <parameter name="action" value="Encrypt"/> -->
+    <parameter name="signaturePropFile" value="crypto.properties" />
+    <!-- <parameter name="encryptionPropFile" value="crypto.properties" /> -->
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="encryptionKeyIdentifier" value="X509KeyIdentifier" />
+	<!-- <parameter name="encryptionParts" value="{Content}{http://example.org/paymentv2}CreditCard;{Element}{}UserName" /> -->
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler name="DoSecurityReceiver" type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
+    <!-- <parameter name="action" value="Signature"/> -->
+	<parameter name="action" value="Encrypt Signature"/>
+    <!-- <parameter name="action" value="Signature Encrypt"/> -->
+    <!-- <parameter name="action" value="Encrypt"/> -->
+    <parameter name="signaturePropFile" value="crypto.properties" />
+    <!-- <parameter name="decryptionPropFile" value="crypto.properties" /> -->
+   </handler>
+  </responseFlow>
+  
+ </service>
+ <transport name="java" pivot="java:org.apache.axis.transport.java.JavaSender"/>
+ <transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
+ <transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender"/>
+</deployment>
\ No newline at end of file
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/client_deploy.wsdd b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/client_deploy.wsdd
new file mode 100644
index 0000000..376b331
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/client_deploy.wsdd
@@ -0,0 +1,34 @@
+<deployment xmlns="http://xml.apache.org/axis/wsdd/"
+            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
+
+ <!-- define the service, using the WSDoAllSender security handler in request flow -->
+ <service name="SecHttp">
+  <requestFlow>
+   <handler name="DoSecuritySender" type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/>
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
+    <!-- <parameter name="action" value="Signature"/> -->
+	<!-- <parameter name="action" value="Encrypt Signatur"/> -->
+    <parameter name="action" value="Signature Encrypt"/>
+    <!-- <parameter name="action" value="Encrypt"/> -->
+    <parameter name="signaturePropFile" value="crypto.properties" />
+    <!-- <parameter name="encryptionPropFile" value="crypto.properties" /> -->
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="encryptionKeyIdentifier" value="X509KeyIdentifier" />
+	<!-- <parameter name="encryptionParts" value="{Content}{http://example.org/paymentv2}CreditCard;{Element}{}UserName" /> -->
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler name="DoSecurityReceiver" type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
+    <!-- <parameter name="action" value="Signature"/> -->
+	<parameter name="action" value="Encrypt Signature"/>
+    <!-- <parameter name="action" value="Signature Encrypt"/> -->
+    <!-- <parameter name="action" value="Encrypt"/> -->
+    <parameter name="signaturePropFile" value="crypto.properties" />
+    <!-- <parameter name="decryptionPropFile" value="crypto.properties" /> -->
+   </handler>
+  </responseFlow>
+ </service>
+
+</deployment>
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/keys/x509.PFX.MSFT b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/keys/x509.PFX.MSFT
new file mode 100644
index 0000000..98be0df
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/keys/x509.PFX.MSFT
Binary files differ
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/log4j.properties b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/log4j.properties
new file mode 100644
index 0000000..62cd524
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/log4j.properties
@@ -0,0 +1,26 @@
+# Set root category priority to INFO and its only appender to CONSOLE.
+log4j.rootCategory=FATAL, CONSOLE
+# log4j.rootCategory=DEBUG, CONSOLE, LOGFILE
+
+# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
+log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
+# log4j.logger.org.apache.axis.i18n.ProjectResourceBundle=INFO
+log4j.logger.org.apache.ws.security.TIME=DEBUG
+# log4j.logger.org.apache.ws.security.message.EnvelopeIdResolver=INFO
+# log4j.logger.org.apache.ws.axis.security.WSDoAllSender=INFO
+# log4j.logger.org.apache.ws.security.WSSecurityEngine=INFO
+# log4j.logger.org.apache.xml.security.encryption.XMLCipher=DEBUG
+
+# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.Threshold=DEBUG
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n
+
+# LOGFILE is set to be a File appender using a PatternLayout.
+log4j.appender.LOGFILE=org.apache.log4j.FileAppender
+log4j.appender.LOGFILE.File=axis.log
+log4j.appender.LOGFILE.Append=true
+log4j.appender.LOGFILE.Threshold=DEBUG
+log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
+log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/sec.wsdl b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/sec.wsdl
new file mode 100644
index 0000000..b4a2d77
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/sec.wsdl
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions name="Axis_sec"
+   targetNamespace="uri:axis_sec"
+   xmlns:swa="uri:axis_sec"
+   xmlns="http://schemas.xmlsoap.org/wsdl/"
+   xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
+   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+   >
+
+   <message name="SecRequest">
+      <part name="applicationName" type="xsd:string"/>
+   </message>
+
+   <message name="SecResponse">
+      <part name="return" type="xsd:string"/>
+   </message>
+
+   <portType name="secPort">
+      <operation name="secSend">
+         <input message="swa:SecRequest"/>
+	 <output message="swa:SecResponse"/>
+      </operation>
+   </portType>
+
+   <binding name="secBinding" type="swa:secPort">
+     <soap:binding style="rpc" transport= "http://schemas.xmlsoap.org/soap/http"/>
+     <operation name="secSend">
+       <soap:operation soapAction="secSend" />
+	   <input>
+	     <soap:body use="literal" parts="applicationName" />
+	   </input>
+	   <output>
+	    <soap:body use="literal" />
+	   </output>
+     </operation>
+   </binding>
+
+   <service name="secService">
+      <port name="SecHttp" binding="swa:secBinding">
+         <soap:address location="http://localhost:8081/axis/services/secHttp"/>
+      </port>
+   </service>
+</definitions>
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/server-config.wsdd b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/server-config.wsdd
new file mode 100644
index 0000000..7680f9e
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/server-config.wsdd
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
+ <globalConfiguration>
+  <parameter name="adminPassword" value="admin"/>
+  <parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl"/>
+  <parameter name="sendXsiTypes" value="true"/>
+  <parameter name="sendMultiRefs" value="true"/>
+  <parameter name="sendXMLDeclaration" value="true"/>
+  <requestFlow>
+   <handler type="java:org.apache.axis.handlers.JWSHandler">
+    <parameter name="scope" value="session"/>
+   </handler>
+   <handler type="java:org.apache.axis.handlers.JWSHandler">
+    <parameter name="scope" value="request"/>
+    <parameter name="extension" value=".jwr"/>
+   </handler>
+  </requestFlow>
+ </globalConfiguration>
+ <handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
+ <handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
+ <handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>
+ <service name="SecHttp" provider="java:RPC" use="literal">
+  <operation name="secSend" qname="secSend" returnQName="return" returnType="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+   <parameter name="applicationName" type="xsd:string"/>
+  </operation>
+  <requestFlow>
+   <handler name="DoSecurityReceiver" type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
+    <!-- <parameter name="action" value="Signature"/> -->
+	<!-- <parameter name="action" value="Encrypt Signature"/> -->
+    <parameter name="action" value="Signature Encrypt"/>
+    <!-- <parameter name="action" value="Encrypt"/> -->
+    <parameter name="signaturePropFile" value="crypto.properties" />
+    <!-- <parameter name="decryptionPropFile" value="crypto.properties" /> -->
+   </handler>
+  </requestFlow>
+  <responseFlow>
+   <handler name="DoSecuritySender" type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/>
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
+    <!-- <parameter name="action" value="Signature"/> -->
+	<parameter name="action" value="Encrypt Signature"/>
+    <!-- <parameter name="action" value="Signature Encrypt"/> -->
+    <!-- <parameter name="action" value="Encrypt"/> -->
+    <parameter name="signaturePropFile" value="crypto.properties" />
+    <!-- <parameter name="encryptionPropFile" value="crypto.properties" /> -->
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="encryptionKeyIdentifier" value="X509KeyIdentifier" />
+   </handler>
+  
+  </responseFlow>
+  <parameter name="allowedMethods" value="secSend"/>
+  <parameter name="wsdlPortType" value="secPort"/>
+  <parameter name="className" value="org.apache.ws.axis.samples.wssec.doall.axisSec.SecBindingImpl"/>
+  <parameter name="wsdlServicePort" value="SecHttp"/>
+  <parameter name="wsdlTargetNamespace" value="uri:axis_sec"/>
+  <parameter name="wsdlServiceElement" value="secService"/>
+ </service>
+ <service name="AdminService" provider="java:MSG">
+  <parameter name="allowedMethods" value="AdminService"/>
+  <parameter name="enableRemoteAdmin" value="false"/>
+  <parameter name="className" value="org.apache.axis.utils.Admin"/>
+  <namespace>http://xml.apache.org/axis/wsdd/</namespace>
+ </service>
+ <service name="Version" provider="java:RPC">
+  <parameter name="allowedMethods" value="getVersion"/>
+  <parameter name="className" value="org.apache.axis.Version"/>
+ </service>
+ <transport name="http">
+  <requestFlow>
+   <handler type="URLMapper"/>
+   <handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
+  </requestFlow>
+  <parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler"/>
+  <parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler"/>
+  <parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler"/>
+ </transport>
+ <transport name="local">
+  <responseFlow>
+   <handler type="LocalResponder"/>
+  </responseFlow>
+ </transport>
+</deployment>
\ No newline at end of file
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/server_deploy.wsdd b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/server_deploy.wsdd
new file mode 100644
index 0000000..405db38
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/server_deploy.wsdd
@@ -0,0 +1,51 @@
+<!-- Use this file to deploy some handlers/chains and services      -->
+<!-- Two ways to do this:                                           -->
+<!--   java org.apache.axis.client.AdminClient deploy.wsdd          -->
+<!--      after the axis server is running                          -->
+<!-- or                                                             -->
+<!--   java org.apache.axis.utils.Admin client|server deploy.wsdd   -->
+<!--      from the same directory that the Axis engine runs         -->
+
+<deployment
+    xmlns="http://xml.apache.org/axis/wsdd/"
+    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
+
+  <!-- Services from secService WSDL service -->
+
+  <service name="SecHttp" provider="java:RPC" style="rpc" use="literal">
+    <parameter name="wsdlTargetNamespace" value="uri:axis_sec"/>
+    <parameter name="wsdlServiceElement" value="secService"/>
+    <parameter name="wsdlServicePort" value="SecHttp"/>
+    <parameter name="className" value="org.apache.ws.axis.samples.wssec.doall.axisSec.SecBindingImpl"/>
+    <parameter name="wsdlPortType" value="secPort"/>
+    <operation name="secSend" qname="secSend" returnQName="return" returnType="rtns:string" xmlns:rtns="http://www.w3.org/2001/XMLSchema" >
+      <parameter name="applicationName" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema"/>
+    </operation>
+    <parameter name="allowedMethods" value="secSend"/>
+    <requestFlow>
+      <handler name="DoSecurityReceiver" type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+       <parameter name="passwordCallbackClass" value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
+       <!-- <parameter name="action" value="Signature"/> -->
+	   <!-- <parameter name="action" value="Encrypt Signature"/> -->
+       <parameter name="action" value="Signature Encrypt"/>
+       <!-- <parameter name="action" value="Encrypt"/> -->
+       <parameter name="signaturePropFile" value="crypto.properties" />
+       <!-- <parameter name="decryptionPropFile" value="crypto.properties" /> -->
+	  </handler>
+ 	</requestFlow>
+  <responseFlow>
+   <handler name="DoSecuritySender" type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    <parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/>
+    <parameter name="passwordCallbackClass" value="org.apache.ws.axis.samples.wssec.doall.PWCallback"/>
+    <!-- <parameter name="action" value="Signature"/> -->
+	<parameter name="action" value="Encrypt Signature"/>
+    <!-- <parameter name="action" value="Signature Encrypt"/> -->
+    <!-- <parameter name="action" value="Encrypt"/> -->
+    <parameter name="signaturePropFile" value="crypto.properties" />
+    <!-- <parameter name="encryptionPropFile" value="crypto.properties" /> -->
+    <parameter name="signatureKeyIdentifier" value="DirectReference" />
+    <parameter name="encryptionKeyIdentifier" value="X509KeyIdentifier" />
+   </handler>
+  </responseFlow>
+  </service>
+</deployment>
diff --git a/trunk/samples/org/apache/ws/axis/samples/wssec/doall/simplelog.properties b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/simplelog.properties
new file mode 100644
index 0000000..79794d5
--- /dev/null
+++ b/trunk/samples/org/apache/ws/axis/samples/wssec/doall/simplelog.properties
@@ -0,0 +1,2 @@
+org.apache.commons.logging.simplelog.defaultlog=debug
+
diff --git a/trunk/specs/WSS-SAML-TOKEN-PROFILE-1.1-wd-04-change-bars.pdf b/trunk/specs/WSS-SAML-TOKEN-PROFILE-1.1-wd-04-change-bars.pdf
new file mode 100644
index 0000000..0567d6d
--- /dev/null
+++ b/trunk/specs/WSS-SAML-TOKEN-PROFILE-1.1-wd-04-change-bars.pdf
Binary files differ
diff --git a/trunk/specs/WSS-SAML-TOKEN-PROFILE-1.1-wd-04.pdf b/trunk/specs/WSS-SAML-TOKEN-PROFILE-1.1-wd-04.pdf
new file mode 100644
index 0000000..ef05284
--- /dev/null
+++ b/trunk/specs/WSS-SAML-TOKEN-PROFILE-1.1-wd-04.pdf
Binary files differ
diff --git a/trunk/specs/oasis-2005xx-wss-kerberos-token-profile-1.1-CD.pdf b/trunk/specs/oasis-2005xx-wss-kerberos-token-profile-1.1-CD.pdf
new file mode 100644
index 0000000..497fa04
--- /dev/null
+++ b/trunk/specs/oasis-2005xx-wss-kerberos-token-profile-1.1-CD.pdf
Binary files differ
diff --git a/trunk/specs/oasis-2005xx-wss-soap-message-security-diffedfrom10.pdf b/trunk/specs/oasis-2005xx-wss-soap-message-security-diffedfrom10.pdf
new file mode 100644
index 0000000..ed01be6
--- /dev/null
+++ b/trunk/specs/oasis-2005xx-wss-soap-message-security-diffedfrom10.pdf
Binary files differ
diff --git a/trunk/specs/oasis-2005xx-wss-username-token-profile-1.1-CD.pdf b/trunk/specs/oasis-2005xx-wss-username-token-profile-1.1-CD.pdf
new file mode 100644
index 0000000..cf1b9f9
--- /dev/null
+++ b/trunk/specs/oasis-2005xx-wss-username-token-profile-1.1-CD.pdf
Binary files differ
diff --git a/trunk/specs/oasis-2005xx-wss-username-token-profile-diffedfrom10.pdf b/trunk/specs/oasis-2005xx-wss-username-token-profile-diffedfrom10.pdf
new file mode 100644
index 0000000..0220461
--- /dev/null
+++ b/trunk/specs/oasis-2005xx-wss-username-token-profile-diffedfrom10.pdf
Binary files differ
diff --git a/trunk/specs/oasis-2005xx-wss-x509-token-profile-1.1-CD.pdf b/trunk/specs/oasis-2005xx-wss-x509-token-profile-1.1-CD.pdf
new file mode 100644
index 0000000..9b8c878
--- /dev/null
+++ b/trunk/specs/oasis-2005xx-wss-x509-token-profile-1.1-CD.pdf
Binary files differ
diff --git a/trunk/specs/oasis-2005xx-wss-x509-token-profile-diffedfrom10.pdf b/trunk/specs/oasis-2005xx-wss-x509-token-profile-diffedfrom10.pdf
new file mode 100644
index 0000000..342e8db
--- /dev/null
+++ b/trunk/specs/oasis-2005xx-wss-x509-token-profile-diffedfrom10.pdf
Binary files differ
diff --git a/trunk/specs/oasis-wss-rel-token-profile-1.1-draft02-cd.pdf b/trunk/specs/oasis-wss-rel-token-profile-1.1-draft02-cd.pdf
new file mode 100644
index 0000000..8b59a30
--- /dev/null
+++ b/trunk/specs/oasis-wss-rel-token-profile-1.1-draft02-cd.pdf
Binary files differ
diff --git a/trunk/specs/wss-11-interop-draft-01.doc b/trunk/specs/wss-11-interop-draft-01.doc
new file mode 100644
index 0000000..d186e33
--- /dev/null
+++ b/trunk/specs/wss-11-interop-draft-01.doc
Binary files differ
diff --git a/trunk/specs/wss-interop1-draft-06.pdf b/trunk/specs/wss-interop1-draft-06.pdf
new file mode 100644
index 0000000..3fe7d3d
--- /dev/null
+++ b/trunk/specs/wss-interop1-draft-06.pdf
Binary files differ
diff --git a/trunk/specs/wss-interop2-draft-06.pdf b/trunk/specs/wss-interop2-draft-06.pdf
new file mode 100644
index 0000000..875c5d4
--- /dev/null
+++ b/trunk/specs/wss-interop2-draft-06.pdf
Binary files differ
diff --git a/trunk/specs/wss-saml-interop1-draft-12.doc b/trunk/specs/wss-saml-interop1-draft-12.doc
new file mode 100644
index 0000000..40ec340
--- /dev/null
+++ b/trunk/specs/wss-saml-interop1-draft-12.doc
Binary files differ
diff --git a/trunk/specs/wss-saml2-interop-draft-v4.doc b/trunk/specs/wss-saml2-interop-draft-v4.doc
new file mode 100644
index 0000000..64573e2
--- /dev/null
+++ b/trunk/specs/wss-saml2-interop-draft-v4.doc
Binary files differ
diff --git a/trunk/specs/wss-swa-profile-1.1-draft-22.pdf b/trunk/specs/wss-swa-profile-1.1-draft-22.pdf
new file mode 100644
index 0000000..7d69679
--- /dev/null
+++ b/trunk/specs/wss-swa-profile-1.1-draft-22.pdf
Binary files differ
diff --git a/trunk/specs/wss-v1.1-spec-os-SOAPMessageSecurity.pdf b/trunk/specs/wss-v1.1-spec-os-SOAPMessageSecurity.pdf
new file mode 100644
index 0000000..a22598c
--- /dev/null
+++ b/trunk/specs/wss-v1.1-spec-os-SOAPMessageSecurity.pdf
Binary files differ
diff --git a/trunk/src/log4j.properties b/trunk/src/log4j.properties
new file mode 100644
index 0000000..ff934a7
--- /dev/null
+++ b/trunk/src/log4j.properties
@@ -0,0 +1,74 @@
+# Set root category priority to INFO and its only appender to CONSOLE.
+log4j.rootCategory=FATAL, CONSOLE
+# log4j.rootCategory=DEBUG, LOGFILE
+
+# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
+# log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
+# log4j.logger.org.apache.axis.i18n.ProjectResourceBundle=INFO
+# log4j.logger.org.apache.ws.security.TIME=DEBUG
+# log4j.logger.org.apache.ws.security.message.EnvelopeIdResolver=DEBUG
+# log4j.logger.org.apache.ws.security.message.WSEncryptBody=INFO
+# log4j.logger.org.apache.ws.security.message.WSSignEnvelope=DEBUG
+# log4j.logger.org.apache.ws.security.processor.ReferenceListProcessor=DEBUG
+# log4j.logger.org.apache.ws.axis.security.WSDoAllSender=DEBUG
+# log4j.logger.org.apache.ws.axis.security.WSDoAllReceiver=DEBUG
+# log4j.logger.org.apache.ws.security.transform.STRTransform=DEBUG
+# log4j.logger.org.apache.ws.security.WSSecurityEngine=DEBUG
+# log4j.logger.org.apache.ws.security.WSSConfig=DEBUG
+# log4j.logger.org.apache.ws.security.message.token.SecurityTokenReference=DEBUG
+# log4j.logger.org.apache.ws.security.components.crypto.Merlin=DEBUG
+# log4j.logger.org.apache.xml.security.encryption.XMLCipher=DEBUG
+# log4j.logger.org.apache.xml.security.algorithms.SignatureAlgorithm=INFO
+# log4j.logger.org.apache.xml.security.signature.XMLSignature=DEBUG
+# log4j.logger.org.apache.xml.security.Init=INFO
+# log4j.logger.org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory=INFO
+# log4j.logger.org.apache.axis.i18n.ProjectResourceBundle=INFO
+# log4j.logger.org.apache.axis.utils.NSStack=INFO
+# log4j.logger.org.apache.axis.encoding.SerializationContextImpl=INFO
+# log4j.logger.org.apache.axis.encoding.DeserializationContextImpl=INFO
+# log4j.logger.org.apache.xml.security.signature.Reference=DEBUG
+# log4j.logger.wssec.TestWSSecurity=DEBUG
+# log4j.logger.wssec.TestWSSecurityNew=DEBUG
+# log4j.logger.wssec.TestWSSecurity1=DEBUG
+# log4j.logger.wssec.TestWSSecurity2=DEBUG
+# log4j.logger.wssec.TestWSSecurityNew2=DEBUG
+# log4j.logger.wssec.TestWSSecurity3=DEBUG
+# log4j.logger.wssec.TestWSSecurity4=DEBUG
+# log4j.logger.wssec.TestWSSecurity5=DEBUG
+# log4j.logger.wssec.TestWSSecurityNew5=DEBUG
+# log4j.logger.wssec.TestWSSecurity6=DEBUG
+# log4j.logger.wssec.TestWSSecurity7=DEBUG
+# log4j.logger.wssec.TestWSSecurity8=DEBUG
+# log4j.logger.wssec.TestWSSecurity9=DEBUG
+# log4j.logger.wssec.TestWSSecurityNew9=DEBUG
+# log4j.logger.wssec.TestWSSecurity10=DEBUG
+# log4j.logger.wssec.TestWSSecurity11=DEBUG
+# log4j.logger.wssec.TestWSSecurity12=DEBUG
+# log4j.logger.wssec.TestWSSecurity13=DEBUG
+# log4j.logger.wssec.TestWSSecurity14=DEBUG
+# log4j.logger.wssec.TestWSSecurityNew15=DEBUG
+# log4j.logger.wssec.TestWSSecurityST1=DEBUG
+# log4j.logger.wssec.TestWSSecurityNewST1=DEBUG
+# log4j.logger.wssec.TestWSSecurityST2=DEBUG
+# log4j.logger.wssec.TestWSSecurityNewST2=DEBUG
+# log4j.logger.wssec.TestWSSecurityST3=DEBUG
+# log4j.logger.wssec.TestWSSecurityNewST3=DEBUG
+# log4j.logger.wssec.TestWSSecuritySOAP12=DEBUG
+# log4j.logger.org.apache.ws.security.handler.WSS4JHandler=DEBUG
+# log4j.logger.org.apache.ws.security.handler.WSHandler=DEBUG
+log4j.logger.policy.WSSPolicyTesterAsymm=DEBUG
+log4j.logger.org.apache.ws.security.policy.parser.WSSPolicyProcessor=ERROR
+
+# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.Threshold=DEBUG
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n
+
+# LOGFILE is set to be a File appender using a PatternLayout.
+log4j.appender.LOGFILE=org.apache.log4j.FileAppender
+log4j.appender.LOGFILE.File=axis.log
+log4j.appender.LOGFILE.Append=true
+log4j.appender.LOGFILE.Threshold=DEBUG
+log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
+log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
diff --git a/trunk/src/org/apache/ws/axis/security/WSDoAllReceiver.java b/trunk/src/org/apache/ws/axis/security/WSDoAllReceiver.java
new file mode 100644
index 0000000..fc7fa0e
--- /dev/null
+++ b/trunk/src/org/apache/ws/axis/security/WSDoAllReceiver.java
@@ -0,0 +1,367 @@
+/*
+* Copyright  2003-2005 The Apache Software Foundation.
+*
+*  Licensed 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.ws.axis.security;
+
+/**
+ * @author Werner Dittmann (werner@apache.org)
+ *
+ */
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.SOAPPart;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.axis.security.handler.WSDoAllHandler;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.handler.WSHandlerResult;
+import org.apache.ws.security.message.token.Timestamp;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.utils.XMLUtils;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPHeader;
+import javax.xml.soap.SOAPHeaderElement;
+import java.io.ByteArrayOutputStream;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+
+public class WSDoAllReceiver extends WSDoAllHandler {
+
+    protected static Log log = LogFactory.getLog(WSDoAllReceiver.class.getName());
+    private static Log tlog =
+        LogFactory.getLog("org.apache.ws.security.TIME");
+
+    /**
+     * Axis calls invoke to handle a message.
+     * <p/>
+     *
+     * @param msgContext message context.
+     * @throws AxisFault
+     */
+    public void invoke(MessageContext msgContext) throws AxisFault {
+
+        boolean doDebug = log.isDebugEnabled();
+
+        if (doDebug) {
+            log.debug("WSDoAllReceiver: enter invoke() with msg type: "
+                    + msgContext.getCurrentMessage().getMessageType());
+        }
+        long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
+        if (tlog.isDebugEnabled()) {
+            t0 = System.currentTimeMillis();
+        }        
+
+        RequestData reqData = new RequestData();
+        /*
+        * The overall try, just to have a finally at the end to perform some
+        * housekeeping.
+        */
+        try {
+            reqData.setMsgContext(msgContext);
+
+            Vector actions = new Vector();
+            String action = null;
+            if ((action = (String) getOption(WSHandlerConstants.ACTION)) == null) {
+                action = (String) msgContext
+                        .getProperty(WSHandlerConstants.ACTION);
+            }
+            if (action == null) {
+                throw new AxisFault("WSDoAllReceiver: No action defined");
+            }
+            int doAction = WSSecurityUtil.decodeAction(action, actions);
+
+            String actor = (String) getOption(WSHandlerConstants.ACTOR);
+
+            Message sm = msgContext.getCurrentMessage();
+            Document doc = null;
+
+            /**
+             * We did not receive anything...Usually happens when we get a
+             * HTTP 202 message (with no content)
+             */
+            if(sm == null){
+                return;
+            }
+
+            try {
+                doc = sm.getSOAPEnvelope().getAsDocument();
+                if (doDebug) {
+                    log.debug("Received SOAP request: ");
+                    log.debug(org.apache.axis.utils.XMLUtils
+                            .PrettyDocumentToString(doc));
+                }
+            } catch (Exception ex) {
+                if (doDebug) {
+                    log.debug(ex.getMessage(), ex);
+                }
+                throw new AxisFault(
+                        "WSDoAllReceiver: cannot convert into document", ex);
+            }
+            /*
+            * Check if it's a response and if its a fault. Don't process
+            * faults.
+            */
+            String msgType = sm.getMessageType();
+            if (msgType != null && msgType.equals(Message.RESPONSE)) {
+                SOAPConstants soapConstants = WSSecurityUtil
+                        .getSOAPConstants(doc.getDocumentElement());
+                if (WSSecurityUtil.findElement(doc.getDocumentElement(),
+                        "Fault", soapConstants.getEnvelopeURI()) != null) {
+                    return;
+                }
+            }
+
+            /*
+            * To check a UsernameToken or to decrypt an encrypted message we
+            * need a password.
+            */
+            CallbackHandler cbHandler = null;
+            if ((doAction & (WSConstants.ENCR | WSConstants.UT)) != 0) {
+                cbHandler = getPasswordCB(reqData);
+            }
+
+            /*
+            * Get and check the Signature specific parameters first because
+            * they may be used for encryption too.
+            */
+            doReceiverAction(doAction, reqData);
+            
+            Vector wsResult = null;
+            if (tlog.isDebugEnabled()) {
+                t1 = System.currentTimeMillis();
+            }        
+
+            try {
+                wsResult = secEngine.processSecurityHeader(doc, actor,
+                        cbHandler, reqData.getSigCrypto(), reqData.getDecCrypto());
+            } catch (WSSecurityException ex) {
+                if (doDebug) {
+                    log.debug(ex.getMessage(), ex);
+                }
+                throw new AxisFault(
+                        "WSDoAllReceiver: security processing failed", ex);
+            }
+
+            if (tlog.isDebugEnabled()) {
+                t2 = System.currentTimeMillis();
+            }        
+
+            if (wsResult == null) { // no security header found
+                if (doAction == WSConstants.NO_SECURITY) {
+                    return;
+                } else {
+                    throw new AxisFault(
+                            "WSDoAllReceiver: Request does not contain required Security header");
+                }
+            }
+
+            if (reqData.getWssConfig().isEnableSignatureConfirmation() && msgContext.getPastPivot()) {
+                checkSignatureConfirmation(reqData, wsResult);
+            }
+            /*
+            * save the processed-header flags
+            */
+            ArrayList processedHeaders = new ArrayList();
+            Iterator iterator = sm.getSOAPEnvelope().getHeaders().iterator();
+            while (iterator.hasNext()) {
+                org.apache.axis.message.SOAPHeaderElement tempHeader = (org.apache.axis.message.SOAPHeaderElement) iterator
+                        .next();
+                if (tempHeader.isProcessed()) {
+                    processedHeaders.add(tempHeader.getQName());
+                }
+            }
+
+            /*
+            * If we had some security processing, get the original SOAP part of
+            * Axis' message and replace it with new SOAP part. This new part
+            * may contain decrypted elements.
+            */
+            SOAPPart sPart = (org.apache.axis.SOAPPart) sm.getSOAPPart();
+
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            XMLUtils.outputDOM(doc, os, true);
+            sPart.setCurrentMessage(os.toByteArray(), SOAPPart.FORM_BYTES);
+            if (doDebug) {
+                log.debug("Processed received SOAP request");
+                log.debug(org.apache.axis.utils.XMLUtils
+                        .PrettyDocumentToString(doc));
+            }
+            if (tlog.isDebugEnabled()) {
+                t3 = System.currentTimeMillis();
+            }        
+
+            /*
+            * set the original processed-header flags
+            */
+            iterator = processedHeaders.iterator();
+            while (iterator.hasNext()) {
+                QName qname = (QName) iterator.next();
+                Enumeration headersByName = sm.getSOAPEnvelope().getHeadersByName(
+                        qname.getNamespaceURI(), qname.getLocalPart());
+                while (headersByName.hasMoreElements()) {
+                    org.apache.axis.message.SOAPHeaderElement tempHeader =
+                        (org.apache.axis.message.SOAPHeaderElement) headersByName.nextElement();
+                    tempHeader.setProcessed(true);
+                }
+            }
+
+            /*
+            * After setting the new current message, probably modified because
+            * of decryption, we need to locate the security header. That is, we
+            * force Axis (with getSOAPEnvelope()) to parse the string, build
+            * the new header. Then we examine, look up the security header and
+            * set the header as processed.
+            *
+            * Please note: find all header elements that contain the same actor
+            * that was given to processSecurityHeader(). Then check if there is
+            * a security header with this actor.
+            */
+
+            SOAPHeader sHeader = null;
+            try {
+                sHeader = sm.getSOAPEnvelope().getHeader();
+            } catch (Exception ex) {
+                if (doDebug) {
+                    log.debug(ex.getMessage(), ex);
+                }
+                throw new AxisFault(
+                        "WSDoAllReceiver: cannot get SOAP header after security processing",
+                        ex);
+            }
+
+            Iterator headers = sHeader.examineHeaderElements(actor);
+
+            SOAPHeaderElement headerElement = null;
+            while (headers.hasNext()) {
+                org.apache.axis.message.SOAPHeaderElement hE = (org.apache.axis.message.SOAPHeaderElement) headers.next();
+                if (hE.getLocalName().equals(WSConstants.WSSE_LN)
+                        && hE.getNamespaceURI().equals(WSConstants.WSSE_NS)) {
+                    headerElement = hE;
+                    break;
+                }
+            }
+            ((org.apache.axis.message.SOAPHeaderElement) headerElement)
+                    .setProcessed(true);
+
+            /*
+            * Now we can check the certificate used to sign the message. In the
+            * following implementation the certificate is only trusted if
+            * either it itself or the certificate of the issuer is installed in
+            * the keystore.
+            *
+            * Note: the method verifyTrust(X509Certificate) allows custom
+            * implementations with other validation algorithms for subclasses.
+            */
+
+            // Extract the signature action result from the action vector
+            WSSecurityEngineResult actionResult = WSSecurityUtil
+                    .fetchActionResult(wsResult, WSConstants.SIGN);
+
+            if (actionResult != null) {
+                X509Certificate returnCert = actionResult.getCertificate();
+
+                if (returnCert != null) {
+                    if (!verifyTrust(returnCert, reqData)) {
+                        throw new AxisFault(
+                                "WSDoAllReceiver: The certificate used for the signature is not trusted");
+                    }
+                }
+            }
+
+            /*
+            * Perform further checks on the timestamp that was transmitted in
+            * the header. In the following implementation the timestamp is
+            * valid if it was created after (now-ttl), where ttl is set on
+            * server side, not by the client.
+            *
+            * Note: the method verifyTimestamp(Timestamp) allows custom
+            * implementations with other validation algorithms for subclasses.
+            */
+
+            // Extract the timestamp action result from the action vector
+            actionResult = WSSecurityUtil.fetchActionResult(wsResult,
+                    WSConstants.TS);
+
+            if (actionResult != null) {
+                Timestamp timestamp = actionResult.getTimestamp();
+
+                if (timestamp != null) {
+                    if (!verifyTimestamp(timestamp, decodeTimeToLive(reqData))) {
+                        throw new AxisFault(
+                                "WSDoAllReceiver: The timestamp could not be validated");
+                    }
+                }
+            }
+
+            /*
+            * now check the security actions: do they match, in right order?
+            */
+            if (!checkReceiverResults(wsResult, actions)) {
+                throw new AxisFault(
+                    "WSDoAllReceiver: security processing failed (actions mismatch)");                
+                
+            }
+            /*
+            * All ok up to this point. Now construct and setup the security
+            * result structure. The service may fetch this and check it.
+            */
+            Vector results = null;
+            if ((results = (Vector) msgContext
+                    .getProperty(WSHandlerConstants.RECV_RESULTS)) == null) {
+                results = new Vector();
+                msgContext
+                        .setProperty(WSHandlerConstants.RECV_RESULTS, results);
+            }
+            WSHandlerResult rResult = new WSHandlerResult(actor, wsResult);
+            results.add(0, rResult);
+            if (tlog.isDebugEnabled()) {
+                t4 = System.currentTimeMillis();
+                tlog.debug("Receive request: total= " + (t4 - t0) +
+                        " request preparation= " + (t1 - t0) +
+                        " request processing= " + (t2 - t1) +
+                        " request to Axis= " + (t3 - t2) + 
+                        " header, cert verify, timestamp= " + (t4 - t3) +
+                        "\n");                                
+            }        
+
+            if (doDebug) {
+                log.debug("WSDoAllReceiver: exit invoke()");
+            }
+        } catch (WSSecurityException e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+            throw new AxisFault(e.getMessage(), e);
+        } finally {
+            reqData.clear();
+            reqData = null;
+        }
+    }
+}
diff --git a/trunk/src/org/apache/ws/axis/security/WSDoAllSender.java b/trunk/src/org/apache/ws/axis/security/WSDoAllSender.java
new file mode 100644
index 0000000..64139f2
--- /dev/null
+++ b/trunk/src/org/apache/ws/axis/security/WSDoAllSender.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.axis.security;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.SOAPPart;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.axis.security.handler.WSDoAllHandler;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.utils.XMLUtils;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Vector;
+
+/**
+ * @author Werner Dittmann (werner@apache.org)
+ */
+public class WSDoAllSender extends WSDoAllHandler {
+
+    protected static Log log = LogFactory.getLog(WSDoAllSender.class.getName());
+    private static Log tlog =
+        LogFactory.getLog("org.apache.ws.security.TIME");
+    
+    /**
+     * Axis calls invoke to handle a message. <p/>
+     *
+     * @param mc message context.
+     * @throws AxisFault
+     */
+    public void invoke(MessageContext mc) throws AxisFault {
+
+        boolean doDebug = log.isDebugEnabled();
+        
+        long t0 = 0, t1 = 0, t2 = 0, t3 = 0;
+        if (tlog.isDebugEnabled()) {
+            t0 = System.currentTimeMillis();
+        }
+
+        if (doDebug && mc.getCurrentMessage() != null
+                && mc.getCurrentMessage().getMessageType() != null) {
+            log.debug("WSDoAllSender: enter invoke() with msg type: "
+                    + mc.getCurrentMessage().getMessageType());
+        }
+
+        RequestData reqData = new RequestData();
+
+        reqData.setMsgContext(mc);
+        /*
+         * The overall try, just to have a finally at the end to perform some
+         * housekeeping.
+         */
+        try {
+            /*
+             * Get the action first.
+             */
+            Vector actions = new Vector();
+            String action = getString(WSHandlerConstants.ACTION, mc);
+            if (action == null) {
+                throw new AxisFault("WSDoAllSender: No action defined");
+            }
+            int doAction = WSSecurityUtil.decodeAction(action, actions);
+            if (doAction == WSConstants.NO_SECURITY) {
+                return;
+            }
+
+            /*
+             * For every action we need a username, so get this now. The
+             * username defined in the deployment descriptor takes precedence.
+             */
+            reqData.setUsername((String) getOption(WSHandlerConstants.USER));
+            if (reqData.getUsername() == null || reqData.getUsername().equals("")) {
+                String username = (String) getProperty(reqData.getMsgContext(), WSHandlerConstants.USER);
+                if (username != null) {
+                    reqData.setUsername(username);
+                } else {
+                    reqData.setUsername(((MessageContext)reqData.getMsgContext()).getUsername());
+                    ((MessageContext)reqData.getMsgContext()).setUsername(null);
+                }
+            }
+            /*
+             * Now we perform some set-up for UsernameToken and Signature
+             * functions. No need to do it for encryption only. Check if
+             * username is available and then get a passowrd.
+             */
+            if ((doAction & (WSConstants.SIGN | WSConstants.UT | WSConstants.UT_SIGN)) != 0) {
+                /*
+                 * We need a username - if none throw an AxisFault. For
+                 * encryption there is a specific parameter to get a username.
+                 */
+                if (reqData.getUsername() == null || reqData.getUsername().equals("")) {
+                    throw new AxisFault(
+                    "WSDoAllSender: Empty username for specified action");
+                }
+            }
+            if (doDebug) {
+                log.debug("Action: " + doAction);
+                log.debug("Actor: " + reqData.getActor());
+            }
+            /*
+             * Now get the SOAP part from the request message and convert it
+             * into a Document.
+             *
+             * This forces Axis to serialize the SOAP request into FORM_STRING.
+             * This string is converted into a document.
+             *
+             * During the FORM_STRING serialization Axis performs multi-ref of
+             * complex data types (if requested), generates and inserts
+             * references for attachements and so on. The resulting Document
+             * MUST be the complete and final SOAP request as Axis would send it
+             * over the wire. Therefore this must shall be the last (or only)
+             * handler in a chain.
+             *
+             * Now we can perform our security operations on this request.
+             */
+            Document doc = null;
+            Message message = mc.getCurrentMessage();
+
+            /**
+             * There is nothing to send...Usually happens when the provider needs to
+             * send a HTTP 202 message (with no content)
+             */
+            if(message == null){
+                return;
+            }
+
+            /*
+            * If the message context property conatins a document then this is
+            * a chained handler.
+            */
+            SOAPPart sPart = (org.apache.axis.SOAPPart) message.getSOAPPart();
+            if ((doc = (Document) ((MessageContext)reqData.getMsgContext())
+                    .getProperty(WSHandlerConstants.SND_SECURITY)) == null) {
+                try {
+                    doc = ((org.apache.axis.message.SOAPEnvelope) sPart
+                            .getEnvelope()).getAsDocument();
+                } catch (Exception e) {
+                    throw new AxisFault(
+                            "WSDoAllSender: cannot get SOAP envlope from message"
+                                    + e);
+                }
+            }
+            if (tlog.isDebugEnabled()) {
+                t1 = System.currentTimeMillis();
+            }
+
+            doSenderAction(doAction, doc, reqData, actions, !mc.getPastPivot());
+            
+            if (tlog.isDebugEnabled()) {
+                t2 = System.currentTimeMillis();
+            }
+
+            /*
+             * If required convert the resulting document into a message first.
+             * The outputDOM() method performs the necessary c14n call. After
+             * that we extract it as a string for further processing.
+             *
+             * Set the resulting byte array as the new SOAP message.
+             *
+             * If noSerialization is false, this handler shall be the last (or
+             * only) one in a handler chain. If noSerialization is true, just
+             * set the processed Document in the transfer property. The next
+             * Axis WSS4J handler takes it and performs additional security
+             * processing steps.
+             *
+             */
+            if (reqData.isNoSerialization()) {
+                ((MessageContext)reqData.getMsgContext()).setProperty(WSHandlerConstants.SND_SECURITY,
+                        doc);
+            } else {
+                ByteArrayOutputStream os = new ByteArrayOutputStream();
+                XMLUtils.outputDOM(doc, os, true);
+                sPart.setCurrentMessage(os.toByteArray(), SOAPPart.FORM_BYTES);
+                if (doDebug) {
+                    String osStr = null;
+                    try {
+                        osStr = os.toString("UTF-8");
+                    } catch (UnsupportedEncodingException e) {
+                        osStr = os.toString();
+                    }
+                    log.debug("Send request:");
+                    log.debug(osStr);
+                }
+                ((MessageContext)reqData.getMsgContext()).setProperty(WSHandlerConstants.SND_SECURITY,
+                        null);
+            }
+            if (tlog.isDebugEnabled()) {
+                t3 = System.currentTimeMillis();
+                tlog.debug("Send request: total= " + (t3 - t0) +
+                        " request preparation= " + (t1 - t0) +
+                        " request processing= " + (t2 - t1) +
+                        " request to Axis= " + (t3 - t2) +
+                        "\n");                
+            }
+
+            if (doDebug) {
+                log.debug("WSDoAllSender: exit invoke()");
+            }
+        } catch (WSSecurityException e) {
+            throw new AxisFault(e.getMessage(), e);
+        } finally {
+            reqData.clear();
+            reqData = null;
+        }
+    }
+}
diff --git a/trunk/src/org/apache/ws/axis/security/handler/WSDoAllHandler.java b/trunk/src/org/apache/ws/axis/security/handler/WSDoAllHandler.java
new file mode 100644
index 0000000..d739bd1
--- /dev/null
+++ b/trunk/src/org/apache/ws/axis/security/handler/WSDoAllHandler.java
@@ -0,0 +1,200 @@
+/*
+* Copyright  2003-2004 The Apache Software Foundation.
+*
+*  Licensed 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.ws.axis.security.handler;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.Handler;
+import org.apache.axis.MessageContext;
+import org.apache.axis.components.logger.LogFactory;
+import org.apache.axis.utils.LockableHashtable;
+import org.apache.commons.logging.Log;
+import org.apache.ws.security.handler.WSHandler;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.xml.namespace.QName;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+
+
+/**
+ * <code>WSDoAllHandler</code> is a utility class which implements simple
+ * property setting/getting behavior, and stubs out a lot of the Handler
+ * methods.  Extend this class to make writing your Handlers easier, and
+ * then override what you need to.
+ */
+public abstract class WSDoAllHandler extends WSHandler implements Handler {
+    private static Log log =
+            LogFactory.getLog(WSDoAllHandler.class.getName());
+
+    protected boolean makeLockable = false;
+    protected Hashtable options;
+    protected String name;
+
+    /**
+     * Should this Handler use a LockableHashtable for options?
+     * Default is 'false'.
+     */
+    protected void setOptionsLockable(boolean makeLockable) {
+        this.makeLockable = makeLockable;
+    }
+
+    protected void initHashtable() {
+        if (makeLockable) {
+            options = new LockableHashtable();
+        } else {
+            options = new Hashtable();
+        }
+    }
+
+    /**
+     * Stubbed-out methods.  Override in your child class to implement
+     * any real behavior.  Note that there is NOT a stub for invoke(), since
+     * we require any Handler derivative to implement that.
+     */
+    public void init() {
+    }
+
+    public void cleanup() {
+    }
+
+    public boolean canHandleBlock(QName qname) {
+        return false;
+    }
+
+    public void onFault(MessageContext msgContext) {
+    }
+
+    /**
+     * Set the given option (name/value) in this handler's bag of options
+     */
+    public void setOption(String name, Object value) {
+        if (options == null) initHashtable();
+        options.put(name, value);
+    }
+
+    /**
+     * Set a default value for the given option:
+     * if the option is not already set, then set it.
+     * if the option is already set, then do not set it.
+     * <p/>
+     * If this is called multiple times, the first with a non-null value
+     * if 'value' will set the default, remaining calls will be ignored.
+     * <p/>
+     * Returns true if value set (by this call), otherwise false;
+     */
+    public boolean setOptionDefault(String name, Object value) {
+        boolean val = (options == null || options.get(name) == null) && value != null;
+        if (val) {
+            setOption(name, value);
+        }
+        return val;
+    }
+
+    /**
+     * Returns the option corresponding to <code>name</code>.
+     *
+     * @param name the non-null name of the option.
+     * @return the option on <code>name</code> if <code>name</code>
+     *  exists; otherwise null.
+     */
+    public Object getOption(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("name cannot be null");
+        }
+        if (options == null) {
+            return null;
+        }
+        return options.get(name);
+    }
+
+    /**
+     * Return the entire list of options
+     */
+    public Hashtable getOptions() {
+        return (options);
+    }
+
+    public void setOptions(Hashtable opts) {
+        options = opts;
+    }
+
+    /**
+     * Set the name (i.e. registry key) of this Handler
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Return the name (i.e. registry key) for this Handler
+     */
+    public String getName() {
+        return name;
+    }
+
+    public Element getDeploymentData(Document doc) {
+        log.debug("Enter: BasicHandler::getDeploymentData");
+
+        Element root = doc.createElementNS("", "handler");
+
+        root.setAttribute("class", this.getClass().getName());
+        options = this.getOptions();
+        if (options != null) {
+            Enumeration e = options.keys();
+            while (e.hasMoreElements()) {
+                String k = (String) e.nextElement();
+                Object v = options.get(k);
+                Element e1 = doc.createElementNS("", "option");
+                e1.setAttribute("name", k);
+                e1.setAttribute("value", v.toString());
+                root.appendChild(e1);
+            }
+        }
+        log.debug("Exit: WSDoAllHandler::getDeploymentData");
+        return (root);
+    }
+
+    public void generateWSDL(MessageContext msgContext) throws AxisFault {
+    }
+
+    /**
+     * Return a list of QNames which this Handler understands.  By returning
+     * a particular QName here, we are committing to fulfilling any contracts
+     * defined in the specification of the SOAP header with that QName.
+     */
+    public List getUnderstoodHeaders() {
+        return null;
+    }
+
+    public Object getProperty(Object msgContext, String key) {
+        return ((MessageContext)msgContext).getProperty(key);
+    }
+    
+    public void setProperty(Object msgContext, String key, Object value) {
+        ((MessageContext)msgContext).setProperty(key, value);
+    }
+
+    public String getPassword(Object msgContext) {
+        return ((MessageContext)msgContext).getPassword();
+    }
+
+    public void setPassword(Object msgContext, String password) {
+        ((MessageContext)msgContext).setPassword(password);
+    }
+}
diff --git a/trunk/src/org/apache/ws/axis/security/package.html b/trunk/src/org/apache/ws/axis/security/package.html
new file mode 100644
index 0000000..0fd3be2
--- /dev/null
+++ b/trunk/src/org/apache/ws/axis/security/package.html
@@ -0,0 +1,680 @@
+<!-- <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+  -->
+<html>
+<head>
+  <title>Axis handler for WSS4J</title>
+<!--
+
+  @(#)Axis handler for WSS4J 
+
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+-->
+</head>
+<body bgcolor="white">
+
+Provides classes and interfaces that implement WSS4J Axis handlers.
+These handler process SOAP requests according to the OASIS Web Service 
+Security (WSS) specifications.
+<p/>
+The WSS4J Axis handlers <code>WSDoAllSender</code> and <code>WSDoAllReceiver
+</code> control the creation and consumption of secure SOAP requests.
+The handlers work behind the scenes and are usually transparent to Web Service
+(WS) applications. The Axis deployment descriptor files (*.wsdd) may contain all
+necessary information to control the security processing.
+<p/>
+A WS application may also set properties to control the handlers
+and provide default values. If the deployment descriptor sets the same 
+property (parameter) then the deployment descriptor overwrites the application
+defined property.  Thus, deployment settings overwrite application settings 
+to fulfill site specific requirements.
+
+<h3>Prerequisties</h3>
+The WS Security Axis handlers use the WSS4J classes (Web Service Security 
+for Java) to process the SOAP messages. WSS4J in turn uses the Apache XML Security 
+project to handle XML Security according to XML Signature and XML Encryption. 
+
+<ul>
+  <li><a href="http://ws.apache.org/ws-fx/wss4j/index.html">WSS4J</a></li>
+  <li><a href="http://xml.apache.org/security/index.html">XML Security</a></li>
+</ul>
+
+The WSS4J Axis handlers require Axis V1.2 because of some problems in previous
+Axis versions. WSS4J CVS contains the latest Axis libraries. 
+
+<h3>Related Documentation</h3>
+The OASIS WSS specifications define a number of features and it is possible 
+to combine them in several ways. The WSS4J Axis handlers already support 
+a large number of WSS features and their combinations. 
+<a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss">
+Here</a> are the WSS specifications.
+
+<h3>The basics - a simple example that uses <code>UsernameToken</code></h3>
+This chapter gives an overview and some examples how to deploy 
+the WSS4J Axis handlers and how the parameters and their values control the
+handlers. For a better understanding of this chapter the reader shall 
+have a knowledge of the OASIS WSS specifications.
+<p/>
+The {@link org.apache.ws.security.handler.WSHandlerConstants}, 
+{@link org.apache.ws.axis.security.WSDoAllSender}, and 
+{@link org.apache.ws.axis.security.WSDoAllReceiver}
+provide additional and detailed documentation.
+
+<h4>Axis deployment descriptor to insert a <code>UsernameToken</code></h4>
+The following snippet shows a general layout how to deploy a WS Axis handler
+on the client (application) side.
+<pre>
+ &lt;!-- define the service, use the WSDoAllSender security handler in request flow -->
+ &lt;service name="Ping1">
+  &lt;requestFlow>
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    &lt;parameter name="action" value="UsernameToken"/>
+    &lt;parameter name="user" value="werner"/>
+    &lt;parameter name="passwordType" value="PasswordText" />
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/>
+   &lt;/handler>
+  &lt;/requestFlow>
+  &lt;/service>
+</pre>
+
+This is the standard way to deploy an Axis handler. Axis parses the deployment
+descriptor and provides the parameters and their value to the handler. Each
+service can have its own request and response flow definition, which provides
+a very flexible set-up of the security parameters.
+<p/>
+The above setup inserts the most simple security structure into a SOAP request: 
+the simple <code>UsernameToken</code>. This token includes a username and the 
+according password. Both fields are sent in cleartext, thus it provides no 
+real security.
+<p/>
+
+The parameters and their meanings are:
+<ul>
+<li><code>action</code> defines the security action. The value <code>
+    UsernameToken</code> directs the handler to insert this token into
+    the SOAP request.
+</li>
+<li><code>user</code> specifies the username to include in the token.
+</li>
+<li><code>passwordType</code> is a pecific parameter for the <code>
+    UsernameToken</code> action and defines the encoding of the passowrd.
+    <code>PasswordText</code> specifies to send the password in
+    plain text, <code>PasswordDigest</code> specifies to send the
+    password in digest mode (refer to WSS UsernameToken Profile)
+</li>
+<li><code>passwordCallbackClass</code> contains the name of a class that
+    implements a method to get the user's password. Please refer to the
+    detailed documentation in 
+    {@link org.apache.ws.security.handler.WSHandlerConstants#PW_CALLBACK_CLASS}.
+    </li>
+</ul>
+The WSS4J Axis security handler interprets the parameter values and controls
+the WSS4J modules to generate the following SOAP request:
+<pre>
+&lt;?xml version="1.0" encoding="UTF-8"?>
+&lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
+  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  &lt;soapenv:Header>
+    &lt;wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext" 
+      soapenv:mustUnderstand="true">
+      &lt;wsse:UsernameToken>
+        &lt;wsse:Username>werner&lt;/wsse:Username>
+        &lt;wsse:Password Type="wsse:PasswordText">security&lt;/wsse:Password>
+      &lt;/wsse:UsernameToken>
+    &lt;/wsse:Security>
+  &lt;/soapenv:Header>
+  &lt;soapenv:Body>
+    &lt;Ping xmlns="http://xmlsoap.org/Ping">
+      &lt;text>Scenario 1 text&lt;/text>
+      &lt;ticket xmlns:ns1="http://xmlsoap.org/Ping" 
+        xsi:type="ns1:ticketType">scenario1&lt;/ticket>
+    &lt;/Ping>
+  &lt;/soapenv:Body>
+&lt;/soapenv:Envelope>
+</pre>
+This is a pretty print of the real SOAP message.
+
+<h4><a name="pwCallBackClass">The password callback class</a></h4>
+
+The deployment descriptor contains the user name that the handler inserts into
+the <code>UsernameToken</code> but not the password. In general it is not a
+good idea to store sensitive information like a password in cleartext. To
+get the password the WSS4J Axis handler uses a password callback
+technique similar to the JAAS mechansim. The parameter 
+<code>passwordCallbackClass</code> contains the classname of the callback
+class. This class must implement the
+{@link javax.security.auth.callback.CallbackHandler}
+interface. The WSS4J Axis handler gets this class,
+instantiates it, and calls the <code>handle</code> method when it
+needs a password. Refer also to the 
+{@link org.apache.ws.security.handler.WSHandlerConstants#PW_CALLBACK_CLASS
+ parameter} documentation.
+ <p/>
+ The following code snippet shows a simple password callback class:
+ <pre>
+package org.apache.ws.axis.oasis;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.ws.security.WSPasswordCallback;
+
+public class PWCallback implements CallbackHandler {
+
+  private static final byte[] key = {
+    (byte)0x31, (byte)0xfd, (byte)0xcb, (byte)0xda,
+    (byte)0xfb, (byte)0xcd, (byte)0x6b, (byte)0xa8,
+    (byte)0xe6, (byte)0x19, (byte)0xa7, (byte)0xbf,
+    (byte)0x51, (byte)0xf7, (byte)0xc7, (byte)0x3e,
+    (byte)0x80, (byte)0xae, (byte)0x98, (byte)0x51,
+    (byte)0xc8, (byte)0x51, (byte)0x34, (byte)0x04,
+  };
+	
+  public void handle(Callback[] callbacks)
+    throws IOException, UnsupportedCallbackException {
+    for (int i = 0; i &lt; callbacks.length; i++) {
+      if (callbacks[i] instanceof WSPasswordCallback) {
+        WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+        /*
+         * here call a function/method to lookup the password for
+         * the given identifier (e.g. a user name or keystore alias)
+         * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+         * for testing we supply a fixed name/fixed key here.
+         */
+        if (pc.getUsage() == WSPasswordCallback.KEY_NAME) {
+          pc.setKey(key);
+        }
+        else {
+          pc.setPassword("security");
+        }
+      } else {
+        throw new UnsupportedCallbackException(
+          callbacks[i], "Unrecognized Callback");
+      }
+    }
+  }
+}
+</pre>
+The Java {@link javax.security.auth.callback.CallbackHandler callback} handler
+documentation provides a detailed description of the interface and exceptions.
+<p/>
+The WSS4J library uses a specific class to get the required password or key
+informations. The <code>WSSPasswordCallback</code> class implements the
+{@link javax.security.auth.callback.Callback} interface according to the
+JAAS. Depending on it usage this class either carries the required password
+as a Java <code>String </code> or it carries the required key information 
+as a Java <code>byte[]</code> array. Refer to
+{@link org.apache.ws.security.WSPasswordCallback} that contains a
+detailed description of the usage codes.
+<p/>
+The WSS4J Axis handler or the WSS4J modules set the usage code before
+they call <code>handle</code> method. 
+
+<h4>Application sets parameters to insert in <code>UsernameToken</code></h4>
+
+Sometimes it is not feasable or not possible to determine parameters
+and their values during deployment. In this case the application can
+set paramters during runtime. The WSS4J Axis handlers use the Axis
+<code>setProperty</code> method to support this feature.
+<p/>
+The following code snippet shows an example how to use the dynamic setting
+of parameters and their values:
+<pre>
+   ...
+ Service service = new Service();
+ Call call = (Call) service.createCall();
+   ...  
+ call.setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
+ call.setProperty(WSHandlerConstants.USER, "werner");
+   ...
+</pre>
+Use this way if your application dynamically creates a <code>call</code> 
+object. If your application uses stubs generated by Axis' <code>WSDL2Java
+</code> tool, the application uses the following functions:
+<pre>
+    ...
+ PingServiceLocator service = new PingServiceLocator();
+    ...
+ PingPort port = (PingPort) service.getPing1();
+ port._setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
+ port._setProperty(WSHandlerConstants.USER, "werner");
+    ...
+</pre>
+Please note that <code>_setProperty</code> is a Axis specific call.
+
+<h4>The password callback object reference</h4>
+
+In addition to the <a href="#pwCallBackClass">password callback class</a>
+an application may set a password callback object using the <code>
+  setProperty()</code> methods. Only applications (and Axis handlers that
+  preceed the WSS4J Axis handlers in a handler chain) can use this feature.
+  <p/>
+  For example:
+  <pre>
+public class Scenario1 implements CallbackHandler {
+
+  public static void main(String args[]) {
+    ...
+    PingServiceLocator service = new PingServiceLocator();
+    ...
+    PingPort port = (PingPort) service.getPing1();
+    ((org.apache.axis.client.Stub)port)._setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
+    ((org.apache.axis.client.Stub)port._setProperty(WSHandlerConstants.USER, "werner");
+    ((org.apache.axis.client.Stub)port._setProperty(WSHandlerConstants.PW_CALLBACK_REF, this);
+    ...
+  }
+
+  public void handle(Callback[] callbacks) {
+    ...
+  }
+}
+</pre>
+
+<h4>Deployment of the WSS4J Axis <code>WSDoAllReceiver</code> handler</h4>
+
+Similar to the deployment descriptor of the sending handler <code>WSDoAllSender
+</code> a deployment descriptor for the receiving handler exists. For the above
+example the deployment descriptor look like:
+<pre>
+  &lt;requestFlow>
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/>
+    &lt;parameter name="action" value="UsernameToken"/>
+   &lt;/handler>
+  &lt;/requestFlow>
+</pre>
+The receiving WSS4J Axis handler checks if the SOAP request matches the defined
+actions.
+
+<h3>Combining security actions</h3>
+
+Often it is necessary to combine or concatenate several security actions, for 
+example to encrypt parts of a message and sign some other parts. The WSS4J 
+Axis handlers provide easy and simple methods to combine or concatenate
+security actions. 
+<p/>
+This chapter describes simple combinations of actions.
+
+<h4>Combine <code>UsernameToken</code> and <code>Encryption</code></h4>
+
+The WS Interoperability specifications define this use case: 
+<ul>
+  <li>Insert a <code>UsernameToken</code>, use <code>PasswordText</code>
+    to set the password. In addition add a timestamp and a nonce into
+    the <code>UsernameToken</code></li>
+  <li>Encrypt the <code>UsernameToken</code> to protect the information.
+    </li>
+</ul>
+
+The Axis deplyment descriptor for this use case:
+<pre>
+  &lt;requestFlow>
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    &lt;parameter name="action" value="UsernameToken Encrypt"/>
+    &lt;parameter name="user" value="werner"/>
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/>
+    &lt;parameter name="passwordType" value="PasswordText" />
+    &lt;parameter name="addUTElement" value="Nonce Created" />
+    &lt;parameter name="encryptionPropFile" value="crypto.properties" />
+    &lt;parameter name="encryptionKeyIdentifier" value="X509KeyIdentifier" />
+    &lt;parameter name="encryptionUser" 
+      value="16c73ab6-b892-458f-abf5-2f875f74882e" />
+    &lt;parameter name="encryptionParts" 
+      value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken" />  
+   &lt;/handler>
+  &lt;/requestFlow>  
+</pre>
+
+This descriptor contains some new parameters to control the <code>UsernameToken
+</code> element and its encryption. The new parameters and their meaning are:
+<ul>
+  <li><code>addUTElement</code> - controls if the handler shall insert elements
+    into the <code>UsernameToken</code>. The value is a blank separated list of
+    element names to include. Only <code>Nonce</code> and <code>Created</code> are
+    supported.</li>
+  <li><code>encryptionPropFile</code> - the name of a crypto property file. This
+    file contains parameters and property that control the encryption. Please refer
+    to the
+    {@link org.apache.ws.security.handler.WSHandlerConstants#ENC_PROP_FILE 
+    detailed} description of the cyrpto property file.</li>
+  <li><code>encryptionKeyIdentifier</code> - specifies the format in which the 
+    handler inserts the encryption key into the SOAP request. Please refer
+    to the 
+    {@link org.apache.ws.security.handler.WSHandlerConstants#ENC_KEY_ID 
+    detailed} description.</li>
+  <li><code>encryptionUser</code> - the name or identifier of the user who owns
+    the public key to encrypt the data. Usually this is the name or alias name
+    of the owner's certificate in a keystore.</li>
+  <li><code>encryptionParts</code> - controls which part or parts the handler
+    of the SOAP shall encrypt. If this parameter is not defined, WSS4J encrypts
+    the whole SOAP Body in <code>Content</code> mode. The value of the
+    parameter in this example specifies to encrypt the element <code>
+    UsernameToken</code>, contained in the namespace
+    <code>http://schemas.xmlsoap.org/ws/2002/07/secext</code>. The encryption
+    module uses the <code>Element</code> mode to encrypt the element data.
+    Please refer to the
+    {@link org.apache.ws.security.handler.WSHandlerConstants#ENCRYPTION_PARTS 
+    detailed} description.
+    </li>
+</ul>
+The matching receiver deployment descriptor:
+<pre>
+  &lt;requestFlow>
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/>
+    &lt;parameter name="action" value="UsernameToken Encrypt"/>
+    &lt;parameter name="decryptionPropFile" value="crypto.properties" />
+   &lt;/handler>
+  &lt;/requestFlow>
+</pre>
+The only new parameter here is the <code>decryptionPropFile</code>. This
+parameter defines the crypto property file at the receiver side. The value
+  of the <code>action</code> parameter matches the according value at the
+  sender side. The WSS4J Axis receiver checks if the SOAP request contains
+  the required security data.
+
+<h4>Combine Signature and Encryption</h4>
+
+This is a very common usage of Web Service security. The WSS4J Axis handler
+provides flexible parameter settings that support several ways to use
+the Signature/Encryption combination.
+<p/>
+A WSS4J Axis deployment descriptor for a simple Singature/Encryption of
+SOAP requests:
+<pre>
+&lt;requestFlow>
+  &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    &lt;parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/>
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/>
+    &lt;parameter name="action" value="Signature Encrypt"/>
+    &lt;parameter name="signaturePropFile" value="crypto.properties" />
+  &lt;/handler>
+&lt;/requestFlow>
+</pre>
+This simple deployment descriptor signs and encrypts the SOAP Body part.
+The only new parameter, <code>signaturePropFile</code>, specifies the
+name of the signature crypto property file to use. Because no 
+<code>encryptionPropFile</code> is declared the handler also uses the signature
+property file to get the encryption certificate. The same holds true for
+the username. The password callback class must return a password
+to get the user's private key (the keystore is defined in the crypto
+property file) that WSS4J uses to generate the signature. The encryption
+method uses the user's public key to encrypt the dynamically generated
+session key.
+<p/>
+The <code>action</code> parameter defines <code>Signature Encryption</code>.
+Thus the handler first signs, then the encrypts the data.
+Because the deployment descriptor does not contain specific encryption or 
+signature part parameters, WSS4J defaults to the data of the SOAP Body element.
+<p/>
+Also all other parameters use their default setting, such as the format of the
+key identifiers, encryption modifiers, and so on. Please refer to the
+{@link org.apache.ws.security.handler.WSHandlerConstants detailed}
+documentation of the parameters.
+<p/>
+If the WSS4J Axis handler shall perform encryption only, then the
+deployment descriptor must contain the encryption specific parameters. Only
+if sign <b>and</b> encryption is required the encryption method falls back to
+the signature parameters if the encryption specific parameters are not set.
+<p/>
+The matching receiver deployment descriptor is also very simple:
+<pre>
+&lt;requestFlow>
+  &lt;handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/>
+    &lt;parameter name="action" value="Signature Encrypt"/>
+    &lt;parameter name="signaturePropFile" value="crypto.properties" />
+  &lt;/handler>
+ &lt;/requestFlow>	
+</pre>
+To reverse the actions, just reverse the action specifiers. The WSS4J
+handler encrypts the SOAP Body first, then signs the encrypted data.
+
+<h3>Signing and encrypting multiple XML elements</h3>
+
+Sometimes it is necessary to sign and/or encrypt several parts of a SOAP
+message. The deployment parameters <code>signatureParts</code> and 
+<code>encryptionParts</code> control which SOAP elements to sign or
+to encrypt. Please refer to the
+{@link org.apache.ws.security.handler.WSHandlerConstants#ENCRYPTION_PARTS 
+detailed} description of these parameters.
+<p/>
+WSS4J signs or encrypts all declared parts using the same keys, that is 
+the signature or encryption data structures directly reference the 
+specified parts as described in the WSS specifications. The receiver
+automatically detects these references and verfies and decrypts the
+data parts. No special settings in the depolyment descriptor is necessary.
+
+<h3>Chaining of WSS4J Axis handlers</h3>
+
+This is a very powerful feature that supports even more flexible signature and
+encryption processing such as signatures with multiple keys (overlapping
+signatures), multiple encryption algorithms, or different SOAP actor (role)
+defintions of the security headers.
+
+<h4>Deployment at the client</h4>
+A deployment descriptor to chain handlers:
+<pre>
+  &lt;requestFlow>
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    &lt;parameter name="action" value="Signature NoSerialization"/>
+    &lt;parameter name="user" value="firstUser"/>
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/>
+    &lt;parameter name="signaturePropFile" value="crypto.properties" />
+    &lt;parameter name="signatureParts" value="{}{http://xmlsoap.org/Ping}ticket" />    
+   &lt;/handler>
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
+    &lt;parameter name="action" value="Signature"/>
+    &lt;parameter name="user" value="anotherUser"/>
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/>
+    &lt;parameter name="signaturePropFile" value="crypto.properties" />
+   &lt;/handler>  
+  &lt;/requestFlow>
+</pre>
+Note the action specifier <code>NoSerialization</code> first handler. 
+In a handler chain of WSS4J handlers every
+but the last handler <i>must</i> have this action specifier. This specifier
+surpresses the very last step of the handler's security processing: the 
+serialization of the processed SOAP request in a XML string (document) that 
+Axis sends to the reveiver. Only the last handler must perform this 
+serialization.
+<p/>
+Every handler specification can have its own set of parameters that define
+the individual values for this handler instance. Thus the deployment
+descriptor can define different crypto property files, different usernames,
+and so on. In the example the first handler signs the <code>ticket</code>
+element and the second handler the SOAP Body (default).
+<p/>
+Parameters set by the application with <code>setProperty</code> are valid for 
+<b>all</b> handler instances in the handler
+chain (<code>setProperty</code> is defined on the SOAP request (call) level).
+As already decribed, deployment settings overrule application settings. Thus it
+is possible to combine various parameter specifications. A special case is the
+definition of the username. If an application sets the username and one
+handler instance in the chain does not have a <code>user</code> parameter 
+in its deployment part, then this one handler instance uses the username set
+bey the application. After the handler copied the username from the username
+property, the handler sets the property's content to <code>null</code>. 
+Handlers that follow in the chain cannot use this username anymore and 
+must have a user (or encryption user) parameter in their deployment part.
+
+<h4>Deployment at the server</h4>
+
+Note: Handler chaining at the receiver side is not yet fully tested.
+<p/>
+Handlers at the receiver can only determine different security headers if their
+SOAP actors are different. The WSS4J handler processes each security structure
+inside one security header. Because the security structures contain most
+information to verify or decrypt the SOAP request this constraint is
+not too much of an issue.
+<p/>
+Only the password call back class and the <code>Crypto</code> implementation
+(as defined in the crypto property file) must be able to handle all possible 
+certificates, users, passwords, and keys that a security header may contain.
+The following deployment descriptor of a receiver shows this.
+<pre>
+  &lt;requestFlow>
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/>
+    &lt;parameter name="action" value="Signature Signature"/>
+    &lt;parameter name="signaturePropFile" value="crypto.properties" />
+   &lt;/handler>
+  &lt;/requestFlow>
+</pre>
+The client uses two handlers in a chain, each signing a part of the SOAP 
+request but with different certificates. Because the handlers do not 
+specifiy a SOAP actor WSS4J puts both signatures in the security header
+of the default actor. 
+To match the security actions the deployment descriptor of the receiver needs 
+to contain the action declaration <code>Signature Signature</code>. This 
+instructs the WSS4J handler to accept and verify two distinct signatures 
+contained in one security header. Because the signatures use different 
+certificates the <code>Crypto</code> implementation must be able to handle
+these certificates.
+<p/>
+Similar requirements are true for the password callback implementation if the
+sender uses handler chaining and uses different encryption parameters in the
+same security header.
+<p/>
+If it is necessary to have different parameters for the distinct signature or
+decryption data then these should be put in different security headers. The 
+easiest way to do this is to define different <code>actor</code> parameters
+for each handler in a WSS4J handler chain.
+ 
+<h3>Reporting Security results to services/applications</h3>
+The WSS4J <code>WSSecurityEngine</code> processes the security elements inside
+a security header. If something goes wrong, for example a signature 
+verfication fails, then the engine throws a fault. If the security engine
+could perform all operations sucessfully it returns a data structure
+that contains the results of the performed security actions. This data
+structure holds information about the performed action, the usernames or
+identifier in case the security engine performed signature or username token
+processing. Please refer to the
+{@link org.apache.ws.security.WSSecurityEngineResult result} structure.
+<p/>
+The <code>WSDoAllReceiver</code> WSS4J handler takes this structure and
+checks if all required actions were performed. If this check fails, the
+WSS4J handler aborts the SOAP request and throws an Axis SOAP fault.
+Otherwise it creates its own data structure 
+{@link org.apache.ws.security.handler.WSHandlerResult}, copies the
+security results in this structure, and adds the actor name of the
+security header. Then it stores this new data structure in a vector and stores
+this vector in a specific 
+{@link org.apache.ws.security.handler.WSHandlerConstants#RECV_RESULTS property} 
+of the current message context. If WSS4J handlers are
+chained, then every handler in the chain adds its result to the vector. The
+vector contains the results in handler-chain order.
+<p/>
+This code snippet shows how a Axis service can access the security result
+data:
+<pre>
+    public void ping(javax.xml.rpc.holders.StringHolder text,
+        org.apache.ws.axis.oasis.ping.TicketType ticket)
+        throws java.rmi.RemoteException {
+
+        text.value = "Echo " + text.value.trim();
+		
+        // get the message context first
+        MessageContext msgContext = MessageContext.getCurrentContext();
+        Message reqMsg = msgContext.getRequestMessage();
+
+        Vector results = null;
+        // get the result Vector from the property
+        if ((results =
+            (Vector) msgContext.getProperty(WSHandlerConstants.RECV_RESULTS))
+             == null) {
+            System.out.println("No security results!!");
+        }
+        System.out.println("Number of results: " + results.size());
+        for (int i = 0; i &lt; results.size(); i++) {
+            WSHandlerResult hResult = (WSHandlerResult)results.get(i);
+            String actor = hResult.getActor();
+            Vector hResults = hResult.getResults();
+            for (int j = 0; j < hResults.size(); j++) {
+              	WSSecurityEngineResult eResult = (WSSecurityEngineResult) hResults.get(j);
+                // Note: an encryption action does not have an associated principal
+    	        // only Signature and UsernameToken actions return a principal
+                if (eResult.getAction() != WSConstants.ENCR) {
+                    System.out.println(eResult.getPrincipal().getName());
+                }
+            }
+        }
+    }
+</pre>
+The principal structure is either a 
+{@link org.apache.ws.security.WSUsernameTokenPrincipal UsernameToken} principal 
+or a {@link java.security.Principal X509Principal}. The 
+princpals contain the names plus other information of the verified username
+token or signature certificate.
+ 
+<h3>Some hints</h3>
+
+<h4>Client</h4>
+At the client side, the WSS4J Axis handler, as all other parts of Axis, run
+in the context of the calling application. Depending on the application,
+the callback classes may perform complex operations, even do some user 
+interaction, to get the password or to access some database to get 
+certificates or keys. There are no timeouts defined at the client side 
+before the SOAP request is put on the wire.
+
+<h4>Server</h4>
+On the server side the WSS4J handler run in the same context as the other part
+of the server, usually some servlet container, such as Tomcat. Also the server
+must be able to handle many requests in a short time. Thus the password 
+callback as well as the <code>Crypto</code> implementation shall be
+as fast as possible. In general, no user interaction is possible at the
+server side to gather passwords. Also at this point of the SOAP request
+processing there are active timeouts, even if they are fairly long.
+
+<h4>Bi-directional SOAP Security</h4>
+WSS4J fully supports bi-directional SOAP security. To enable bi-directional
+support just put <code>WSDoAllSender</code> on the 
+<code>responseFlow</code> at the server and <code>WSDoAllReceiver</code>
+at the response flow of the client thus reversing the roles. Similar to
+the above hints, the server side part (now <code>WSDoAllSender</code>)
+runs in the server context and <code>WSDoAllReceiver</code>
+runs in the application (client) context. There are no Axis timeout
+constraints on the client side after Axis received the response 
+and handed it over to the WSS4J handler.
+
+<h4>Handler chaining</h4>
+Usually WSS4J handlers are chained without any other handler between them in
+the chain. It is, however, possible to do so. In this case the intermediate
+handler <b>must not</b> modify the SOAP Envelope that is contained in the
+Axis message. This could (most probably will) invalidate or destroy any 
+security actions done sofar. Such an intermediate handler may set some 
+properties that may influence the processing of the following WSS4J handler, 
+such as setting a new username, password callback class, and so on.
+
+<!-- Put @see and @since tags down here. -->
+@since WSS4J 1.0
+</body>
+</html>
diff --git a/trunk/src/org/apache/ws/security/CustomTokenPrincipal.java b/trunk/src/org/apache/ws/security/CustomTokenPrincipal.java
new file mode 100644
index 0000000..5901dec
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/CustomTokenPrincipal.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.security;
+
+import org.w3c.dom.Element;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+public class CustomTokenPrincipal implements Principal, Serializable {
+
+
+    private Element tokenElement;
+    private String name;
+    private Object tokenObject;
+    
+    public Object getTokenObject() {
+        return tokenObject;
+    }
+
+    public void setTokenObject(Object tokenObject) {
+        this.tokenObject = tokenObject;
+    }
+
+    public CustomTokenPrincipal(String name) {
+        this.name = name;
+    }
+    
+    public String getName() {
+        return this.name;
+    }
+
+    public Element getTokenElement() {
+        return tokenElement;
+    }
+
+    public void setTokenElement(Element tokenElement) {
+        this.tokenElement = tokenElement;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/SOAP11Constants.java b/trunk/src/org/apache/ws/security/SOAP11Constants.java
new file mode 100644
index 0000000..0650365
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/SOAP11Constants.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import javax.xml.namespace.QName;
+
+/**
+ * SOAP 1.1 constants
+ *
+ * @author Glen Daniels (gdaniels@apache.org)
+ * @author Andras Avar (andras.avar@nokia.com)
+ */
+public class SOAP11Constants implements SOAPConstants {
+    private static QName headerQName = new QName(WSConstants.URI_SOAP11_ENV,
+            WSConstants.ELEM_HEADER);
+    private static QName bodyQName = new QName(WSConstants.URI_SOAP11_ENV,
+            WSConstants.ELEM_BODY);
+    private static QName roleQName = new QName(WSConstants.URI_SOAP11_ENV,
+            WSConstants.ATTR_ACTOR);
+
+    public String getEnvelopeURI() {
+        return WSConstants.URI_SOAP11_ENV;
+    }
+
+    public QName getHeaderQName() {
+        return headerQName;
+    }
+
+    public QName getBodyQName() {
+        return bodyQName;
+    }
+
+    /**
+     * Obtain the QName for the role attribute (actor/role)
+     */
+    public QName getRoleAttributeQName() {
+        return roleQName;
+    }
+
+    /**
+     * Obtain the "next" role/actor URI
+     */
+    public String getNextRoleURI() {
+        return WSConstants.URI_SOAP11_NEXT_ACTOR;
+    }
+
+    /**
+     * Obtain the MustUnderstand string
+     */
+    public String getMustUnderstand() {
+        return "1";
+    }
+    
+    /**
+     * Obtain the MustUnderstand string
+     * @deprecated use getMustUnderstand() instead
+     */
+    public String getMustunderstand() {
+        return getMustUnderstand();
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/SOAP12Constants.java b/trunk/src/org/apache/ws/security/SOAP12Constants.java
new file mode 100644
index 0000000..d589d28
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/SOAP12Constants.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import javax.xml.namespace.QName;
+
+/**
+ * SOAP 1.2 constants
+ *
+ * @author Glen Daniels (gdaniels@apache.org)
+ * @author Andras Avar (andras.avar@nokia.com)
+ */
+public class SOAP12Constants implements SOAPConstants {
+    private static QName headerQName = new QName(WSConstants.URI_SOAP12_ENV,
+            WSConstants.ELEM_HEADER);
+    private static QName bodyQName = new QName(WSConstants.URI_SOAP12_ENV,
+            WSConstants.ELEM_BODY);
+    private static QName roleQName = new QName(WSConstants.URI_SOAP12_ENV,
+            WSConstants.ATTR_ROLE);
+    
+    // Public constants for SOAP 1.2
+    
+    /**
+     * MessageContext property name for webmethod
+     */
+    public static final String PROP_WEBMETHOD = "soap12.webmethod";
+
+    public String getEnvelopeURI() {
+        return WSConstants.URI_SOAP12_ENV;
+    }
+
+    public QName getHeaderQName() {
+        return headerQName;
+    }
+
+    public QName getBodyQName() {
+        return bodyQName;
+    }
+
+    /**
+     * Obtain the QName for the role attribute (actor/role)
+     */
+    public QName getRoleAttributeQName() {
+        return roleQName;
+    }
+
+    /**
+     * Obtain the "next" role/actor URI
+     */
+    public String getNextRoleURI() {
+        return WSConstants.URI_SOAP12_NEXT_ROLE;
+    }
+
+    /**
+     * Obtain the MustUnderstand string
+     */
+    public String getMustUnderstand() {
+        return "true";
+    }
+    
+    /**
+     * Obtain the MustUnderstand string
+     * @deprecated use getMustUnderstand() instead
+     */
+    public String getMustunderstand() {
+        return getMustUnderstand();
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/SOAPConstants.java b/trunk/src/org/apache/ws/security/SOAPConstants.java
new file mode 100644
index 0000000..bf1a0d4
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/SOAPConstants.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import javax.xml.namespace.QName;
+import java.io.Serializable;
+
+/**
+ * An interface definining SOAP constants.  This allows various parts of the
+ * engine to avoid hardcoding dependence on a particular SOAP version and its
+ * associated URIs, etc.
+ * <p/>
+ * This might be fleshed out later to encapsulate factories for behavioral
+ * objects which act differently depending on the SOAP version, but for now
+ * it just supplies common namespaces + QNames.
+ *
+ * @author Glen Daniels (gdaniels@apache.org)
+ * @author Andras Avar (andras.avar@nokia.com)
+ */
+public interface SOAPConstants extends Serializable {
+    /**
+     * SOAP 1.1 constants - thread-safe and shared
+     */
+    public SOAP11Constants SOAP11_CONSTANTS = new SOAP11Constants();
+    /**
+     * SOAP 1.2 constants - thread-safe and shared
+     */
+    public SOAP12Constants SOAP12_CONSTANTS = new SOAP12Constants();
+
+    /**
+     * Obtain the envelope namespace for this version of SOAP
+     */
+    public String getEnvelopeURI();
+
+    /**
+     * Obtain the QName for the Header element
+     */
+    public QName getHeaderQName();
+
+    /**
+     * Obtain the QName for the Body element
+     */
+    public QName getBodyQName();
+
+    /**
+     * Obtain the QName for the role attribute (actor/role)
+     */
+    public QName getRoleAttributeQName();
+
+    /**
+     * Obtain the "next" role/actor URI
+     */
+    public String getNextRoleURI();
+
+    /**
+     * Obtain the "next" role/actor URI
+     */
+    public String getMustUnderstand();
+    
+    /**
+     * Obtain the "next" role/actor URI
+     * @deprecated use getMustUnderstand() instead
+     */
+    public String getMustunderstand();
+    
+    
+
+}
diff --git a/trunk/src/org/apache/ws/security/WSConstants.java b/trunk/src/org/apache/ws/security/WSConstants.java
new file mode 100644
index 0000000..eccaa9c
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSConstants.java
@@ -0,0 +1,490 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import javax.xml.namespace.QName;
+
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.utils.EncryptionConstants;
+
+/**
+ * Constants in WS-Security spec.
+ */
+public class WSConstants {
+    /*
+     * All the various string and keywords required.
+     * 
+     * At first the WSS namespaces as per WSS specifications
+     */
+    public static final String WSSE_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
+    public static final String WSSE11_NS = "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd";
+    public static final String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
+    
+    /*
+     * The base UIRs for the various profiles.
+     */
+    public static final String SOAPMESSAGE_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0";
+    public static final String SOAPMESSAGE_NS11 = "http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1";
+    public static final String USERNAMETOKEN_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0";
+    public static final String X509TOKEN_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0";
+    public static final String SAMLTOKEN_NS = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0";
+    /*
+     * The Element name (local name) of the security header
+     */
+    public static final String WSSE_LN = "Security";
+
+    /*
+     * The Thumbprint relative URI string (without #)
+     * Combine it with SOAPMESSAGE_NS11, #, to get the full URL
+     */
+    public static final String THUMBPRINT ="ThumbprintSHA1";
+    
+    /*
+     * The SAMLAssertionID relative URI string (without #)
+     */
+    public static final String SAML_ASSERTION_ID = "SAMLAssertionID";
+    
+    /*
+     * The EncryptedKeyToken value type URI used in wsse:Reference 
+     */
+    public static final String ENC_KEY_VALUE_TYPE = "EncryptedKey";
+    
+    /*
+     * The relative URI to be used for encrypted key SHA1 (Without #)
+     * Combine it with SOAPMESSAGE_NS11, #, to get the full URL
+     */
+    public static final String ENC_KEY_SHA1_URI = "EncryptedKeySHA1";
+    
+    /*
+     * The namespace prefixes used. We uses the same prefix convention
+     * as shown in the specifications
+     */
+    public static final String WSSE_PREFIX = "wsse";
+    public static final String WSSE11_PREFIX = "wsse11";
+    public static final String WSU_PREFIX = "wsu";
+    
+    /*
+     * Now the namespaces, local names, and prefixes of XML-SIG and XML-ENC
+     */
+    public static final String SIG_NS = "http://www.w3.org/2000/09/xmldsig#";
+    public static final String SIG_PREFIX = "ds";
+    public static final String SIG_LN = "Signature";
+    public static final String ENC_NS = "http://www.w3.org/2001/04/xmlenc#";
+    public static final String ENC_PREFIX = "xenc";
+    public static final String ENC_KEY_LN = "EncryptedKey";
+    public static final String ENC_DATA_LN = "EncryptedData";
+    public static final String REF_LIST_LN = "ReferenceList";
+
+    /*
+     * The standard namesace definitions
+     */
+    public static final String XMLNS_NS = "http://www.w3.org/2000/xmlns/";
+    public static final String XML_NS = "http://www.w3.org/XML/1998/namespace";
+    
+    /*
+     * The local names and attribute names used by WSS
+     */
+    public static final String USERNAME_TOKEN_LN = "UsernameToken";
+    public static final String BINARY_TOKEN_LN = "BinarySecurityToken";
+    public static final String TIMESTAMP_TOKEN_LN = "Timestamp";
+    public static final String USERNAME_LN = "Username";
+    public static final String PASSWORD_LN = "Password";
+    public static final String PASSWORD_TYPE_ATTR = "Type";
+    public static final String NONCE_LN = "Nonce";
+    public static final String CREATED_LN = "Created";
+    public static final String EXPIRES_LN = "Expires";
+    public static final String SIGNATURE_CONFIRMATION_LN = "SignatureConfirmation"; 
+    public static final String SALT_LN = "Salt";
+    public static final String ITERATION_LN = "Iteration";
+    
+    /*
+     * The definitions for SAML
+     */
+    public static final String SAML_NS = "urn:oasis:names:tc:SAML:1.0:assertion";
+    public static final String SAMLP_NS = "urn:oasis:names:tc:SAML:1.0:protocol";
+    public static final String ASSERTION_LN = "Assertion";
+    public static final String WSS_SAML_NS = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#";
+    public static final String WSS_SAML_ASSERTION = "SAMLAssertion-1.1";
+
+    //
+    // SOAP-ENV Namespaces
+    //
+    public static final String URI_SOAP11_ENV =
+            "http://schemas.xmlsoap.org/soap/envelope/";
+    public static final String URI_SOAP12_ENV =
+            "http://www.w3.org/2003/05/soap-envelope";
+
+    public static final String[] URIS_SOAP_ENV = {
+        URI_SOAP11_ENV,
+        URI_SOAP12_ENV,
+    };
+
+    // Misc SOAP Namespaces / URIs
+    public static final String URI_SOAP11_NEXT_ACTOR =
+            "http://schemas.xmlsoap.org/soap/actor/next";
+    public static final String URI_SOAP12_NEXT_ROLE =
+            "http://www.w3.org/2003/05/soap-envelope/role/next";
+    public static final String URI_SOAP12_NONE_ROLE =
+            "http://www.w3.org/2003/05/soap-envelope/role/none";
+    public static final String URI_SOAP12_ULTIMATE_ROLE =
+            "http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver";
+
+    public static final String ELEM_ENVELOPE = "Envelope";
+    public static final String ELEM_HEADER = "Header";
+    public static final String ELEM_BODY = "Body";
+
+    public static final String ATTR_MUST_UNDERSTAND = "mustUnderstand";
+    public static final String ATTR_ACTOR = "actor";
+    public static final String ATTR_ROLE = "role";
+
+    public static final String NULL_NS = "Null";
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSSAddUsernameToken#build(Document, String, String) UserNameToken}
+     * method to use a password digest to send the password information
+     * <p/>
+     * This is a required method as defined by WS Specification, Username token profile.
+     */
+    public static final String PW_DIGEST = "PasswordDigest";
+    /*
+     * The password type URI used in the username token 
+     */
+    public static final String PASSWORD_DIGEST = USERNAMETOKEN_NS + "#PasswordDigest";
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSSAddUsernameToken#build(Document, String, String) UserNameToken}
+     * method to send the password in clear
+     * <p/>
+     * This is a required method as defined by WS Specification, Username token profile.
+     */
+    public static final String PW_TEXT = "PasswordText";
+    /*
+     * The password type URI used in the username token 
+     */
+    public static final String PASSWORD_TEXT = USERNAMETOKEN_NS + "#PasswordText";
+    
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSSAddUsernameToken#build(Document, String, String) UserNameToken}
+     * method to send _no_ password related information. 
+     * <p/>
+     * This is a required method as defined by WS Specification, Username token profile as passwords are optional.
+     * Also see the WS-I documentation for scenario's using this feature in a trust environment.
+     */ 
+    public static final String PW_NONE = "PasswordNone";
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSEncryptBody#build(Document, Crypto) encryption}
+     * method to encrypt the symmetric data encryption key with the RSA algoritm.
+     * <p/>
+     * This is a required method as defined by XML encryption.
+     */
+    public static final String KEYTRANSPORT_RSA15 = EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSEncryptBody#build(Document, Crypto) encryption}
+     * method to encrypt the symmetric data encryption key with the RSA algoritm.
+     * <p/>
+     * This is a required method as defined by XML encryption.
+     * <p/>
+     * NOTE: This algorithm is not yet supported by WSS4J
+     */
+    public static final String KEYTRANSPORT_RSAOEP = EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSEncryptBody#build(Document, Crypto) encryption}
+     * method to use triple DES as the symmetric algorithm to encrypt data.
+     * <p/>
+     * This is a required method as defined by XML encryption.
+     * The String to use in WSDD file (in accordance to w3c specifications:
+     * <br/>
+     * http://www.w3.org/2001/04/xmlenc#tripledes-cbc
+     */
+    public static final String TRIPLE_DES = EncryptionConstants.ALGO_ID_BLOCKCIPHER_TRIPLEDES;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSEncryptBody#build(Document, Crypto) encryption}
+     * method to use AES with 128 bit key as the symmetric algorithm to encrypt data.
+     * <p/>
+     * This is a required method as defined by XML encryption.
+     * The String to use in WSDD file (in accordance to w3c specifications:
+     * <br/>
+     * http://www.w3.org/2001/04/xmlenc#aes128-cbc
+     */
+    public static final String AES_128 = EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSEncryptBody#build(Document, Crypto) encryption}
+     * method to use AES with 256 bit key as the symmetric algorithm to encrypt data.
+     * <p/>
+     * This is a required method as defined by XML encryption.
+     * The String to use in WSDD file (in accordance to w3c specifications:
+     * <br/>
+     * http://www.w3.org/2001/04/xmlenc#aes256-cbc
+     */
+    public static final String AES_256 = EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSEncryptBody#build(Document, Crypto) encryption}
+     * method to use AES with 192 bit key as the symmetric algorithm to encrypt data.
+     * <p/>
+     * This is a optional method as defined by XML encryption.
+     * The String to use in WSDD file (in accordance to w3c specifications:
+     * <br/>
+     * http://www.w3.org/2001/04/xmlenc#aes192-cbc
+     */
+    public static final String AES_192 = EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSSignEnvelope#build(Document, Crypto) signature}
+     * method to use DSA with SHA1 (DSS) to sign data.
+     * <p/>
+     * This is a required method as defined by XML signature.
+     */
+    public static final String DSA = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSSignEnvelope#build(Document, Crypto) signature}
+     * method to use RSA with SHA to sign data.
+     * <p/>
+     * This is a recommended method as defined by XML signature.
+     */
+    public static final String RSA = XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;
+
+    public static final String C14N_OMIT_COMMENTS = Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS;
+    public static final String C14N_WITH_COMMENTS = Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS;
+    public static final String C14N_EXCL_OMIT_COMMENTS = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
+    public static final String C14N_EXCL_WITH_COMMENTS = Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSSignEnvelope#build(Document, Crypto) signing}
+     * method to send the signing certificate as a
+     * <code>BinarySecurityToken</code>.
+     * <p/>
+     * The signing method takes the signing certificate, converts it to a
+     * <code>BinarySecurityToken</code>, puts it in the security header,
+     * and inserts a <code>Reference</code> to the binary security token
+     * into the <code>wsse:SecurityReferenceToken</code>. Thus the whole
+     * signing certificate is transfered to the receiver.
+     * The X509 profile recommends to use {@link #ISSUER_SERIAL} instead
+     * of sending the whole certificate.
+     * <p/>
+     * Please refer to WS Security specification X509 profile, chapter 3.3.2
+     * and to WS Security specification, chapter 7.2
+     * <p/>
+     * Note: only local refernces to BinarySecurityToken are supported
+     */
+    public static final int BST_DIRECT_REFERENCE = 1;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSSignEnvelope#build(Document, Crypto) signing}
+     * or the {@link org.apache.ws.security.message.WSEncryptBody#build(Document, Crypto) encryption}
+     * method to send the issuer name and the serial number of a
+     * certificate to the receiver.
+     * <p/>
+     * In contrast to {@link #BST_DIRECT_REFERENCE} only the issuer name
+     * and the serial number of the signiung certificate are sent to the
+     * receiver. This reduces the amount of data being sent. The encryption
+     * method uses the public key associated with this certificate to encrypt
+     * the symmetric key used to encrypt data.
+     * <p/>
+     * Please refer to WS Security specification X509 profile, chapter 3.3.3
+     */
+    public static final int ISSUER_SERIAL = 2;
+
+    /**
+     * Sets the {@link org.apache.ws.security.message.WSEncryptBody#build(Document, Crypto) encryption}
+     * method to send the certificate used to encrypt the symmetric key.
+     * <p/>
+     * The encryption method uses the public key associated with this certificate
+     * to encrypr the symmetric key used to encrypt data. The certificate is
+     * converted into a <code>KeyIdentfier</code> token and sent to the receiver.
+     * Thus the complete certificate data is transfered to receiver.
+     * The X509 profile recommends to use {@link #ISSUER_SERIAL} instead
+     * of sending the whole certificate.
+     * <p/>
+     * <p/>
+     * Please refer to WS Security specification X509 profile, chapter 7.3
+     */
+    public static final int X509_KEY_IDENTIFIER = 3;
+    /**
+     * Sets the
+     * {@link org.apache.ws.security.message.WSSignEnvelope#build(Document, Crypto)
+     * signing}
+     * method to send a <code>SubjectKeyIdentifier</code> to identify
+     * the signing certificate.
+     * <p/>
+     * Refer to WS Security specification X509 profile, chapter 3.3.1
+     * This identification token is not yet fully tested by WSS4J. The
+     * WsDoAllSender does not include the X.509 certificate as
+     * <code>BinarySecurityToken</code> in the request message.
+     */
+    public static final int SKI_KEY_IDENTIFIER = 4;
+
+    /**
+     * Embeds a keyinfo/key name into the EncryptedData element.
+     * <p/>
+     * Refer to WS Security specification X509 profile
+     */
+    public static final int EMBEDDED_KEYNAME = 5;
+    /**
+     * Embeds a keyinfo/wsse:SecurityTokenReference into EncryptedData element.
+     */
+    public static final int EMBED_SECURITY_TOKEN_REF = 6;
+    
+    /**
+     * <code>UT_SIGNING</code> is used internally only to set a specific Signature
+     * behavior.
+     * 
+     * The signing token is constructed from values in the UsernameToken according
+     * to WS-Trust specification.
+     */
+    public static final int UT_SIGNING = 7;
+    
+    /**
+     * <code>THUMPRINT_IDENTIFIER</code> is used to set the specific key identifier
+     * ThumbprintSHA1.
+     * 
+     * This identifier uses the SHA-1 digest of a security token to
+     * identify the security token. Please refer to chapter 7.2 of the OASIS WSS 1.1
+     * specification.
+     * 
+     */
+    public static final int THUMBPRINT_IDENTIFIER = 8;
+    
+    /**
+     * <code>CUSTOM_SYMM_SIGNING</code> is used internally only to set a 
+     * specific Signature behavior.
+     * 
+     * The signing key, reference id and value type are set externally. 
+     */
+    public static final int CUSTOM_SYMM_SIGNING = 9;
+    
+    /**
+     * <code>ENCRYPTED_KEY_SHA1_IDENTIFIER</code> is used to set the specific key identifier
+     * ThumbprintSHA1.
+     * 
+     * This identifier uses the SHA-1 digest of a security token to
+     * identify the security token. Please refer to chapter 7.3 of the OASIS WSS 1.1
+     * specification.
+     * 
+     */
+    public static final int ENCRYPTED_KEY_SHA1_IDENTIFIER = 10;
+    
+    
+    public static final String ENCRYPTED_HEADER = "EncryptedHeader";
+
+    /*
+     * The following values are bits that can be combined to for a set.
+     * Be careful when selecting new values.
+     */
+    public static final int NO_SECURITY = 0;
+    public static final int UT = 0x1; // perform UsernameToken
+    public static final int SIGN = 0x2; // Perform Signature
+    public static final int ENCR = 0x4; // Perform Encryption
+
+    /*
+     * Attention: the signed/Unsigned types identify if WSS4J uses
+     * the SAML token for signature, signature key or not. It does
+     * not mean if the token contains an enveloped signature.
+     */
+    public static final int ST_UNSIGNED = 0x8; // perform SAMLToken unsigned
+    public static final int ST_SIGNED = 0x10; // perform SAMLToken signed
+
+    public static final int TS = 0x20; // insert Timestamp
+    public static final int UT_SIGN = 0x40; // perform sinagture with UT secrect key
+    public static final int SC = 0x80;      // this is a SignatureConfirmation
+
+    public static final int NO_SERIALIZE = 0x100;
+    public static final int SERIALIZE = 0x200;
+    public static final int SCT = 0x400; //SecurityContextToken
+    public static final int DKT = 0x800; //DerivedKeyToken
+    public static final int BST = 0x1000; //BinarySecurityToken
+
+    /**
+     * Length of UsernameToken derived key used by .NET WSE to sign a message.
+     */
+    public static final int WSE_DERIVED_KEY_LEN = 16;
+    public static final String LABEL_FOR_DERIVED_KEY = "WS-Security";
+    
+    /**
+     * WS-Trust namespace
+     */
+    public static final String WST_NS = "http://schemas.xmlsoap.org/ws/2005/02/trust";
+    
+    public final static String WSC_SCT = "http://schemas.xmlsoap.org/ws/2005/02/sc/sct";
+    
+    //
+    // Fault codes defined in the WSS 1.1 spec under section 12, Error handling
+    //
+    
+    /**
+     * An unsupported token was provided
+     */
+    public static final QName UNSUPPORTED_SECURITY_TOKEN = new QName(WSSE_NS, "UnsupportedSecurityToken");
+    
+    /**
+     * An unsupported signature or encryption algorithm was used
+     */
+    public static final QName UNSUPPORTED_ALGORITHM  = new QName(WSSE_NS, "UnsupportedAlgorithm");
+    
+    /**
+     * An error was discovered processing the <Security> header
+     */
+    public static final QName INVALID_SECURITY = new QName (WSSE_NS, "InvalidSecurity");
+    
+    /**
+     * An invalid security token was provided
+     */
+    public static final QName INVALID_SECURITY_TOKEN = new QName (WSSE_NS, "InvalidSecurityToken");
+    
+    /**
+     * The security token could not be authenticated or authorized
+     */
+    public static final QName FAILED_AUTHENTICATION = new QName (WSSE_NS, "FailedAuthentication");
+    
+    /**
+     * The signature or decryption was invalid
+     */
+    public static final QName FAILED_CHECK = new QName (WSSE_NS, "FailedCheck");
+    
+    /** 
+     * Referenced security token could not be retrieved
+     */
+    public static final QName SECURITY_TOKEN_UNAVAILABLE = new QName (WSSE_NS, "SecurityTokenUnavailable");
+    
+    /** 
+     * The message has expired
+     */
+    public static final QName MESSAGE_EXPIRED = new QName (WSSE_NS, "MessageExpired");
+    
+    /**
+     * Header type in <code>org.apache.ws.security.WSEncryptionPart</code>
+     */
+    public static final int PART_TYPE_HEADER = 1;
+    
+    /**
+     * Body type in <code>org.apache.ws.security.WSEncryptionPart</code>
+     */
+    public static final int PART_TYPE_BODY = 2;
+    
+    /**
+     * Element type in <code>org.apache.ws.security.WSEncryptionPart</code>
+     */
+    public static final int PART_TYPE_ELEMENT = 3;
+    
+}
diff --git a/trunk/src/org/apache/ws/security/WSDataRef.java b/trunk/src/org/apache/ws/security/WSDataRef.java
new file mode 100644
index 0000000..cd103fe
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSDataRef.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+/**
+ * WSDataRef stores information about decrypted elements
+ * 
+ * When a processor decrypts an elements it stores information 
+ * about that element in a WSDataRef so these information can 
+ * be used for validation stages 
+ * 
+ */
+
+import javax.xml.namespace.QName;
+
+public class WSDataRef {
+    
+    /**
+     * reference by which the Encrypted Data was referred 
+     */
+    private String dataref;
+    
+    /**
+     * wsu:Id of the decrypted element (if present)
+     */
+    private String wsuId;
+    
+    /**
+     * QName of the decrypted element
+     */
+    private QName name;
+    
+    
+    /**
+     * @param dataref reference by which the Encrypted Data was referred 
+     */
+    public WSDataRef(String dataref) {
+        this.dataref = dataref;
+    }
+    
+    /**
+     * @param dataref reference by which the Encrypted Data was referred 
+     * @param wsuId Id of the decrypted element (if present)
+     */
+    public WSDataRef(String dataref, String wsuId) {
+        this.dataref = dataref;
+        this.wsuId = wsuId;
+    }
+    
+    /**
+     * @param dataref reference by which the Encrypted Data was referred 
+     * @param wsuId Id of the decrypted element (if present)
+     * @param name QName of the decrypted element
+     */
+    public WSDataRef(String dataref, String wsuId, QName name) {
+        this.dataref = dataref;
+        this.wsuId = wsuId;
+        this.name = name;
+    }
+
+    /**
+     * @return the data reference 
+     */
+    public String getDataref() {
+        return dataref;
+    }
+
+    /**
+     * @param dataref reference by which the Encrypted Data was referred 
+     */
+    public void setDataref(String dataref) {
+        this.dataref = dataref;
+    }
+
+    /**
+     * @return Id of the decrypted element (if present)
+     */
+    public String getWsuId() {
+        return wsuId;
+    }
+
+    /**
+     * @param wsuId Id of the decrypted element (if present)
+     */
+    public void setWsuId(String wsuId) {
+        this.wsuId = wsuId;
+    }
+
+    /**
+     * @return QName of the decrypted element
+     */
+    public QName getName() {
+        return name;
+    }
+
+    /**
+     * @param name QName of the decrypted element
+     */
+    public void setName(QName name) {
+        this.name = name;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/WSDerivedKeyTokenPrincipal.java b/trunk/src/org/apache/ws/security/WSDerivedKeyTokenPrincipal.java
new file mode 100644
index 0000000..6d5cf68
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSDerivedKeyTokenPrincipal.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import java.security.Principal;
+
+/**
+ * This class implements the <code>Principal</code> interface and
+ * represents a <code>DerivedKeyToken</code>.
+ * The principal's name will be the <code>wsu:Id</code> valud of the 
+ * <code>DerivedKeyToken</code>
+ * 
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public class WSDerivedKeyTokenPrincipal implements Principal {
+
+    private String id;
+    private String nonce;
+    private String label;
+    private int length;
+    private int offset;
+    private String basetokenId;
+    
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public int getLength() {
+        return length;
+    }
+
+    public void setLength(int length) {
+        this.length = length;
+    }
+
+    public int getOffset() {
+        return offset;
+    }
+
+    public void setOffset(int offset) {
+        this.offset = offset;
+    }
+
+    public String getNonce() {
+        return nonce;
+    }
+
+    public WSDerivedKeyTokenPrincipal(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return id;
+    }
+    
+    public void setNonce(String nonce) {
+        this.nonce = nonce;
+    }
+
+    public String getBasetokenId() {
+        return basetokenId;
+    }
+
+    public void setBasetokenId(String basetokenId) {
+        this.basetokenId = basetokenId;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/WSDocInfo.java b/trunk/src/org/apache/ws/security/WSDocInfo.java
new file mode 100644
index 0000000..49d6941
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSDocInfo.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+/**
+ * WSDocInfo holds information about the document to process. Together
+ * with the WSDocInfoStore it provides a method to store and access document
+ * information about BinarySecurityToken, used Crypto, and others.
+ * </p>
+ * Using the Document's hash a caller can identify a document and get
+ * the stored information that me be necessary to process the document.
+ * The main usage for this is (are) the transformation functions that
+ * are called during Signature/Verification process. 
+ * 
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com)
+ *
+ */
+
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.processor.Processor;
+import org.w3c.dom.Element;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class WSDocInfo {
+    int hash;
+    Crypto crypto = null;
+    Vector bst = null;
+    Element assertion = null;
+    Vector processors = null;
+
+    public WSDocInfo(int hash) {
+        this.hash = hash;
+    }
+
+    /**
+     * Clears the info data except the hash code
+     */
+    public void clear() {
+        crypto = null;
+        assertion = null;
+        if (bst != null && bst.size() > 0) {
+            bst.removeAllElements();
+        }
+        if (processors != null && processors.size() > 0) {
+            processors.removeAllElements();
+        }
+        
+        bst = null;
+        processors = null;
+    }
+
+    /**
+     * Get a BinarySecurityToken for the given Id
+     *
+     * @param uri is the relative uri (starts with #) of the id
+     * @return the BST element or null if nothing found
+     */
+    public Element getBst(String uri) {
+        String id = uri.substring(1);
+        Element elem = null;
+
+        if (bst != null) {
+            for (Enumeration e = bst.elements(); e.hasMoreElements();) {
+                elem = (Element) e.nextElement();
+                String cId = elem.getAttribute("Id");
+                if (id.equals(cId)) {
+                    break;
+                }
+            }
+        }
+        return elem;
+    }
+
+    /**
+     * Get a Processor for the given Id
+     *
+     * @param id is the Id to look for
+     * @return the Security processor identified with this Id or null if nothing found
+     */
+    public Processor getProcessor(String id) {
+        
+        if (id == null) {
+                return null;
+            }
+
+            Processor p = null;
+        if (processors != null) {
+            for (Enumeration e = processors.elements(); e.hasMoreElements();) {
+                p = (Processor) e.nextElement();
+                String cId = p.getId();
+                if (id.equals(cId)) {
+                    return p;
+                }
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * Store a Processor for later access.
+     * 
+     * @param p is the Processor to store
+     */
+    public void setProcessor(Processor p) {
+        if (processors == null) {
+            processors = new Vector();
+        }
+        processors.add(p);
+    }
+    
+    /**
+     * @return the signature crypto class used to process
+     *         the signature/verify
+     */
+    public Crypto getCrypto() {
+        return crypto;
+    }
+
+    /**
+     * @return the hash value of the document
+     */
+    public int getHash() {
+        return hash;
+    }
+
+    /**
+     * @param elem is the BinarySecurityToken to store
+     */
+    public void setBst(Element elem) {
+        if (bst == null) {
+            bst = new Vector();
+        }
+        bst.add(elem);
+    }
+
+    /**
+     * @param crypto is the signature crypto class used to
+     *               process signature/verify
+     */
+    public void setCrypto(Crypto crypto) {
+        this.crypto = crypto;
+    }
+
+    /**
+     * @return Returns the assertion.
+     */
+    public Element getAssertion() {
+        return assertion;
+    }
+
+    /**
+     * @param assertion The assertion to set.
+     */
+    public void setAssertion(Element assertion) {
+        this.assertion = assertion;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/WSDocInfoStore.java b/trunk/src/org/apache/ws/security/WSDocInfoStore.java
new file mode 100644
index 0000000..0a7464b
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSDocInfoStore.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+/**
+ * WSDocInfoStore store WSDocInfo structure in a static Hash. 
+ * 
+ * Also the access methods are static. Thus it is possible to exchange
+ * WSDocInfo between otherwise unrelated functions/methods.
+ * The main usage for this is (are) the transformation functions that
+ * are called during Signature/Verfication process. 
+ * 
+ * @author Werner Dittmann (Werner.Dittmann@apache.org)
+ */
+
+import java.util.Hashtable;
+
+public class WSDocInfoStore {
+
+    static Hashtable storage = new Hashtable(10);
+
+    public static WSDocInfo lookup(int hash) {
+        Integer intObj = new Integer(hash);
+        return (WSDocInfo) storage.get(intObj);
+    }
+
+    public static void store(WSDocInfo info) {
+        Integer intObj = new Integer(info.getHash());
+        if (storage.containsKey(intObj)) {
+            return;
+        }
+        storage.put(intObj, info);
+    }
+
+    public static void delete(int hash) {
+        Integer intObj = new Integer(hash);
+        WSDocInfo wsInfo = (WSDocInfo) storage.get(intObj);
+        if (wsInfo != null) {
+            storage.remove(intObj);
+        }
+    }
+
+    public static void delete(WSDocInfo info) {
+        delete(info.getHash());
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/WSEncryptionPart.java b/trunk/src/org/apache/ws/security/WSEncryptionPart.java
new file mode 100644
index 0000000..be34f9b
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSEncryptionPart.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+/**
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com)
+ */
+public class WSEncryptionPart {
+
+    private String name;
+    private String namespace;
+    private String encModifier;
+    private String encId;
+    private String id;
+    
+    /**
+     * Types of WSEncryptionPart
+     * <code>org.apache.ws.security.WSConstants.PART_TYPE_HEADER</code>
+     * <code>org.apache.ws.security.WSConstants.PART_TYPE_BODY</code>
+     * <code>org.apache.ws.security.WSConstants.PART_TYPE_ELEMENT</code>
+     */
+    private int type = -1;
+
+    /**
+     * Constructor to initialize part structure with element, namespace, and modifier.
+     * 
+     * This constructor initializes the parts structure to lookup for a
+     * fully qualified name of an element to encrypt or sign. The modifier
+     * controls how encryption encrypts the element, signature processing does
+     * not use the modifier information.
+     * 
+     * <p/>
+     * 
+     * Regarding the modifier ("Content" or "Element") refer to the W3C
+     * XML Encryption specification. 
+     * 
+     * @param nm Element's name
+     * @param nmspace Element's namespace
+     * @param encMod The encryption modifier
+     */
+    public WSEncryptionPart(String nm, String nmspace, String encMod) {
+        name = nm;
+        namespace = nmspace;
+        encModifier = encMod;
+        id = null;
+    }
+    
+    /**
+     * Constructor to initialize part structure with element, namespace, and modifier,type.
+     * 
+     * This constructor initializes the parts structure to lookup for a
+     * fully qualified name of an element to encrypt or sign. The modifier
+     * controls how encryption encrypts the element, signature processing does
+     * not use the modifier information.
+     * 
+     * <p/>
+     * 
+     * Regarding the modifier ("Content" or "Element") refer to the W3C
+     * XML Encryption specification. 
+     * 
+     * @param nm Element's name
+     * @param nmspace Element's namespace
+     * @param encMod The encryption modifier
+     * @param type Type of the WSEncryptionPart
+     */
+    public WSEncryptionPart(String nm, String nmspace, String encMod, int type) {
+        name = nm;
+        namespace = nmspace;
+        encModifier = encMod;
+        this.type = type;
+        id = null;
+    }
+
+    /**
+     * Constructor to initialize part structure with element id.
+     * 
+     * This constructor initializes the parts structure to lookup for a
+     * an element with the given Id to encrypt or sign. 
+     * 
+     * @param id The Id to of the element to process
+     */
+    public WSEncryptionPart(String id) {
+        this.id = id;
+        name = namespace = encModifier = null;
+    }
+    
+    /**
+     * Constructor to initialize part structure with element id and modifier.
+     * 
+     * This constructor initializes the parts structure to lookup for a
+     * an element with the given Id to encrypt or sign. The modifier
+     * controls how encryption encrypts the element, signature processing does
+     * not use the modifier information.
+     * 
+     * <p/>
+     * 
+     * Regarding the modifier ("Content" or "Element") refer to the W3C
+     * XML Encryption specification. 
+     * 
+     * @param id The Id to of the element to process
+     * @param encMod The encryption modifier
+     */
+    public WSEncryptionPart(String id, String encMod) {
+        this.id = id;
+        encModifier = encMod;
+        name = namespace = null;
+    }
+    
+    /**
+     * Constructor to initialize part structure with element id, modifier and type.
+     * 
+     * This constructor initializes the parts structure to lookup for a
+     * an element with the given Id to encrypt or sign. The modifier
+     * controls how encryption encrypts the element, signature processing does
+     * not use the modifier information. 
+     * 
+     * <p/>
+     * 
+     * Regarding the modifier ("Content" or "Element") refer to the W3C
+     * XML Encryption specification. 
+     * 
+     * @param id The Id to of the element to process
+     * @param encMod The encryption modifier
+     * @param type of the element
+     */
+    public WSEncryptionPart(String id, String encMod,int type) {
+        this.id = id;
+        encModifier = encMod;
+        this.type = type;
+        name = namespace = null;
+    }
+
+    /**
+     * @return the local name of the element to encrypt.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @return the namespace of the element to encrypt
+     */
+    public String getNamespace() {
+        return namespace;
+    }
+
+    /**
+     * @return the encryption modifier
+     */
+    public String getEncModifier() {
+        return encModifier;
+    }
+
+    /**
+     * @return Returns the id.
+     */
+    public String getId() {
+        return id;
+    }
+    
+    public void setEncId (String id) {
+        encId = id;
+    }
+    
+    public String getEncId() {
+        return encId;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public void setType(int type) {
+        this.type = type;
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/WSPasswordCallback.java b/trunk/src/org/apache/ws/security/WSPasswordCallback.java
new file mode 100644
index 0000000..6511fb4
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSPasswordCallback.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.Callback;
+
+/**
+ * Simple class to provide a password callback mechanism.
+ * <p/>
+ * It uses the JAAS authentication mechanisms and callback methods.
+ * In addition to the identifier (user name) this class also provides
+ * information what type of information the callback <code>handle</code>
+ * method shall provide.
+ * <p/>
+ * The <code> WSPasswordCallback</code> class defines the following usage
+ * codes:
+ * <ul>
+ * <li><code>UNKNOWN</code> - an unknown usage. Never used by the WSS4J
+ * implementation and shall be treated as an error by the <code>handle
+ * </code> method.</li>
+ * <li><code>DECRYPT</code> - need a password to get the private key of
+ * this identifier (username) from the keystore. WSS4J uses this private
+ * key to decrypt the session (symmetric) key. Because the encryption
+ * method uses the public key to encrypt the session key it needs no
+ * password (a public key is usually not protected by a password).</li>
+ * <li><code>USERNAME_TOKEN</code> - need the password to fill in or to
+ * verify a <code>UsernameToken</code>.</li>
+ * <li><code>SIGNATURE</code> - need the password to get the private key of
+ * this identifier (username) from    the keystore. WSS4J uses this private
+ * key to produce a signature. The signature verification uses the public
+ * key to verify the signature.</li>
+ * <li><code>KEY_NAME</code> - need the <i>key</i>, not the password,
+ * associated with the identifier. WSS4J uses this key to encrypt or
+ * decrypt parts of the SOAP request. Note, the key must match the
+ * symmetric encryption/decryption algorithm specified (refer to
+ * {@link org.apache.ws.security.handler.WSHandlerConstants#ENC_SYM_ALGO}).</li>
+ * <li><code>USERNAME_TOKEN_UNKNOWN</code> - either an not specified 
+ * password type or a password type passwordText. In these both cases <b>only</b>
+ * the password variable is <b>set</b>. The callback class now may check if
+ * the username and password match. If they don't match the callback class must
+ * throw an exception. The exception can be a UnsupportedCallbackException or
+ * an IOException.</li>
+ * <li><code>SECURITY_CONTEXT_TOKEN</code> - need the key to to be associated 
+ * with a <code>wsc:SecurityContextToken</code>.</li>
+ * </ul>
+ *
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com).
+ */
+
+public class WSPasswordCallback implements Callback {
+
+    public static final int UNKNOWN = 0;
+    public static final int DECRYPT = 1;
+    public static final int USERNAME_TOKEN = 2;
+    public static final int SIGNATURE = 3;
+    public static final int KEY_NAME = 4;
+    public static final int USERNAME_TOKEN_UNKNOWN = 5;
+    public final static int SECURITY_CONTEXT_TOKEN = 6;
+    public final static int CUSTOM_TOKEN = 7;
+    public final static int ENCRYPTED_KEY_TOKEN = 8;
+    
+    private String identifier;
+    private String password;
+    private byte[] key;
+    private int usage;
+    private String passwordType;
+    private Element customToken;
+    
+    /**
+     * Constructor.
+     *
+     * @param id The application called back must supply the password for
+     *           this identifier.
+     */
+    public WSPasswordCallback(String id, int usage) {
+        this(id, null, null, usage);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param id The application called back must supply the password for
+     *           this identifier.
+     */
+    public WSPasswordCallback(String id, String pw, String type, int usage) {
+        identifier = id;
+        password = pw;
+        passwordType = type;
+        this.usage = usage;
+    }
+    /**
+     * Get the identifier.
+     * <p/>
+     *
+     * @return The identifier
+     */
+    public String getIdentifier() {
+        return identifier;
+    }
+    
+    /**
+     * Get the identifier.
+     * <p/>
+     *
+     * @return The identifier
+     * @deprecated use getIdentifier() instead
+     */
+    public String getIdentifer() {
+        return getIdentifier();
+    }
+    
+    /**
+     * Extended callback interface allows for setting the username as well.
+     * Callback functions can change the identifier, this is intended in the usernametoken scenario
+     * where the usernametoken denotes the identity, but a fixed identity for signing is used
+     * The initial value is that from the configuration file. If this method is not called, the
+     * configured identity is used.
+     * 
+     * @param ident The identity.
+     */
+    public void setIdentifier(String ident) {
+        this.identifier = ident;
+    }
+
+    /**
+     * Set the password.
+     * <p/>
+     *
+     * @param passwd is the password associated to the identifier
+     */
+    public void setPassword(String passwd) {
+        password = passwd;
+    }
+
+    /**
+     * Get the password.
+     * <p/>
+     *
+     * @return The password
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Set the Key.
+     * <p/>
+     *
+     * @param key is the key associated to the identifier
+     */
+    public void setKey(byte[] key) {
+        this.key = key;
+    }
+
+    /**
+     * Get the key.
+     * <p/>
+     *
+     * @return The key
+     */
+    public byte[] getKey() {
+        return this.key;
+    }
+
+    /**
+     * Get the usage.
+     * <p/>
+     *
+     * @return The usage for this callback
+     */
+    public int getUsage() {
+        return usage;
+    }
+    /**
+     * The password type is only relevant for usage <code>USERNAME_TOKEN</code>
+     * and <code>USERNAME_TOKEN_UNKNOWN</code>.
+     * 
+     * @return Returns the passwordType.
+     */
+    public String getPasswordType() {
+        return passwordType;
+    }
+
+    public Element getCustomToken() {
+        return customToken;
+    }
+
+    public void setCustomToken(Element customToken) {
+        this.customToken = customToken;
+    }
+}
+
+
diff --git a/trunk/src/org/apache/ws/security/WSSConfig.java b/trunk/src/org/apache/ws/security/WSSConfig.java
new file mode 100644
index 0000000..cf350f7
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSSConfig.java
@@ -0,0 +1,492 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import java.util.HashMap;
+
+import javax.xml.namespace.QName;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.action.Action;
+import org.apache.ws.security.processor.Processor;
+import org.apache.ws.security.transform.STRTransform;
+import org.apache.ws.security.util.Loader;
+import org.apache.xml.security.transforms.Transform;
+
+/**
+ * WSSConfig <p/> Carries configuration data so the WSS4J spec compliance can be
+ * modified in runtime. Configure an instance of this object only if you need
+ * WSS4J to emulate certain industry clients or previous OASIS specifications
+ * for WS-Security interoperability testing purposes. <p/> The default settings
+ * follow the latest OASIS and changing anything might violate the OASIS specs.
+ * <p/> <b>WARNING: changing the default settings will break the compliance with
+ * the latest specs. Do this only if you know what you are doing.</b> <p/>
+ * 
+ * @author Rami Jaamour (rjaamour@parasoft.com)
+ * @author Werner Dittmann (werner@apache.org)
+ */
+public class WSSConfig {
+    
+    private static final Log log = LogFactory.getLog(WSSConfig.class.getName());
+
+    /**
+     * The default collection of actions supported by the toolkit.
+     */
+    private static final java.util.Map DEFAULT_ACTIONS;
+    static {
+        final java.util.Map tmp = new java.util.HashMap();
+        try {
+            tmp.put(
+                new Integer(WSConstants.UT),
+                org.apache.ws.security.action.UsernameTokenAction.class.getName()
+            );
+            tmp.put(
+                new Integer(WSConstants.ENCR),
+                org.apache.ws.security.action.EncryptionAction.class.getName()
+            );
+            tmp.put(
+                new Integer(WSConstants.SIGN),
+                org.apache.ws.security.action.SignatureAction.class.getName()
+            );
+            //
+            // Note that all actions/processors with dependencies on opensaml are
+            // registered as Strings. This is so that applications that do not use
+            // saml do not have to have the opensaml jar available.
+            //
+            tmp.put(
+                new Integer(WSConstants.ST_SIGNED),
+                "org.apache.ws.security.action.SAMLTokenSignedAction"
+            );
+            tmp.put(
+                new Integer(WSConstants.ST_UNSIGNED),
+                "org.apache.ws.security.action.SAMLTokenUnsignedAction"
+            );
+            tmp.put(
+                new Integer(WSConstants.TS),
+                org.apache.ws.security.action.TimestampAction.class.getName()
+            );
+            tmp.put(
+                new Integer(WSConstants.UT_SIGN),
+                org.apache.ws.security.action.UsernameTokenSignedAction.class.getName()
+            );
+            tmp.put(
+                new Integer(WSConstants.SC),
+                org.apache.ws.security.action.SignatureConfirmationAction.class.getName()
+            );
+        } catch (final Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug(t.getMessage(), t);
+            }
+        }
+        DEFAULT_ACTIONS = java.util.Collections.unmodifiableMap(tmp);
+    }
+
+    /**
+     * The default collection of processors supported by the toolkit
+     */
+    private static final java.util.Map DEFAULT_PROCESSORS;
+    static {
+        final java.util.Map tmp = new java.util.HashMap();
+        try {
+            tmp.put(
+                WSSecurityEngine.SAML_TOKEN,
+                "org.apache.ws.security.processor.SAMLTokenProcessor"
+            );
+            tmp.put(
+                WSSecurityEngine.ENCRYPTED_KEY,
+                org.apache.ws.security.processor.EncryptedKeyProcessor.class.getName()
+            );
+            tmp.put(
+                WSSecurityEngine.SIGNATURE,
+                org.apache.ws.security.processor.SignatureProcessor.class.getName()
+            );
+            tmp.put(
+                WSSecurityEngine.timeStamp,
+                org.apache.ws.security.processor.TimestampProcessor.class.getName()
+            );
+            tmp.put(
+                WSSecurityEngine.usernameToken,
+                org.apache.ws.security.processor.UsernameTokenProcessor.class.getName()
+            );
+            tmp.put(
+                WSSecurityEngine.REFERENCE_LIST,
+                org.apache.ws.security.processor.ReferenceListProcessor.class.getName()
+            );
+            tmp.put(
+                WSSecurityEngine.signatureConfirmation,
+                org.apache.ws.security.processor.SignatureConfirmationProcessor.class.getName()
+            );
+            tmp.put(
+                WSSecurityEngine.DERIVED_KEY_TOKEN_05_02,
+                org.apache.ws.security.processor.DerivedKeyTokenProcessor.class.getName()
+            );
+            tmp.put(
+                WSSecurityEngine.DERIVED_KEY_TOKEN_05_12,
+                tmp.get(WSSecurityEngine.DERIVED_KEY_TOKEN_05_02)
+            );
+            tmp.put(
+                WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_02,
+                org.apache.ws.security.processor.SecurityContextTokenProcessor.class.getName()
+            );
+            tmp.put(
+                WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_12,
+                tmp.get(WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_02)
+            );
+            tmp.put(
+                WSSecurityEngine.binaryToken,
+                org.apache.ws.security.processor.BinarySecurityTokenProcessor.class.getName()
+            );
+            tmp.put(
+                WSSecurityEngine.ENCRYPTED_DATA,
+                org.apache.ws.security.processor.EncryptedDataProcessor.class.getName()
+            );
+        } catch (final Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug(t.getMessage(), t);
+            }
+        }
+        DEFAULT_PROCESSORS = java.util.Collections.unmodifiableMap(tmp);
+    }
+
+    protected static WSSConfig defaultConfig = null;
+
+    protected boolean wsiBSPCompliant = false;
+
+    /**
+     * Set the timestamp precision mode. If set to <code>true</code> then use
+     * timestamps with milliseconds, otherwise omit the millisconds. As per XML
+     * Date/Time specification the default is to include the milliseconds.
+     */
+    protected boolean precisionInMilliSeconds = true;
+
+    protected boolean enableSignatureConfirmation = true;
+
+    /**
+     * If set to true then the timestamp handling will throw an exception if the
+     * timestamp contains an expires element and the semantics are expired.
+     * 
+     * If set to false, no exception will be thrown, even if the semantics are
+     * expired.
+     */
+    protected boolean timeStampStrict = true;
+    
+    /**
+     * This variable controls whether types other than PasswordDigest or PasswordText
+     * are allowed when processing UsernameTokens. 
+     * 
+     * By default this is set to false so that the user doesn't have to explicitly
+     * reject custom token types in the callback handler.
+     */
+    protected boolean handleCustomPasswordTypes = false;
+
+    protected HashMap jceProvider = new HashMap(10);
+
+    /**
+     * The known actions.  These are initialized from a set of defaults,
+     * but the list may be modified via the setAction operation.
+     */
+    private final java.util.Map actionMap = new java.util.HashMap(DEFAULT_ACTIONS);
+
+    /**
+     * The known processors.  These are initialized from a set of defaults,
+     * but the list may be modified via the setProcessor operation.
+     */
+    private final java.util.Map processorMap = new java.util.HashMap(DEFAULT_PROCESSORS);
+    
+    /**
+     * a static boolean flag that determines whether default JCE providers
+     * should be added at the time of construction.
+     *
+     * These providers, and the order in which they are added, can interfere
+     * with some JVMs (such as IBMs).
+     */
+    private static boolean addJceProviders = true;
+    
+    /**
+     * a boolean flag to record whether we have already been statically
+     * initialized.  This flag prevents repeated and unecessary calls
+     * to static initialization code at construction time.
+     */
+    private static boolean staticallyInitialized = false;
+    
+    /**
+     * Set the value of the internal addJceProviders flag.  This flag
+     * turns on (or off) automatic registration of known JCE providers
+     * that provide necessary cryptographic algorithms for use with WSS4J.
+     * By default, this flag is true, for backwards compatibility.  You may
+     * wish (or need) to initialize the JCE manually, e.g., in some JVMs.
+     */
+    public static void setAddJceProviders(boolean value) {
+        addJceProviders = value;
+    }
+    
+    private synchronized void
+    staticInit() {
+        if (!staticallyInitialized) {
+            org.apache.xml.security.Init.init();
+            if (addJceProviders) {
+                /*
+                 * The last provider added has precedence, that is if JuiCE can be add
+                 * then WSS4J uses this provider.
+                 */
+                addJceProvider("BC",
+                        "org.bouncycastle.jce.provider.BouncyCastleProvider");
+                addJceProvider("JuiCE",
+                        "org.apache.security.juice.provider.JuiCEProviderOpenSSL");
+            }
+            Transform.init();
+            try {
+                Transform.register(STRTransform.implementedTransformURI,
+                        "org.apache.ws.security.transform.STRTransform");
+            } catch (Exception ex) {
+                if (log.isDebugEnabled()) {
+                    log.debug(ex.getMessage(), ex);
+                }
+            }
+            staticallyInitialized = true;
+        }
+    }
+    
+    protected WSSConfig() {
+        staticInit();
+    }
+    
+    /**
+     * @return a new WSSConfig instance configured with the default values
+     *         (values identical to
+     *         {@link #getDefaultWSConfig getDefaultWSConfig()})
+     */
+    public static WSSConfig getNewInstance() {
+        WSSConfig config = new WSSConfig();
+        return config;
+    }
+
+    /**
+     * returns a static WSConfig instance that is configured with the latest
+     * OASIS WS-Security settings.
+     */
+    public static WSSConfig getDefaultWSConfig() {
+        if (defaultConfig == null) {
+            defaultConfig = getNewInstance();
+        }
+        return defaultConfig;
+    }
+    
+    /**
+     * Checks if we are in WS-I Basic Security Profile compliance mode
+     * 
+     * @return TODO
+     */
+    public boolean isWsiBSPCompliant() {
+        return wsiBSPCompliant;
+    }
+
+    /**
+     * Set the WS-I Basic Security Profile compliance mode. The default is false
+     * (dues to .Net interop problems).
+     * 
+     * @param wsiBSPCompliant
+     */
+    public void setWsiBSPCompliant(boolean wsiBSPCompliant) {
+        this.wsiBSPCompliant = wsiBSPCompliant;
+    }
+
+    /**
+     * Checks if we need to use milliseconds in timestamps
+     * 
+     * @return TODO
+     */
+    public boolean isPrecisionInMilliSeconds() {
+        return precisionInMilliSeconds;
+    }
+
+    /**
+     * Set the precision in milliseconds
+     * 
+     * @param precisionInMilliSeconds
+     *            TODO
+     */
+    public void setPrecisionInMilliSeconds(boolean precisionInMilliSeconds) {
+        this.precisionInMilliSeconds = precisionInMilliSeconds;
+    }
+
+    /**
+     * @return Returns the enableSignatureConfirmation.
+     */
+    public boolean isEnableSignatureConfirmation() {
+        return enableSignatureConfirmation;
+    }
+
+    /**
+     * @param enableSignatureConfirmation
+     *            The enableSignatureConfirmation to set.
+     */
+    public void setEnableSignatureConfirmation(
+            boolean enableSignatureConfirmation) {
+        this.enableSignatureConfirmation = enableSignatureConfirmation;
+    }
+    
+    /**
+     * @param handleCustomTypes 
+     * whether to handle custom UsernameToken password types or not
+     */
+    public void setHandleCustomPasswordTypes(boolean handleCustomTypes) {
+        this.handleCustomPasswordTypes = handleCustomTypes;
+    }
+    
+    /**
+     * @return whether custom UsernameToken password types are allowed or not
+     */
+    public boolean getHandleCustomPasswordTypes() {
+        return handleCustomPasswordTypes;
+    }
+
+    /**
+     * @return Returns if we shall throw an exception on expired request
+     *         semantic
+     */
+    public boolean isTimeStampStrict() {
+        return timeStampStrict;
+    }
+
+    /**
+     * @param timeStampStrict
+     *            If true throw an exception on expired request semantic
+     */
+    public void setTimeStampStrict(boolean timeStampStrict) {
+        this.timeStampStrict = timeStampStrict;
+    }
+    
+    /**
+     * Associate an action with a specific action code.
+     *
+     * This operation allows applications to supply their own
+     * actions for well-known operations.
+     */
+    public String setAction(int code, String action) {
+        return (String) actionMap.put(new Integer(code), action);
+    }
+
+    /**
+     * Lookup action
+     * 
+     * @param action
+     * @return An action class to create a security token
+     * @throws WSSecurityException
+     */
+    public Action getAction(int action) throws WSSecurityException {
+        Integer key = new Integer(action);
+        String name = (String) actionMap.get(key);
+        if (name == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unknownAction", new Object[] { key });
+        }
+        try {
+            return (Action) Loader.loadClass(name).newInstance();
+        } catch (Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug(t.getMessage(), t);
+            }
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unableToLoadClass", new Object[] { name }, t);
+        }
+    }
+    
+    /**
+     * Associate a SOAP processor name with a specified SOAP Security header
+     * element QName.  Processors registered under this QName will be
+     * called when processing header elements with the specified type.
+     */
+    public String setProcessor(QName el, String name) {
+        return (String) processorMap.put(el, name);
+    }
+
+    /**
+     * @return      the SOAP processor associated with the specified
+     *              QName.  The QName is intended to refer to an element
+     *              in a SOAP security header.  This operation returns
+     *              null if there is no processor associated with the 
+     *              specified QName.
+     */
+    public Processor getProcessor(QName el) throws WSSecurityException {
+        final String name = (String) processorMap.get(el);
+        if (name != null) {
+            try {
+                return (Processor) Loader.loadClass(name).newInstance();
+            } catch (Throwable t) {
+                if (log.isDebugEnabled()) {
+                    log.debug(t.getMessage(), t);
+                }
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "unableToLoadClass", new Object[] { name }, t);
+            }
+        }
+        return null;
+    }
+
+    private boolean loadProvider(String id, String className) {
+        try {
+            Class c = Loader.loadClass(className);
+            if (java.security.Security.getProvider(id) == null) {
+                if (log.isDebugEnabled()) {
+                    log.debug("The provider " + id
+                            + " had to be added to the java.security.Security");
+                }
+                int ret =java.security.Security.insertProviderAt(
+                        (java.security.Provider) c.newInstance(), 2);
+                if (log.isDebugEnabled()) {
+                    log.debug("The provider " + id + " was added at: "
+                            + ret);
+                }                
+            }
+            return true;
+        } catch (Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug("The provider " + id + " could not be added: "
+                        + t.getMessage(), t);
+            }
+            return false;
+        }
+
+    }
+
+    /**
+     * Add a new JCE security provider to use for WSS4J.
+     * 
+     * If the provider is not already known the method loads a security provider
+     * class and adds the provider to the java security service.
+     * 
+     * 
+     * @param id
+     *            The id string of the provider
+     * @param className
+     *            Name of the class the implements the provider. This class must
+     *            be a subclass of <code>java.security.Provider</code>
+     * 
+     * @return Returns <code>true</code> if the provider was successfully
+     *         added, <code>false</code> otherwise.
+     */
+    public boolean addJceProvider(String id, String className) {
+        if (jceProvider.get(id) == null && loadProvider(id, className)) {
+            jceProvider.put(id, className);
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/WSSecurityEngine.java b/trunk/src/org/apache/ws/security/WSSecurityEngine.java
new file mode 100644
index 0000000..fc6b227
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSSecurityEngine.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.conversation.ConversationConstants;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.processor.Processor;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+import java.util.Vector;
+
+/**
+ * WS-Security Engine.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de).
+ */
+public class WSSecurityEngine {
+    public static final String VALUE_TYPE = "ValueType";
+    private static Log log = LogFactory.getLog(WSSecurityEngine.class.getName());
+    private static Log tlog =
+            LogFactory.getLog("org.apache.ws.security.TIME");
+
+    private static WSSecurityEngine engine = null;
+    
+    /**
+     * The WSSConfig instance used by this SecurityEngine to
+     * find Processors for processing security headers
+     */
+    private WSSConfig wssConfig = null;
+    private boolean doDebug = false;
+    /**
+     * <code>wsse:BinarySecurityToken</code> as defined by WS Security specification
+     */
+    public static final QName binaryToken = new QName(WSConstants.WSSE_NS, WSConstants.BINARY_TOKEN_LN);
+    /**
+     * <code>wsse:UsernameToken</code> as defined by WS Security specification
+     */
+    public static final QName usernameToken = new QName(WSConstants.WSSE_NS, WSConstants.USERNAME_TOKEN_LN);
+    /**
+     * <code>wsu:Timestamp</code> as defined by OASIS WS Security specification,
+     */
+    public static final QName timeStamp = new QName(WSConstants.WSU_NS, WSConstants.TIMESTAMP_TOKEN_LN);
+    /**
+     * <code>wsse11:signatureConfirmation</code> as defined by OASIS WS Security specification,
+     */
+    public static final QName signatureConfirmation = new QName(WSConstants.WSSE11_NS, WSConstants.SIGNATURE_CONFIRMATION_LN);
+    /**
+     * <code>ds:Signature</code> as defined by XML Signature specification,
+     * enhanced by WS Security specification
+     */
+    public static final QName SIGNATURE = new QName(WSConstants.SIG_NS, WSConstants.SIG_LN);
+    /**
+     * <code>xenc:EncryptedKey</code> as defined by XML Encryption specification,
+     * enhanced by WS Security specification
+     */
+    public static final QName ENCRYPTED_KEY = new QName(WSConstants.ENC_NS, WSConstants.ENC_KEY_LN);
+    /**
+     * <code>xenc:EncryptedData</code> as defined by XML Encryption specification,
+     * enhanced by WS Security specification
+     */
+    public static final QName ENCRYPTED_DATA = new QName(WSConstants.ENC_NS, WSConstants.ENC_DATA_LN);
+    /**
+     * <code>xenc:ReferenceList</code> as defined by XML Encryption specification,
+     */
+    public static final QName REFERENCE_LIST = new QName(WSConstants.ENC_NS, WSConstants.REF_LIST_LN);
+    /**
+     * <code>saml:Assertion</code> as defined by SAML specification
+     */
+    public static final QName SAML_TOKEN = new QName(WSConstants.SAML_NS, WSConstants.ASSERTION_LN);
+
+    /**
+     * <code>wsc:DerivedKeyToken</code> as defined by WS-SecureConversation specification
+     */
+    public static final QName DERIVED_KEY_TOKEN_05_02 = new QName(ConversationConstants.WSC_NS_05_02, ConversationConstants.DERIVED_KEY_TOKEN_LN);
+
+    /**
+     * <code>wsc:SecurityContextToken</code> as defined by WS-SecureConversation specification
+     */
+    public static final QName SECURITY_CONTEXT_TOKEN_05_02 = new QName(ConversationConstants.WSC_NS_05_02, ConversationConstants.SECURITY_CONTEXT_TOKEN_LN);
+
+    /**
+     * <code>wsc:DerivedKeyToken</code> as defined by WS-SecureConversation specification in WS-SX
+     */
+    public static final QName DERIVED_KEY_TOKEN_05_12 = new QName(ConversationConstants.WSC_NS_05_12, ConversationConstants.DERIVED_KEY_TOKEN_LN);
+
+    /**
+     * <code>wsc:SecurityContextToken</code> as defined by WS-SecureConversation specification in WS-SX
+     */
+    public static final QName SECURITY_CONTEXT_TOKEN_05_12 = new QName(ConversationConstants.WSC_NS_05_12, ConversationConstants.SECURITY_CONTEXT_TOKEN_LN);
+    
+    public WSSecurityEngine() {
+    }
+
+    /**
+     * Get a singleton instance of security engine.
+     * <p/>
+     *
+     * @return ws-security engine.
+     */
+    public synchronized static WSSecurityEngine getInstance() {
+        if (engine == null) {
+            engine = new WSSecurityEngine();
+        }
+        return engine;
+    }
+    
+    /**
+     * @return      the WSSConfig object set on this instance, or
+     *              the statically defined one, if the instance-level
+     *              config object is null.
+     */
+    public final WSSConfig
+    getWssConfig() {
+        return (wssConfig == null) ? WSSConfig.getDefaultWSConfig() : wssConfig;
+    }
+    
+    /**
+     * @param cfg   the WSSConfig instance for this WSSecurityEngine to use
+     *
+     * @return      the WSSConfig instance previously set on this 
+     *              WSSecurityEngine instance
+     */
+    public final WSSConfig
+    setWssConfig(WSSConfig cfg) {
+        WSSConfig ret = wssConfig;
+        wssConfig = cfg;
+        return ret;
+    }
+    
+    /**
+     * Process the security header given the soap envelope as W3C document.
+     * <p/>
+     * This is the main entry point to verify or decrypt a SOAP envelope.
+     * First check if a <code>wsse:Security</code> is available with the
+     * defined actor.
+     *
+     * @param doc    the SOAP envelope as {@link Document}
+     * @param actor  the engine works on behalf of this <code>actor</code>. Refer
+     *               to the SOAP specification about <code>actor</code> or <code>role
+     *               </code>
+     * @param cb     a callback hander to the caller to resolve passwords during
+     *               encryption and {@link UsernameToken} handling
+     * @param crypto the object that implements the access to the keystore and the
+     *               handling of certificates.
+     * @return a result vector
+     * @throws WSSecurityException
+     * @see WSSecurityEngine#processSecurityHeader(Element securityHeader, CallbackHandler cb,Crypto sigCrypto, Crypto decCrypto)
+     */
+    public Vector processSecurityHeader(Document doc,
+                                        String actor,
+                                        CallbackHandler cb,
+                                        Crypto crypto)
+            throws WSSecurityException {
+        return processSecurityHeader(doc, actor, cb, crypto, crypto);
+    }
+
+    /**
+     * Process the security header given the soap envelope as W3C document.
+     * <p/>
+     * This is the main entry point to verify or decrypt a SOAP envelope.
+     * First check if a <code>wsse:Security</code> is available with the
+     * defined actor.
+     *
+     * @param doc       the SOAP envelope as {@link Document}
+     * @param actor     the engine works on behalf of this <code>actor</code>. Refer
+     *                  to the SOAP specification about <code>actor</code> or <code>role
+     *                  </code>
+     * @param cb        a callback hander to the caller to resolve passwords during
+     *                  encryption and {@link UsernameToken} handling
+     * @param sigCrypto the object that implements the access to the keystore and the
+     *                  handling of certificates for Signature
+     * @param decCrypto the object that implements the access to the keystore and the
+     *                  handling of certificates for Decryption
+     * @return a result vector
+     * @throws WSSecurityException
+     * @see WSSecurityEngine#processSecurityHeader(
+     * Element securityHeader, CallbackHandler cb,Crypto sigCrypto, Crypto decCrypto)
+     */
+    public Vector processSecurityHeader(Document doc,
+                                        String actor,
+                                        CallbackHandler cb,
+                                        Crypto sigCrypto,
+                                        Crypto decCrypto)
+            throws WSSecurityException {
+
+        doDebug = log.isDebugEnabled();
+        if (doDebug) {
+            log.debug("enter processSecurityHeader()");
+        }
+
+        if (actor == null) {
+            actor = "";
+        }
+        Vector wsResult = null;
+        SOAPConstants sc = WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
+        Element elem = WSSecurityUtil.getSecurityHeader(doc, actor, sc);
+        if (elem != null) {
+            if (doDebug) {
+                log.debug("Processing WS-Security header for '" + actor
+                        + "' actor.");
+            }
+            wsResult = processSecurityHeader(elem, cb, sigCrypto, decCrypto);
+        }
+        return wsResult;
+    }
+
+    /**
+     * Process the security header given the <code>wsse:Security</code> DOM
+     * Element. 
+     * 
+     * This function loops over all direct child elements of the
+     * <code>wsse:Security</code> header. If it finds a known element, it
+     * transfers control to the appropriate handling function. The method
+     * processes the known child elements in the same order as they appear in
+     * the <code>wsse:Security</code> element. This is in accordance to the WS
+     * Security specification. <p/>
+     * 
+     * Currently the functions can handle the following child elements:
+     * 
+     * <ul>
+     * <li>{@link #SIGNATURE <code>ds:Signature</code>}</li>
+     * <li>{@link #ENCRYPTED_KEY <code>xenc:EncryptedKey</code>}</li>
+     * <li>{@link #REFERENCE_LIST <code>xenc:ReferenceList</code>}</li>
+     * <li>{@link #usernameToken <code>wsse:UsernameToken</code>}</li>
+     * <li>{@link #timeStamp <code>wsu:Timestamp</code>}</li>
+     * </ul>
+     *
+     * Note that additional child elements can be processed if appropriate
+     * Processors have been registered with the WSSCondig instance set
+     * on this class.
+     *
+     * @param securityHeader the <code>wsse:Security</code> header element
+     * @param cb             a callback hander to the caller to resolve passwords during
+     *                       encryption and {@link UsernameToken}handling
+     * @param sigCrypto      the object that implements the access to the keystore and the
+     *                       handling of certificates used for Signature
+     * @param decCrypto      the object that implements the access to the keystore and the
+     *                       handling of certificates used for Decryption
+     * @return a Vector of {@link WSSecurityEngineResult}. Each element in the
+     *         the Vector represents the result of a security action. The elements
+     *         are ordered according to the sequence of the security actions in the
+     *         wsse:Signature header. The Vector maybe empty if no security processing
+     *         was performed.
+     * @throws WSSecurityException
+     */
+    protected Vector processSecurityHeader(Element securityHeader,
+                                           CallbackHandler cb,
+                                           Crypto sigCrypto,
+                                           Crypto decCrypto) throws WSSecurityException {
+
+        long t0 = 0, t1 = 0, t2 = 0;
+        if (tlog.isDebugEnabled()) {
+            t0 = System.currentTimeMillis();
+        }
+        /*
+         * Gather some info about the document to process and store
+         * it for retrieval. Store the implementation of signature crypto
+         * (no need for encryption --- yet)
+         */
+        WSDocInfo wsDocInfo = new WSDocInfo(securityHeader.getOwnerDocument().hashCode());
+        wsDocInfo.setCrypto(sigCrypto);
+
+        NodeList list = securityHeader.getChildNodes();
+        int len = list.getLength();
+        Node elem;
+        if (tlog.isDebugEnabled()) {
+            t1 = System.currentTimeMillis();
+        }
+        Vector returnResults = new Vector();
+
+        for (int i = 0; i < len; i++) {
+            elem = list.item(i);
+            if (elem.getNodeType() != Node.ELEMENT_NODE) {
+                continue;
+            }
+            QName el = new QName(elem.getNamespaceURI(), elem.getLocalName());
+            final WSSConfig cfg = getWssConfig();
+            Processor p = cfg.getProcessor(el);
+            /*
+             * Call the processor for this token. After the processor returns, 
+             * store it for later retrieval. The token processor may store some
+             * information about the processed token
+             */
+            if (p != null) {
+                p.handleToken((Element) elem, sigCrypto, decCrypto, cb, wsDocInfo, returnResults, cfg);
+                wsDocInfo.setProcessor(p);
+            } else {
+                /*
+                * Add check for a BinarySecurityToken, add info to WSDocInfo. If BST is
+                * found before a Signature token this would speed up (at least a little
+                * bit) the processing of STR Transform.
+                */
+                if (doDebug) {
+                    log.debug("Unknown Element: " + elem.getLocalName() + " " + elem.getNamespaceURI());
+                }
+            }
+        }
+        if (tlog.isDebugEnabled()) {
+            t2 = System.currentTimeMillis();
+            tlog.debug("processHeader: total " + (t2 - t0) +
+                    ", prepare " + (t1 - t0) +
+                    ", handle " + (t2 - t1));
+        }
+        return returnResults;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/WSSecurityEngineResult.java b/trunk/src/org/apache/ws/security/WSSecurityEngineResult.java
new file mode 100644
index 0000000..af93205
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSSecurityEngineResult.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright  2003-2006 The Apache Software Foundation, or their licensors, as
+ * appropriate.
+ *
+ *  Licensed 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.ws.security;
+
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.SecurityContextToken;
+import org.apache.ws.security.message.token.SignatureConfirmation;
+import org.apache.ws.security.message.token.Timestamp;
+import org.opensaml.SAMLAssertion;
+
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de)
+ */
+public class WSSecurityEngineResult extends java.util.HashMap {
+
+    /**
+     * Tag denoting the cryptographic operation performed
+     *
+     * The value under this tag is of type java.lang.Integer
+     */
+    public static final java.lang.String TAG_ACTION =
+        "action";
+
+    /**
+     * Tag denoting the security principal found, if applicable.
+     *
+     * The value under this tag is of type java.security.Principal.
+     */
+    public static final java.lang.String TAG_PRINCIPAL =
+        "principal";
+
+    /**
+     * Tag denoting the X.509 certificate found, if applicable.
+     *
+     * The value under this tag is of type java.security.cert.X509Certificate.
+     */
+    public static final java.lang.String TAG_X509_CERTIFICATE =
+        "x509-certificate";
+
+    /**
+     * Tag denoting the SAML Assertion found, if applicable.
+     *
+     * The value under this tag is of type org.opensaml.SAMLAssertion.
+     */
+    public static final java.lang.String TAG_SAML_ASSERTION =
+        "saml-assertion";
+
+    /**
+     * Tag denoting the timestamp found, if applicable.
+     *
+     * The value under this tag is of type
+     * org.apache.ws.security.message.token.Timestamp.
+     */
+    public static final java.lang.String TAG_TIMESTAMP =
+        "timestamp";
+
+    /**
+     * Tag denoting the wsu:Ids of signed elements, if applicable.
+     *
+     * The value under this tag is of type java.util.Set, where
+     * each element of the set is of type java.lang.String.
+     */
+    public static final java.lang.String TAG_SIGNED_ELEMENT_IDS =
+        "signed-element-ids";
+
+    /**
+     * Tag denoting the signature value of a signed element, if applicable.
+     *
+     * The value under this tag is of type byte[].
+     */
+    public static final java.lang.String TAG_SIGNATURE_VALUE =
+        "signature-value";
+
+    /**
+     * Tag denoting the signature confirmation of a signed element,
+     * if applicable.
+     *
+     * The value under this tag is of type
+     * org.apache.ws.security.message.token.SignatureConfirmation.
+     */
+    public static final java.lang.String TAG_SIGNATURE_CONFIRMATION =
+        "signature-confirmation";
+
+    /**
+     * Tag denoting references to the DOM elements that have been
+     * cryptographically protected.
+     *
+     * The value under this tag is of type java.util.Set, where
+     * each element in the set is of type org.w3c.dom.Element.
+     */
+    public static final java.lang.String TAG_PROTECTED_ELEMENTS =
+        "protected-elements";
+
+    /**
+     * Tag denoting references to the DOM elements that have been
+     * cryptographically protected.
+     *
+     * The value under this tag is of type SecurityContextToken.
+     */
+    public static final java.lang.String TAG_SECURITY_CONTEXT_TOKEN =
+        "security-context-token";
+
+    /**
+     * Tag denoting a reference to the decrypted key
+     *
+     * The value under this tag is of type byte[].
+     */
+    public static final java.lang.String TAG_DECRYPTED_KEY =
+        "decrypted-key";
+
+    /**
+     * Tag denoting references to the encrypted key id.
+     *
+     * The value under this tag is of type String.
+     */
+    public static final java.lang.String TAG_ENCRYPTED_KEY_ID =
+        "encrypted-key-id";
+
+    /**
+     * Tag denoting references to a List of Data ref URIs.
+     *
+     * The value under this tag is of type List.
+     */
+    public static final java.lang.String TAG_DATA_REF_URIS =
+        "data-ref-uris";
+
+    /**
+     * Tag denoting the X.509 certificate chain found, if applicable.
+     *
+     * The value under this tag is of type java.security.cert.X509Certificate[].
+     */
+    public static final java.lang.String TAG_X509_CERTIFICATES =
+        "x509-certificates";
+
+    /**
+     * Tag denoting the X.509 certificate found, if applicable.
+     *
+     * The value under this tag is of type java.security.cert.X509Certificate.
+     */
+    public static final java.lang.String TAG_BINARY_SECURITY_TOKEN =
+        "binary-security-token";
+
+    /**
+     * Tag denoting the encrypted key bytes
+     *
+     * The value under this tag is a byte array 
+     */
+    public static final Object TAG_ENCRYPTED_EPHEMERAL_KEY = "encrypted-ephemeral-key-bytes";
+
+    public WSSecurityEngineResult(
+        int act, 
+        SAMLAssertion ass
+    ) {
+        put(TAG_ACTION, new Integer(act));
+        put(TAG_SAML_ASSERTION, ass);
+    }
+
+    public WSSecurityEngineResult(
+        int act, 
+        Principal princ,
+        X509Certificate certificate, 
+        Set elements, 
+        byte[] sv
+    ) {
+        put(TAG_ACTION, new Integer(act));
+        put(TAG_PRINCIPAL, princ);
+        put(TAG_X509_CERTIFICATE, certificate);
+        put(TAG_SIGNED_ELEMENT_IDS, elements);
+        put(TAG_SIGNATURE_VALUE, sv);
+    }
+
+    public
+    WSSecurityEngineResult(
+        int act,
+        Principal princ,
+        X509Certificate certificate,
+        Set elements,
+        Set protectedElements,
+        byte[] sv
+    ) {
+        this(act, princ, certificate, elements, sv);
+        put(TAG_PROTECTED_ELEMENTS, protectedElements);
+    }
+
+    public WSSecurityEngineResult(
+        int act, 
+        byte[] decryptedKey, 
+        byte[] encryptedKeyBytes,
+        String encyptedKeyId, 
+        List dataRefUris
+    ) {
+        put(TAG_ACTION, new Integer(act));
+        put(TAG_DECRYPTED_KEY, decryptedKey);
+        put(TAG_ENCRYPTED_EPHEMERAL_KEY, encryptedKeyBytes);
+        put(TAG_ENCRYPTED_KEY_ID, encyptedKeyId);
+        put(TAG_DATA_REF_URIS, dataRefUris);
+    }
+    
+    public WSSecurityEngineResult(int act, ArrayList dataRefUris) {
+        put(TAG_ACTION, new Integer(act));
+        put(TAG_DATA_REF_URIS, dataRefUris);
+    }
+    
+    public WSSecurityEngineResult(int act, Timestamp tstamp) {
+        put(TAG_ACTION, new Integer(act));
+        put(TAG_TIMESTAMP, tstamp);
+    }
+    
+    public WSSecurityEngineResult(int act, SecurityContextToken sct) {
+        put(TAG_ACTION, new Integer(act));
+        put(TAG_SECURITY_CONTEXT_TOKEN, sct);
+    }
+    
+    public WSSecurityEngineResult(int act, SignatureConfirmation sc) {
+        put(TAG_ACTION, new Integer(act));
+        put(TAG_SIGNATURE_CONFIRMATION, sc);
+    }
+
+    public WSSecurityEngineResult(int act, BinarySecurity token,
+            X509Certificate[] certificates) {
+        put(TAG_ACTION, new Integer(act));
+        put(TAG_BINARY_SECURITY_TOKEN, token);
+        put(TAG_X509_CERTIFICATES, certificates);
+    }
+
+    /**
+     * @return the actions vector. These actions were performed by the the
+     *         security engine.
+     *
+     * @deprecated      use ((java.lang.Integer) #get(#TAG_ACTION)).intValue() 
+     *                  instead
+     */
+    public int getAction() {
+        return ((java.lang.Integer) get(TAG_ACTION)).intValue();
+    }
+
+    /**
+     * @return the principals found if UsernameToken or Signature
+     *         processing were done
+     *
+     * @deprecated      use (Principal) #get(#TAG_PRINCIPAL) instead
+     */
+    public Principal getPrincipal() {
+        return (Principal) get(TAG_PRINCIPAL);
+    }
+
+    /**
+     * @return the Certificate found if Signature
+     *         processing were done
+     *
+     * @deprecated      use (X509Certificate)
+     *                  #get(#TAG_X509_CERTIFICATE) instead
+     */
+    public X509Certificate getCertificate() {
+        return (X509Certificate) get(TAG_X509_CERTIFICATE);
+    }
+
+    /**
+     * @return Returns the assertion.
+     *
+     * @deprecated      use (SAMLAssertion)
+     *                  #get(#TAG_SAML_ASSERTION) instead
+     */
+    public SAMLAssertion getAssertion() {
+        return (SAMLAssertion) get(TAG_SAML_ASSERTION);
+    }
+
+    /**
+     * @return the timestamp found
+     *
+     * @deprecated      use (Timestamp)
+     *                  #get(#TAG_TIMESTAMP) instead
+     */
+    public Timestamp getTimestamp() {
+        return (Timestamp) get(TAG_TIMESTAMP);
+    }
+
+    /**
+     * @return Returns the signedElements.
+     *
+     * @deprecated      use (java.util.Set)
+     *                  #get(#TAG_SIGNED_ELEMENT_IDS) instead
+     */
+    public Set getSignedElements() {
+        return (java.util.Set) get(TAG_SIGNED_ELEMENT_IDS);
+    }
+
+    /**
+     * @return Returns the signatureValue.
+     *
+     * @deprecated      use (byte[])
+     *                  #get(#TAG_SIGNATURE_VALUE) instead
+     */
+    public byte[] getSignatureValue() {
+        return (byte[]) get(TAG_SIGNATURE_VALUE);
+    }
+
+    /**
+     * @return Returns the sigConf.
+     *
+     * @deprecated      use (SignatureConfirmation)
+     *                  #get(#TAG_SIGNATURE_CONFIRMATION) instead
+     */
+    public SignatureConfirmation getSigConf() {
+        return (SignatureConfirmation) get(TAG_SIGNATURE_CONFIRMATION);
+    }
+
+    /**
+     * @param signatureValue The signatureValue to set.
+     *
+     * @deprecated      use put(#TAG_SIGNATURE_VALUE, signatureValue) instead
+     */
+    public void setSignatureValue(byte[] signatureValue) {
+        put(TAG_SIGNATURE_VALUE, signatureValue);
+    }
+
+    /**
+     * @return          the security context token acquired off the message
+     *
+     * @deprecated      use
+     *                  #get(#TAG_SECURITY_CONTEXT_TOKEN) instead
+     */
+    public SecurityContextToken getSecurityContextToken() {
+        return (SecurityContextToken) get(TAG_SECURITY_CONTEXT_TOKEN);
+    }
+
+    /**
+     * @return          the decrypted key
+     *
+     * @deprecated      use
+     *                  #get(#TAG_DECRYPTED_KEY) instead
+     */
+    public byte[] getDecryptedKey() {
+        return (byte[]) get(TAG_DECRYPTED_KEY);
+    }
+
+    /**
+     * @return          the encrypted key id
+     *
+     * @deprecated      use
+     *                  #get(#TAG_ENCRYPTED_KEY) instead
+     */
+    public String getEncryptedKeyId() {
+        return (String) get(TAG_ENCRYPTED_KEY_ID);
+    }
+
+    /**
+     * @return          the list of data ref URIs
+     *
+     * @deprecated      use
+     *                  #get(#TAG_DATA_REF_URIS) instead
+     */
+    public ArrayList getDataRefUris() {
+        return (ArrayList) get(TAG_DATA_REF_URIS);
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/WSSecurityException.java b/trunk/src/org/apache/ws/security/WSSecurityException.java
new file mode 100644
index 0000000..f350989
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSSecurityException.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import java.rmi.RemoteException;
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Exception class for WS-Security.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class WSSecurityException extends RemoteException {
+    public static final int FAILURE = 0;
+    public static final int UNSUPPORTED_SECURITY_TOKEN = 1;
+    public static final int UNSUPPORTED_ALGORITHM = 2;
+    public static final int INVALID_SECURITY = 3;
+    public static final int INVALID_SECURITY_TOKEN = 4;
+    public static final int FAILED_AUTHENTICATION = 5;
+    public static final int FAILED_CHECK = 6;
+    public static final int SECURITY_TOKEN_UNAVAILABLE = 7;
+    public static final int MESSAGE_EXPIRED = 8;
+    public static final int FAILED_ENCRYPTION = 9;
+    public static final int FAILED_SIGNATURE = 10;
+    private static ResourceBundle resources;
+    /*
+     * This is an Integer -> QName map. Its function is to map the integer error codes
+     * given above to the QName fault codes as defined in the SOAP Message Security 1.1
+     * specification. A client application can simply call getFaultCode rather than do
+     * any parsing of the error code. Note that there are no mappings for "FAILURE", 
+     * "FAILED_ENCRYPTION" and "FAILED_SIGNATURE" as these are not standard error messages.
+     */
+    private static final java.util.Map FAULT_CODE_MAP = new java.util.HashMap();
+
+    static {
+        try {
+            resources = ResourceBundle.getBundle("org.apache.ws.security.errors");
+        } catch (MissingResourceException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+        
+        FAULT_CODE_MAP.put(
+            new Integer(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN), 
+            WSConstants.UNSUPPORTED_SECURITY_TOKEN
+        );
+        FAULT_CODE_MAP.put(
+            new Integer(UNSUPPORTED_ALGORITHM), 
+            WSConstants.UNSUPPORTED_ALGORITHM
+        );
+        FAULT_CODE_MAP.put(
+            new Integer(INVALID_SECURITY), 
+            WSConstants.INVALID_SECURITY
+        );
+        FAULT_CODE_MAP.put(
+            new Integer(INVALID_SECURITY_TOKEN), 
+            WSConstants.INVALID_SECURITY_TOKEN
+        );
+        FAULT_CODE_MAP.put(
+            new Integer(FAILED_AUTHENTICATION), 
+            WSConstants.FAILED_AUTHENTICATION
+         );
+        FAULT_CODE_MAP.put(
+            new Integer(FAILED_CHECK), 
+            WSConstants.FAILED_CHECK
+         );
+        FAULT_CODE_MAP.put(
+            new Integer(SECURITY_TOKEN_UNAVAILABLE),
+            WSConstants.SECURITY_TOKEN_UNAVAILABLE
+         );
+        FAULT_CODE_MAP.put(
+            new Integer(MESSAGE_EXPIRED), 
+            WSConstants.MESSAGE_EXPIRED
+        );
+    }
+
+    private int errorCode;
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param errorCode
+     * @param msgId
+     * @param args
+     * @param exception
+     */
+    public WSSecurityException(int errorCode, String msgId, Object[] args, Throwable exception) {
+        super(getMessage(errorCode, msgId, args), exception);
+        this.errorCode = errorCode;
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param errorCode
+     * @param msgId
+     * @param args
+     */
+    public WSSecurityException(int errorCode, String msgId, Object[] args) {
+        super(getMessage(errorCode, msgId, args));
+        this.errorCode = errorCode;
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param errorCode
+     * @param msgId
+     */
+    public WSSecurityException(int errorCode, String msgId) {
+        this(errorCode, msgId, null);
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param errorCode
+     */
+    public WSSecurityException(int errorCode) {
+        this(errorCode, null, null);
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param errorMessage
+     */
+    public WSSecurityException(String errorMessage) {
+        super(errorMessage);
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param errorMessage
+     */
+    public WSSecurityException(String errorMessage, Throwable t) {
+        super(errorMessage, t);
+    }
+
+    /**
+     * Get the error code.
+     * <p/>
+     *
+     * @return error code of this exception See values above.
+     */
+    public int getErrorCode() {
+        return this.errorCode;
+    }
+    
+    /**
+     * Get the fault code QName for this associated error code.
+     * <p/>
+     * 
+     * @return the fault code QName of this exception
+     */
+    public javax.xml.namespace.QName getFaultCode() {
+        Object ret = FAULT_CODE_MAP.get(new Integer(this.errorCode));
+        if (ret != null) {
+            return (javax.xml.namespace.QName)ret;
+        }
+        return null;
+    }
+
+    /**
+     * get the message from resource bundle.
+     * <p/>
+     *
+     * @param errorCode
+     * @param msgId
+     * @param args
+     * @return the message translated from the property (message) file.
+     */
+    private static String getMessage(int errorCode, String msgId, Object[] args) {
+        String msg = null;
+        try {
+            msg = resources.getString(String.valueOf(errorCode));
+            if (msgId != null) {
+                return msg += (" (" + MessageFormat.format(resources.getString(msgId), args) + ")");
+            }
+        } catch (MissingResourceException e) {
+            throw new RuntimeException("Undefined '" + msgId + "' resource property", e);
+        }
+        return msg;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/WSUsernameTokenPrincipal.java b/trunk/src/org/apache/ws/security/WSUsernameTokenPrincipal.java
new file mode 100644
index 0000000..dacaee9
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/WSUsernameTokenPrincipal.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security;
+
+import java.security.Principal;
+
+/**
+ * This class implements the <code>Principal</code> interface and
+ * represents a UsernameToken user. 
+ * <p/>In addition to the principal's name
+ * this principal object also contains the nonce and created time of the
+ * UsernameToken (refer to the OASIS WS Security specification, UsernameToken
+ * profile). These values are set only if the password of UsernameToken was of
+ * type <code>PasswordDigest</code>.
+ * <p/>Furthermore the password type is
+ * provided to the application. The password type is the string of the type
+ * attribute of the password element inside the username token. Refer to the
+ * OASIS WSS specification for predefined password types. <p/>The
+ * <code>equals()</code> method use the prinicipal's name only and does not
+ * compare nonce or created time. 
+ * <p/>Modelled according to the example provided
+ * by JAAS documentation 
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com).
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com).
+ * @see java.security.Principal
+ * @see javax.security.auth.Subject
+ */
+public class WSUsernameTokenPrincipal implements Principal, java.io.Serializable {
+
+    /**
+     * @serial
+     */
+    private String name = null;
+    private String nonce = null;
+    private String password = null;
+    private String createdTime = null;
+    private String passwordType = null;
+    private boolean digest = false;
+
+    /**
+     * Create a WSUsernameTokenPrincipal with a WSUsernameToken username.
+     * <p/>
+     *
+     * @param name the WSUsernameToken username for this user.
+     * @throws NullPointerException if the <code>name</code>
+     *                              is <code>null</code>.
+     */
+    public WSUsernameTokenPrincipal(String name, boolean digest) {
+        if (name == null)
+            throw new NullPointerException("illegal null input");
+        this.name = name;
+        this.digest = digest;
+    }
+
+    /**
+     * Return the WSUsernameToken username for this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     * <p/>
+     *
+     * @return the WSUsernameToken username for this <code>WSUsernameTokenPrincipal</code>
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Return the WSUsernameToken password type for this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     * <p/>
+     *
+     * @return true if the password type was <code>PassowrdDigest</code>
+     */
+    public boolean isPasswordDigest() {
+        return digest;
+    }
+
+    /**
+     * Set the WSUsernameToken password for this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     * <p/>
+     *
+     * @param password
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    /**
+     * Return the WSUsernameToken password for this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     * <p/>
+     *
+     * @return the WSUsernameToken password for this <code>WSUsernameTokenPrincipal</code>
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Set the WSUsernameToken nonce for this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     * <p/>
+     *
+     * @param nonce
+     */
+    public void setNonce(String nonce) {
+        this.nonce = nonce;
+    }
+
+    /**
+     * Return the WSUsernameToken nonce for this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     * <p/>
+     *
+     * @return the WSUsernameToken nonce for this <code>WSUsernameTokenPrincipal</code>
+     */
+    public String getNonce() {
+        return nonce;
+    }
+
+    /**
+     * Set the WSUsernameToken created time for this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     *
+     * @param createdTime
+     */
+    public void setCreatedTime(String createdTime) {
+        this.createdTime = createdTime;
+    }
+
+    /**
+     * Return the WSUsernameToken created time for this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     *
+     * @return the WSUsernameToken created time for this <code>WSUsernameTokenPrincipal</code>
+     */
+    public String getCreatedTime() {
+        return createdTime;
+    }
+
+    /**
+     * Return a string representation of this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     *
+     * @return a string representation of this <code>WSUsernameTokenPrincipal</code>.
+     */
+    public String toString() {
+        return ("WSUsernameTokenPrincipal:  " + name);
+    }
+
+    /**
+     * @return Returns the passwordType.
+     */
+    public String getPasswordType() {
+        return passwordType;
+    }
+    /**
+     * @param passwordType The passwordType to set.
+     */
+    public void setPasswordType(String passwordType) {
+        this.passwordType = passwordType;
+    }
+    /**
+     * Compares the specified Object with this <code>WSUsernameTokenPrincipal</code>
+     * for equality.  Returns true if the given object is also a
+     * <code>WSUsernameTokenPrincipal</code> and the two WSUsernameTokenPrincipals
+     * have the same username.
+     * <p/>
+     * <p/>
+     *
+     * @param o Object to be compared for equality with this
+     *          <code>WSUsernameTokenPrincipal</code>.
+     * @return true if the specified Object is equal equal to this
+     *         <code>WSUsernameTokenPrincipal</code>.
+     */
+    public boolean equals(Object o) {
+        if (o == null) {
+            return false;
+        }
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof WSUsernameTokenPrincipal)) {
+            return false;
+        }
+        WSUsernameTokenPrincipal that = (WSUsernameTokenPrincipal) o;
+        if (this.getName().equals(that.getName())) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Return a hash code for this <code>WSUsernameTokenPrincipal</code>.
+     * <p/>
+     * <p/>
+     *
+     * @return a hash code for this <code>WSUsernameTokenPrincipal</code>.
+     */
+    public int hashCode() {
+        return name.hashCode();
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/action/Action.java b/trunk/src/org/apache/ws/security/action/Action.java
new file mode 100644
index 0000000..6fab8cb
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/action/Action.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.action;
+
+import org.w3c.dom.Document;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.WSSecurityException;
+
+/**
+ * Interface for all actions
+ */
+public interface Action {
+    public void execute(WSHandler handler, int actionToDo, Document doc,
+            RequestData reqData) throws WSSecurityException;
+}
diff --git a/trunk/src/org/apache/ws/security/action/EncryptionAction.java b/trunk/src/org/apache/ws/security/action/EncryptionAction.java
new file mode 100644
index 0000000..cf919ea
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/action/EncryptionAction.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.action;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.w3c.dom.Document;
+
+public class EncryptionAction implements Action {
+    public void execute(WSHandler handler, int actionToDo, Document doc, RequestData reqData)
+            throws WSSecurityException {
+        WSSecEncrypt wsEncrypt = new WSSecEncrypt();
+        wsEncrypt.setWsConfig(reqData.getWssConfig());
+
+        if (reqData.getEncKeyId() != 0) {
+            wsEncrypt.setKeyIdentifierType(reqData.getEncKeyId());
+        }
+        if (reqData.getEncKeyId() == WSConstants.EMBEDDED_KEYNAME) {
+            String encKeyName = handler.getString(WSHandlerConstants.ENC_KEY_NAME,
+                    reqData.getMsgContext());
+            wsEncrypt.setEmbeddedKeyName(encKeyName);
+            byte[] embeddedKey =
+                    handler.getPassword(reqData.getEncUser(),
+                            actionToDo,
+                            WSHandlerConstants.ENC_CALLBACK_CLASS,
+                            WSHandlerConstants.ENC_CALLBACK_REF, reqData)
+                            .getKey();
+            wsEncrypt.setKey(embeddedKey);
+            wsEncrypt.setDocument(doc);
+        }
+        if (reqData.getEncSymmAlgo() != null) {
+            wsEncrypt.setSymmetricEncAlgorithm(reqData.getEncSymmAlgo());
+        }
+        if (reqData.getEncKeyTransport() != null) {
+            wsEncrypt.setKeyEnc(reqData.getEncKeyTransport());
+        }
+        wsEncrypt.setUserInfo(reqData.getEncUser());
+        wsEncrypt.setUseThisCert(reqData.getEncCert());
+        if (reqData.getEncryptParts().size() > 0) {
+            wsEncrypt.setParts(reqData.getEncryptParts());
+        }
+        try {
+            wsEncrypt.build(doc, reqData.getEncCrypto(), reqData.getSecHeader());
+        } catch (WSSecurityException e) {
+            throw new WSSecurityException("Error during encryption: ", e);
+        }
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/action/SAMLTokenSignedAction.java b/trunk/src/org/apache/ws/security/action/SAMLTokenSignedAction.java
new file mode 100644
index 0000000..f63b304
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/action/SAMLTokenSignedAction.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.action;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.saml.SAMLIssuer;
+import org.apache.ws.security.saml.SAMLIssuerFactory;
+import org.apache.ws.security.saml.WSSecSignatureSAML;
+import org.opensaml.SAMLAssertion;
+import org.w3c.dom.Document;
+
+public class SAMLTokenSignedAction implements Action {
+    
+    private static Log log = LogFactory.getLog(SAMLTokenSignedAction.class.getName());
+
+    public void execute(WSHandler handler, int actionToDo, Document doc, RequestData reqData)
+            throws WSSecurityException {
+        Crypto crypto = null;
+        /*
+        * it is possible and legal that we do not have a signature
+        * crypto here - thus ignore the exception. This is usually
+        * the case for the SAML option "sender vouches". In this case
+        * no user crypto is required.
+        */
+        try {
+            crypto = handler.loadSignatureCrypto(reqData);
+        } catch (Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug(t.getMessage(), t);
+            }
+        }
+
+        SAMLIssuer saml = loadSamlIssuer(handler, reqData);
+        saml.setUsername(reqData.getUsername());
+        saml.setUserCrypto(crypto);
+        saml.setInstanceDoc(doc);
+
+        SAMLAssertion assertion = saml.newAssertion();
+        if (assertion == null) {
+            throw new WSSecurityException("WSHandler: Signed SAML: no SAML token received");
+        }
+        String issuerKeyName = null;
+        String issuerKeyPW = null;
+        Crypto issuerCrypto = null;
+
+        WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
+        wsSign.setWsConfig(reqData.getWssConfig());
+
+        String password = null;
+        if (saml.isSenderVouches()) {
+            issuerKeyName = saml.getIssuerKeyName();
+            issuerKeyPW = saml.getIssuerKeyPassword();
+            issuerCrypto = saml.getIssuerCrypto();
+        } else {
+            password =
+                    handler.getPassword(reqData.getUsername(),
+                            actionToDo,
+                            WSHandlerConstants.PW_CALLBACK_CLASS,
+                            WSHandlerConstants.PW_CALLBACK_REF, reqData)
+                            .getPassword();
+            wsSign.setUserInfo(reqData.getUsername(), password);
+        }
+        if (reqData.getSigKeyId() != 0) {
+            wsSign.setKeyIdentifierType(reqData.getSigKeyId());
+        }
+
+         /*
+         * required to add support for the 
+         * signatureParts parameter.
+         * If not set WSSecSignatureSAML
+         * defaults to only sign the body.
+         */
+        if (reqData.getSignatureParts().size() > 0) {
+            wsSign.setParts(reqData.getSignatureParts());
+        }
+
+        try {
+            wsSign.build(
+                    doc,
+                    crypto,
+                    assertion,
+                    issuerCrypto,
+                    issuerKeyName,
+                    issuerKeyPW,
+                    reqData.getSecHeader());
+            reqData.getSignatureValues().add(wsSign.getSignatureValue());
+        } catch (WSSecurityException e) {
+            throw new WSSecurityException("Error when signing the SAML token: ", e);
+        }
+    }
+
+    protected SAMLIssuer loadSamlIssuer(WSHandler handler, 
+                    RequestData reqData) {
+        String samlPropFile = 
+            handler.getString(WSHandlerConstants.SAML_PROP_FILE,
+                reqData.getMsgContext());
+        return SAMLIssuerFactory.getInstance(samlPropFile);
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/action/SAMLTokenUnsignedAction.java b/trunk/src/org/apache/ws/security/action/SAMLTokenUnsignedAction.java
new file mode 100644
index 0000000..237e6b4
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/action/SAMLTokenUnsignedAction.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.action;
+
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.message.WSSecSAMLToken;
+import org.apache.ws.security.saml.SAMLIssuer;
+import org.opensaml.SAMLAssertion;
+import org.w3c.dom.Document;
+
+public class SAMLTokenUnsignedAction extends SAMLTokenSignedAction {
+
+    public void execute(WSHandler handler, int actionToDo, Document doc, RequestData reqData)
+            throws WSSecurityException {
+        WSSecSAMLToken builder = new WSSecSAMLToken();
+        builder.setWsConfig(reqData.getWssConfig());
+
+        SAMLIssuer saml = loadSamlIssuer(handler, reqData);
+        saml.setUsername(reqData.getUsername());
+        SAMLAssertion assertion = saml.newAssertion();
+
+        // add the SAMLAssertion Token to the SOAP Envelope
+        builder.build(doc, assertion, reqData.getSecHeader());
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/action/SignatureAction.java b/trunk/src/org/apache/ws/security/action/SignatureAction.java
new file mode 100644
index 0000000..6cb314e
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/action/SignatureAction.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.action;
+
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.message.WSSecSignature;
+import org.w3c.dom.Document;
+
+public class SignatureAction implements Action {
+    public void execute(WSHandler handler, int actionToDo, Document doc, RequestData reqData)
+            throws WSSecurityException {
+        String password;
+        password =
+                handler.getPassword(reqData.getUsername(),
+                        actionToDo,
+                        WSHandlerConstants.PW_CALLBACK_CLASS,
+                        WSHandlerConstants.PW_CALLBACK_REF, reqData)
+                        .getPassword();
+
+        WSSecSignature wsSign = new WSSecSignature();
+        wsSign.setWsConfig(reqData.getWssConfig());
+
+        if (reqData.getSigKeyId() != 0) {
+            wsSign.setKeyIdentifierType(reqData.getSigKeyId());
+        }
+        if (reqData.getSigAlgorithm() != null) {
+            wsSign.setSignatureAlgorithm(reqData.getSigAlgorithm());
+        }
+
+        wsSign.setUserInfo(reqData.getUsername(), password);
+        if (reqData.getSignatureParts().size() > 0) {
+            wsSign.setParts(reqData.getSignatureParts());
+        }
+
+        try {
+            wsSign.build(doc, reqData.getSigCrypto(), reqData.getSecHeader());
+            reqData.getSignatureValues().add(wsSign.getSignatureValue());
+        } catch (WSSecurityException e) {
+            throw new WSSecurityException("Error during Signature: ", e);
+        }
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/action/SignatureConfirmationAction.java b/trunk/src/org/apache/ws/security/action/SignatureConfirmationAction.java
new file mode 100644
index 0000000..427575d
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/action/SignatureConfirmationAction.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.action;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.handler.WSHandlerResult;
+import org.apache.ws.security.message.WSSecSignatureConfirmation;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+
+import java.util.Vector;
+
+public class SignatureConfirmationAction implements Action {
+    protected static Log log = LogFactory.getLog(WSHandler.class.getName());
+
+    public void execute(WSHandler handler, int actionToDo, Document doc, RequestData reqData)
+            throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("Perform Signature confirmation");
+        }
+
+        Vector results = (Vector) handler.getProperty(reqData.getMsgContext(),
+                WSHandlerConstants.RECV_RESULTS);
+        /*
+         * loop over all results gathered by all handlers in the chain. For each
+         * handler result get the various actions. After that loop we have all
+         * signature results in the signatureActions vector
+         */
+        Vector signatureActions = new Vector();
+        for (int i = 0; i < results.size(); i++) {
+            WSHandlerResult wshResult = (WSHandlerResult) results.get(i);
+
+            WSSecurityUtil.fetchAllActionResults(wshResult.getResults(),
+                    WSConstants.SIGN, signatureActions);
+            WSSecurityUtil.fetchAllActionResults(wshResult.getResults(),
+                    WSConstants.ST_SIGNED, signatureActions);
+            WSSecurityUtil.fetchAllActionResults(wshResult.getResults(),
+                    WSConstants.UT_SIGN, signatureActions);
+        }
+        Vector signatureParts = reqData.getSignatureParts();
+        // prepare a SignatureConfirmation token
+        WSSecSignatureConfirmation wsc = new WSSecSignatureConfirmation();
+        if (signatureActions.size() > 0) {
+            if (log.isDebugEnabled()) {
+                log.debug("Signature Confirmation: number of Signature results: "
+                        + signatureActions.size());
+            }
+            for (int i = 0; i < signatureActions.size(); i++) {
+                WSSecurityEngineResult wsr = (WSSecurityEngineResult) signatureActions
+                        .get(i);
+                byte[] sigVal = (byte[]) wsr
+                        .get(WSSecurityEngineResult.TAG_SIGNATURE_VALUE);
+                wsc.build(doc, sigVal, reqData.getSecHeader());
+                signatureParts.add(new WSEncryptionPart(wsc.getId()));
+            }
+        } else {
+            wsc.build(doc, null, reqData.getSecHeader());
+            signatureParts.add(new WSEncryptionPart(wsc.getId()));
+        }
+        handler.setProperty(reqData.getMsgContext(), WSHandlerConstants.SIG_CONF_DONE,
+                WSHandler.DONE);
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/action/TimestampAction.java b/trunk/src/org/apache/ws/security/action/TimestampAction.java
new file mode 100644
index 0000000..14acedb
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/action/TimestampAction.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.action;
+
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.message.WSSecTimestamp;
+import org.w3c.dom.Document;
+
+public class TimestampAction implements Action {
+    public void execute(WSHandler handler, int actionToDo, Document doc, RequestData reqData)
+            throws WSSecurityException {
+        WSSecTimestamp timeStampBuilder =
+                new WSSecTimestamp();
+        timeStampBuilder.setWsConfig(reqData.getWssConfig());
+        timeStampBuilder.setTimeToLive(handler.decodeTimeToLive(reqData));
+        // add the Timestamp to the SOAP Envelope
+        timeStampBuilder.build(doc, reqData.getSecHeader());
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/action/UsernameTokenAction.java b/trunk/src/org/apache/ws/security/action/UsernameTokenAction.java
new file mode 100644
index 0000000..f99e946
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/action/UsernameTokenAction.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.action;
+
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.w3c.dom.Document;
+
+public class UsernameTokenAction implements Action {
+    public void execute(WSHandler handler, int actionToDo, Document doc, RequestData reqData)
+            throws WSSecurityException {
+        
+        // Always call the callback for the username. We mis-use the configured password callback class and callback methods for this.
+        String providedUsername = reqData.getUsername();
+        WSPasswordCallback callbackData = handler.getPassword(reqData.getUsername(),
+                        actionToDo,
+                        WSHandlerConstants.PW_CALLBACK_CLASS,
+                        WSHandlerConstants.PW_CALLBACK_REF, reqData);
+        providedUsername = callbackData.getIdentifier();
+        String password = callbackData.getPassword();
+
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setWsConfig(reqData.getWssConfig());
+        builder.setPasswordType(reqData.getPwType());
+        builder.setUserInfo(providedUsername, password);
+
+        if (reqData.getUtElements() != null && reqData.getUtElements().length > 0) {
+            for (int j = 0; j < reqData.getUtElements().length; j++) {
+                reqData.getUtElements()[j].trim();
+                if (reqData.getUtElements()[j].equals("Nonce")) {
+                    builder.addNonce();
+                }
+                if (reqData.getUtElements()[j].equals("Created")) {
+                    builder.addCreated();
+                }
+                reqData.getUtElements()[j] = null;
+            }
+        }
+        builder.build(doc, reqData.getSecHeader());        
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/action/UsernameTokenSignedAction.java b/trunk/src/org/apache/ws/security/action/UsernameTokenSignedAction.java
new file mode 100644
index 0000000..c042529
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/action/UsernameTokenSignedAction.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright  2003-2007 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.action;
+
+import java.util.Vector;
+
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.signature.XMLSignature;
+import org.w3c.dom.Document;
+
+/**
+ * Sign a request using a secret key derived from UsernameToken data.
+ * 
+ * Enhanced by Alberto Coletti to support digest password type for 
+ * username token signature
+ * 
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de)
+ */
+
+public class UsernameTokenSignedAction implements Action {
+    public void execute(WSHandler handler, int actionToDo, Document doc, RequestData reqData)
+            throws WSSecurityException {
+        String password;
+        password = handler.getPassword(reqData.getUsername(), actionToDo,
+                WSHandlerConstants.PW_CALLBACK_CLASS,
+                WSHandlerConstants.PW_CALLBACK_REF, reqData).getPassword();
+
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setWsConfig(reqData.getWssConfig());
+        builder.setPasswordType(reqData.getPwType());  // enhancement by Alberto Coletti
+        
+        builder.setUserInfo(reqData.getUsername(), password);
+        builder.addCreated();
+        builder.addNonce();
+        builder.prepare(doc);
+
+        // Now prepare to sign.
+        // First step:  Get a WS Signature object and set config parameters
+        // second step: set user data and algorithm parameters. This
+        //              _must_ be done before we "prepare"
+        // third step:  Call "prepare". This creates the internal WS Signature
+        //              data structures, XML element, fills in the algorithms
+        //              and other data.
+        // fourth step: Get the references. These references identify the parts
+        //              of the document that will be included into the 
+        //              signature. If no references are given sign the message
+        //              body by default.
+        // fifth step:  compute the signature
+        //
+        // after "prepare" the Signature XML element is ready and may prepend
+        // this to the security header.
+        
+        WSSecSignature sign = new WSSecSignature();
+        sign.setWsConfig(reqData.getWssConfig());
+
+        sign.setUsernameToken(builder);
+        sign.setKeyIdentifierType(WSConstants.UT_SIGNING);
+        sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+
+        sign.prepare(doc, null, reqData.getSecHeader());
+
+        // prepend in this order: first the Signature Element and then the
+        // UsernameToken Element. This way the server gets the UsernameToken
+        // first, can check it and are prepared to compute the Signature key.  
+        sign.prependToHeader(reqData.getSecHeader());
+        builder.prependToHeader(reqData.getSecHeader());
+
+        Vector parts = null;
+        if (reqData.getSignatureParts().size() > 0) {
+            parts = reqData.getSignatureParts();
+        }
+        else {
+            SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                    .getDocumentElement());
+            
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+        sign.addReferencesToSign(parts, reqData.getSecHeader());
+
+        try {
+            sign.computeSignature();
+            reqData.getSignatureValues().add(sign.getSignatureValue());
+        } catch (WSSecurityException e) {
+            throw new WSSecurityException(
+                "WSHandler: Error during UsernameTokenSignature", e
+            );
+        }
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/components/crypto/AbstractCrypto.java b/trunk/src/org/apache/ws/security/components/crypto/AbstractCrypto.java
new file mode 100644
index 0000000..5abc19c
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/components/crypto/AbstractCrypto.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.components.crypto;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.util.Loader;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.cert.CertificateFactory;
+import java.util.Properties;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dims
+ * Date: Sep 15, 2005
+ * Time: 9:50:40 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public abstract class AbstractCrypto extends CryptoBase {
+    
+    private static final Log log = LogFactory.getLog(AbstractCrypto.class.getName());
+    private static final boolean doDebug = log.isDebugEnabled();
+
+    protected static CertificateFactory certFact;
+    protected Properties properties = null;
+    
+    /**
+     * Constructor
+     *
+     * @param properties
+     */
+    public AbstractCrypto(Properties properties) throws CredentialException, IOException {
+        this(properties, AbstractCrypto.class.getClassLoader());
+    }
+
+    /**
+     * This allows providing a custom class loader to load the resources, etc
+     * @param properties
+     * @param loader
+     * @throws CredentialException
+     * @throws IOException
+     */
+    public AbstractCrypto(Properties properties, ClassLoader loader) throws CredentialException, IOException {
+        this.properties = properties;
+        if (this.properties == null) {
+            return;
+        }
+        String location = this.properties.getProperty("org.apache.ws.security.crypto.merlin.file");
+        InputStream is = null;
+        if (location != null) {
+            java.net.URL url = Loader.getResource(loader, location);
+            if(url != null) {
+                is =  url.openStream();
+            } else {
+                is = new java.io.FileInputStream(location);
+            }
+    
+            /**
+             * If we don't find it, then look on the file system.
+             */
+            if (is == null) {
+                try {
+                    is = new FileInputStream(location);
+                } catch (Exception e) {
+                    if (doDebug) {
+                        log.debug(e.getMessage(), e);
+                    }
+                    throw new CredentialException(
+                        CredentialException.IO_ERROR, "proxyNotFound", new Object[]{location}, e
+                    );
+                }
+            }
+        }
+
+        /**
+         * Load the keystore
+         */
+        try {
+            String provider = properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.provider");
+            String passwd = properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.password", "security");
+            String type = properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.type", KeyStore.getDefaultType());
+            this.keystore = load(is, passwd, provider, type);
+        } finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+
+        /**
+         * Load cacerts
+         */
+        String cacertsPath = System.getProperty("java.home") + "/lib/security/cacerts";
+        InputStream cacertsIs = new FileInputStream(cacertsPath);
+        try {
+            String cacertsPasswd = properties.getProperty("org.apache.ws.security.crypto.merlin.cacerts.password", "changeit");
+            this.cacerts = load(cacertsIs, cacertsPasswd, null, KeyStore.getDefaultType());
+        } finally {
+            cacertsIs.close();
+        }
+    }
+
+
+    /**
+     * Loads the keystore from an <code>InputStream </code>.
+     * <p/>
+     *
+     * @param input <code>InputStream</code> to read from
+     * @throws CredentialException
+     */
+    public KeyStore load(InputStream input, String storepass, String provider, String type) throws CredentialException {
+        KeyStore ks = null;
+        
+        try {
+            if (provider == null || provider.length() == 0) {
+                ks = KeyStore.getInstance(type);
+            } else {
+                ks = KeyStore.getInstance(type, provider);
+            }
+                    
+            ks.load(input, (storepass == null || storepass.length() == 0) ? new char[0] : storepass.toCharArray());
+        } catch (IOException e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+            throw new CredentialException(CredentialException.IO_ERROR, "ioError00", e);
+        } catch (GeneralSecurityException e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+            throw new CredentialException(CredentialException.SEC_ERROR, "secError00", e);
+        } catch (Exception e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+            throw new CredentialException(CredentialException.FAILURE, "error00", e);
+        }
+        return ks;
+    }
+
+    
+    protected String
+    getCryptoProvider() {
+        return properties.getProperty("org.apache.ws.security.crypto.merlin.cert.provider");
+    }
+
+    /**
+     * Retrieves the alias name of the default certificate which has been
+     * specified as a property. This should be the certificate that is used for
+     * signature and encryption. This alias corresponds to the certificate that
+     * should be used whenever KeyInfo is not present in a signed or
+     * an encrypted message. May return null.
+     *
+     * @return alias name of the default X509 certificate
+     */
+    public String getDefaultX509Alias() {
+        if (properties == null) {
+            return null;
+        }
+        return properties.getProperty("org.apache.ws.security.crypto.merlin.keystore.alias");
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/components/crypto/BouncyCastle.java b/trunk/src/org/apache/ws/security/components/crypto/BouncyCastle.java
new file mode 100644
index 0000000..ebb10a7
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/components/crypto/BouncyCastle.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.components.crypto;
+
+import org.apache.ws.security.WSSecurityException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.PKIXParameters;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * JDK1.4 based implementation of Crypto (uses keystore).
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class BouncyCastle extends AbstractCrypto {
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param properties
+     * @throws CredentialException
+     * @throws java.io.IOException
+     */
+    public BouncyCastle(Properties properties) throws CredentialException, IOException {
+        super(properties);
+    }
+
+    public BouncyCastle(Properties properties, ClassLoader loader) throws CredentialException, IOException {
+        super(properties,loader);
+    }
+
+    /**
+     * Construct an array of X509Certificate's from the byte array.
+     * <p/>
+     *
+     * @param data    The <code>byte</code> array containing the X509 data
+     * @param reverse If set the first certificate in input data will
+     *                the last in the array
+     * @return An array of X509 certificates, ordered according to
+     *         the reverse flag
+     * @throws org.apache.ws.security.WSSecurityException
+     *
+     */
+    public X509Certificate[] getX509Certificates(byte[] data, boolean reverse)
+            throws WSSecurityException {
+        InputStream in = new ByteArrayInputStream(data);
+        CertPath path = null;
+        try {
+            CertificateFactory factory = CertificateFactory.getInstance("X.509");
+            path = factory.generateCertPath(in);
+        } catch (CertificateException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "parseError", null, e
+            );
+        }
+        List l = path.getCertificates();
+        X509Certificate[] certs = new X509Certificate[l.size()];
+        Iterator iterator = l.iterator();
+        for (int i = 0; i < l.size(); i++) {
+            certs[(reverse) ? (l.size() - 1 - i) : i] = (X509Certificate) iterator.next();
+        }
+        return certs;
+    }
+
+    /**
+     * get a byte array given an array of X509 certificates.
+     * <p/>
+     *
+     * @param reverse If set the first certificate in the array data will
+     *                the last in the byte array
+     * @param certs   The certificates to convert
+     * @return The byte array for the certificates ordered according
+     *         to the reverse flag
+     * @throws org.apache.ws.security.WSSecurityException
+     *
+     */
+    public byte[] getCertificateData(boolean reverse, X509Certificate[] certs)
+            throws WSSecurityException {
+        Vector list = new Vector();
+        for (int i = 0; i < certs.length; i++) {
+            if (reverse) {
+                list.insertElementAt(certs[i], 0);
+            } else {
+                list.add(certs[i]);
+            }
+        }
+        try {
+            CertificateFactory factory = CertificateFactory.getInstance("X.509");
+            CertPath path = factory.generateCertPath(list);
+            return path.getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError", null, e
+            );
+        } catch (CertificateException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "parseError", null, e
+            );
+        }
+    }
+
+    /**
+     * Uses the CertPath API to validate a given certificate chain
+     *
+     * @param certs Certificate chain to validate
+     * @return true if the certificate chain is valid, false otherwise
+     * @throws org.apache.ws.security.WSSecurityException
+     *
+     */
+    public boolean validateCertPath(X509Certificate[] certs) throws WSSecurityException {
+
+        try {
+            // Generate cert path
+            List certList = Arrays.asList(certs);
+            CertificateFactory factory = CertificateFactory.getInstance("X.509");
+            CertPath path = factory.generateCertPath(certList);
+
+            // Use the certificates in the keystore as TrustAnchors
+            PKIXParameters param = new PKIXParameters(this.keystore);
+
+            // Do not check a revocation list
+            param.setRevocationEnabled(false);
+
+            // Verify the trust path using the above settings            
+            CertPathValidator certPathValidator = CertPathValidator.getInstance("PKIX");
+            certPathValidator.validate(path, param);
+        } catch (NoSuchAlgorithmException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath",
+                    new Object[]{ex.getMessage()},
+                    (Throwable) ex);
+        } catch (CertificateException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath",
+                    new Object[]{ex.getMessage()},
+                    (Throwable) ex);
+        } catch (InvalidAlgorithmParameterException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath",
+                    new Object[]{ex.getMessage()},
+                    (Throwable) ex);
+        } catch (KeyStoreException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath",
+                    new Object[]{ex.getMessage()},
+                    (Throwable) ex);
+        } catch (CertPathValidatorException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath",
+                    new Object[]{ex.getMessage()},
+                    (Throwable) ex);
+        }
+        return true;
+    }
+}
+
+
diff --git a/trunk/src/org/apache/ws/security/components/crypto/CredentialException.java b/trunk/src/org/apache/ws/security/components/crypto/CredentialException.java
new file mode 100644
index 0000000..956ab43
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/components/crypto/CredentialException.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.components.crypto;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * CredentialException.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class CredentialException extends Exception {
+    public static final int FAILURE = -1;
+    public static final int EXPIRED = 1;
+    public static final int DEFECTIVE = 2;
+    public static final int IO_ERROR = 3;
+    public static final int SEC_ERROR = 4;
+    private static ResourceBundle resources;
+    private int errorCode;
+
+    static {
+        try {
+            resources = ResourceBundle.getBundle("org.apache.ws.security.components.crypto.errors");
+        } catch (MissingResourceException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param errorCode
+     * @param msgId
+     * @param root
+     */
+    public CredentialException(int errorCode, String msgId, Throwable root) {
+        this(errorCode, msgId, null, root);
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param errorCode
+     * @param msgId
+     * @param args
+     */
+    public CredentialException(int errorCode, String msgId, Object[] args) {
+        this(errorCode, msgId, args, null);
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param errorCode
+     * @param msgId
+     * @param args
+     * @param root
+     */
+    public CredentialException(int errorCode, String msgId, Object[] args, Throwable root) {
+        super(getMessage(msgId, args), root);
+        this.errorCode = errorCode;
+    }
+
+    /**
+     * get the error code.
+     * <p/>
+     *
+     * @return error code of this exception See values above.
+     */
+    public int getErrorCode() {
+        return errorCode;
+    }
+
+    /**
+     * get the actual message.
+     * <p/>
+     *
+     * @param msgId
+     * @param args
+     * @return the message translated from the property (message) file.
+     */
+    private static String getMessage(String msgId, Object[] args) {
+        try {
+            return MessageFormat.format(resources.getString(msgId), args);
+        } catch (MissingResourceException e) {
+            throw new RuntimeException("bad" + msgId, e);
+        }
+    }
+}
+
diff --git a/trunk/src/org/apache/ws/security/components/crypto/Crypto.java b/trunk/src/org/apache/ws/security/components/crypto/Crypto.java
new file mode 100644
index 0000000..53eff38
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/components/crypto/Crypto.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.components.crypto;
+
+import org.apache.ws.security.WSSecurityException;
+
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+/**
+ * Crypto.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public interface Crypto {
+    /**
+     * load a X509Certificate from the input stream.
+     * <p/>
+     *
+     * @param in The <code>InputStream</code> array containing the X509 data
+     * @return An X509 certificate
+     * @throws WSSecurityException
+     */
+    X509Certificate loadCertificate(InputStream in) throws WSSecurityException;
+
+    /**
+     * Construct an array of X509Certificate's from the byte array.
+     * <p/>
+     *
+     * @param data    The <code>byte</code> array containing the X509 data
+     * @param reverse If set the first certificate in input data will
+     *                the last in the array
+     * @return An array of X509 certificates, ordered according to
+     *         the reverse flag
+     * @throws WSSecurityException
+     */
+    X509Certificate[] getX509Certificates(byte[] data, boolean reverse) throws WSSecurityException;
+
+    /**
+     * get a byte array given an array of X509 certificates.
+     * <p/>
+     *
+     * @param reverse If set the first certificate in the array data will
+     *                the last in the byte array
+     * @param certs   The certificates to convert
+     * @return The byte array for the certificates ordered according
+     *         to the reverse flag
+     * @throws WSSecurityException
+     */
+    byte[] getCertificateData(boolean reverse, X509Certificate[] certs) throws WSSecurityException;
+
+    /**
+     * Gets the private key identified by <code>alias</> and <code>password</code>.
+     * <p/>
+     *
+     * @param alias    The alias (<code>KeyStore</code>) of the key owner
+     * @param password The password needed to access the private key
+     * @return The private key
+     * @throws Exception
+     */
+    public PrivateKey getPrivateKey(String alias, String password) throws Exception;
+
+    /**
+     * get the list of certificates for a given alias. This method
+     * reads a new certificate chain and overwrites a previously
+     * stored certificate chain.
+     * <p/>
+     *
+     * @param alias Lookup certificate chain for this alias
+     * @return Array of X509 certificates for this alias name, or
+     *         null if this alias does not exist in the keystore
+     */
+    public X509Certificate[] getCertificates(String alias) throws WSSecurityException;
+
+    /**
+     * Return a X509 Certificate alias in the keystore according to a given Certificate
+     * <p/>
+     *
+     * @param cert The certificate to lookup
+     * @return alias name of the certificate that matches the given certificate
+     *         or null if no such certificate was found.
+     *         <p/>
+     *         See comment above
+     *         <p/>
+     *         See comment above
+     */
+    /*
+     * See comment above
+     */
+    public String getAliasForX509Cert(Certificate cert) throws WSSecurityException;
+
+    /**
+     * Lookup a X509 Certificate in the keystore according to a given
+     * the issuer of a Certificate.
+     * <p/>
+     * The search gets all alias names of the keystore and gets the certificate chain
+     * for each alias. Then the Issuer of each certificate of the chain
+     * is compared with the parameters.
+     *
+     * @param issuer The issuer's name for the certificate
+     * @return alias name of the certificate that matches the issuer name
+     *         or null if no such certificate was found.
+     */
+    public String getAliasForX509Cert(String issuer) throws WSSecurityException;
+
+    /**
+     * Search a X509 Certificate in the keystore according to a given serial number and
+     * the issuer of a Certificate.
+     * <p/>
+     * The search gets all alias names of the keystore and gets the certificate chain
+     * for each alias. Then the SerialNumber and Issuer of each certificate of the chain
+     * is compared with the parameters.
+     *
+     * @param issuer       The issuer's name for the certificate
+     * @param serialNumber The serial number of the certificate from the named issuer
+     * @return alias name of the certificate that matches serialNumber and issuer name
+     *         or null if no such certificate was found.
+     */
+    public String getAliasForX509Cert(String issuer, BigInteger serialNumber) throws WSSecurityException;
+
+    /**
+     * Lookup a X509 Certificate in the keystore according to a given
+     * SubjectKeyIdentifier.
+     * <p/>
+     * The search gets all alias names of the keystore and gets the certificate chain
+     * or certificate for each alias. Then the SKI for each user certificate
+     * is compared with the SKI parameter.
+     *
+     * @param skiBytes The SKI info bytes
+     * @return alias name of the certificate that matches serialNumber and issuer name
+     *         or null if no such certificate was found.
+     */
+    public String getAliasForX509Cert(byte[] skiBytes) throws WSSecurityException;
+
+    /**
+     * Retrieves the alias name of the default certificate which has been
+     * specified as a property. This should be the certificate that is used for
+     * signature and encryption. This alias corresponds to the certificate that
+     * should be used whenever KeyInfo is not present in a signed or
+     * an encrypted message. May return null.
+     *
+     * @return alias name of the default X509 certificate.
+     */
+    public String getDefaultX509Alias();
+
+    /**
+     * Reads the SubjectKeyIdentifier information from the certificate.
+     * <p/>
+     *
+     * @param cert The certificate to read SKI
+     * @return The byte array containing the binary SKI data
+     */
+    public byte[] getSKIBytesFromCert(X509Certificate cert) throws WSSecurityException;
+ 
+    /**
+     * Lookup a X509 Certificate in the keystore according to a given
+     * Thumbprint.
+     * 
+     * The search gets all alias names of the keystore, then reads the certificate chain
+     * or certificate for each alias. Then the thumbprint for each user certificate
+     * is compared with the thumbprint parameter.
+     *
+     * @param thumb The SHA1 thumbprint info bytes
+     * @return alias name of the certificate that matches the thumbprint
+     *         or null if no such certificate was found.
+     * @throws WSSecurityException if problems during keystore handling or wrong certificate
+     */
+
+    public String getAliasForX509CertThumb(byte[] thumb) throws WSSecurityException;
+ 
+    /**
+     * Gets the Keystore that was loaded by the underlying implementation
+     *
+     * @return the Keystore
+     */
+    public KeyStore getKeyStore();
+
+    /**
+     * Gets the CertificateFactory instantiated by the underlying implementation
+     *
+     * @return the CertificateFactory
+     * @throws WSSecurityException
+     */
+    public CertificateFactory getCertificateFactory() throws WSSecurityException;
+
+    /**
+     * Uses the CertPath API to validate a given certificate chain
+     * <p/>
+     *
+     * @param certs Certificate chain to validate
+     * @return true if the certificate chain is valid, false otherwise
+     * @throws WSSecurityException
+     */
+    public boolean validateCertPath(X509Certificate[] certs) throws WSSecurityException;
+
+    /**
+     * Lookup X509 Certificates in the keystore according to a given DN of the subject of the certificate
+     * <p/>
+     *
+     * @param subjectDN The DN of subject to look for in the keystore
+     * @return Vector with all alias of certificates with the same DN as given in the parameters
+     * @throws WSSecurityException
+     */
+    public String[] getAliasesForDN(String subjectDN) throws WSSecurityException;
+}
diff --git a/trunk/src/org/apache/ws/security/components/crypto/CryptoBase.java b/trunk/src/org/apache/ws/security/components/crypto/CryptoBase.java
new file mode 100644
index 0000000..f049c02
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/components/crypto/CryptoBase.java
@@ -0,0 +1,733 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.components.crypto;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityException;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.CertPath;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: dims
+ * Date: Sep 15, 2005
+ * Time: 9:50:40 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public abstract class CryptoBase implements Crypto {
+    private static Log log = LogFactory.getLog(CryptoBase.class);
+    protected static CertificateFactory certFact;
+    protected KeyStore keystore = null;
+    static String SKI_OID = "2.5.29.14";
+    protected KeyStore cacerts = null;
+    
+    /**
+     * Constructor
+     */
+    protected CryptoBase() {
+    }
+    
+    /**
+     * @return      a crypto provider name.  This operation should
+     *              return null if the default crypto provider should
+     *              be used.
+     */
+    protected abstract String getCryptoProvider();
+    
+    /**
+     * Singleton certificate factory for this Crypto instance.
+     * <p/>
+     *
+     * @return Returns a <code>CertificateFactory</code> to construct
+     *         X509 certficates
+     * @throws org.apache.ws.security.WSSecurityException
+     *
+     */
+    public synchronized CertificateFactory getCertificateFactory() throws WSSecurityException {
+        if (certFact == null) {
+            try {
+                String provider = getCryptoProvider();
+                if (provider == null || provider.length() == 0) {
+                    certFact = CertificateFactory.getInstance("X.509");
+                } else {
+                    certFact = CertificateFactory.getInstance("X.509", provider);
+                }
+            } catch (CertificateException e) {
+                throw new WSSecurityException(
+                    WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "unsupportedCertType",
+                    null, e
+                );
+            } catch (NoSuchProviderException e) {
+                throw new WSSecurityException(
+                    WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "noSecProvider",
+                    null, e
+                );
+            }
+        }
+        return certFact;
+    }
+
+    /**
+     * load a X509Certificate from the input stream.
+     * <p/>
+     *
+     * @param in The <code>InputStream</code> array containing the X509 data
+     * @return Returns a X509 certificate
+     * @throws org.apache.ws.security.WSSecurityException
+     *
+     */
+    public X509Certificate loadCertificate(InputStream in) throws WSSecurityException {
+        X509Certificate cert = null;
+        try {
+            cert = (X509Certificate) getCertificateFactory().generateCertificate(in);
+        } catch (CertificateException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "parseError",
+                null, e
+            );
+        }
+        return cert;
+    }
+
+    /**
+     * Gets the private key identified by <code>alias</> and <code>password</code>.
+     * <p/>
+     *
+     * @param alias    The alias (<code>KeyStore</code>) of the key owner
+     * @param password The password needed to access the private key
+     * @return The private key
+     * @throws Exception
+     */
+    public PrivateKey getPrivateKey(String alias, String password) throws Exception {
+        if (alias == null) {
+            throw new Exception("alias is null");
+        }
+        boolean b = keystore.isKeyEntry(alias);
+        if (!b) {
+            log.error("Cannot find key for alias: " + alias);
+            throw new Exception("Cannot find key for alias: " + alias);
+        }
+        Key keyTmp = keystore.getKey(alias, password.toCharArray());
+        if (!(keyTmp instanceof PrivateKey)) {
+            throw new Exception("Key is not a private key, alias: " + alias);
+        }
+        return (PrivateKey) keyTmp;
+    }
+
+    protected Vector splitAndTrim(String inString) {
+        X509NameTokenizer nmTokens = new X509NameTokenizer(inString);
+        Vector vr = new Vector();
+
+        while (nmTokens.hasMoreTokens()) {
+            vr.add(nmTokens.nextToken());
+        }
+        java.util.Collections.sort(vr);
+        return vr;
+    }
+
+    /**
+     * Lookup a X509 Certificate in the keystore according to a given
+     * the issuer of a Certificate.
+     * <p/>
+     * The search gets all alias names of the keystore and gets the certificate chain
+     * for each alias. Then the Issuer for each certificate of the chain
+     * is compared with the parameters.
+     *
+     * @param issuer The issuer's name for the certificate
+     * @return alias name of the certificate that matches the issuer name
+     *         or null if no such certificate was found.
+     */
+    public String getAliasForX509Cert(String issuer)
+            throws WSSecurityException {
+        return getAliasForX509Cert(issuer, null, false);
+    }
+
+    /**
+     * Lookup a X509 Certificate in the keystore according to a given serial number and
+     * the issuer of a Certificate.
+     * <p/>
+     * The search gets all alias names of the keystore and gets the certificate chain
+     * for each alias. Then the SerialNumber and Issuer for each certificate of the chain
+     * is compared with the parameters.
+     *
+     * @param issuer       The issuer's name for the certificate
+     * @param serialNumber The serial number of the certificate from the named issuer
+     * @return alias name of the certificate that matches serialNumber and issuer name
+     *         or null if no such certificate was found.
+     */
+    public String getAliasForX509Cert(String issuer, BigInteger serialNumber)
+            throws WSSecurityException {
+        return getAliasForX509Cert(issuer, serialNumber, true);
+    }
+
+    /*
+    * need to check if "getCertificateChain" also finds certificates that are
+    * used for encryption only, i.e. they may not be signed by a CA
+    * Otherwise we must define a restriction how to use certificate:
+    * each certificate must be signed by a CA or is a self signed Certificate
+    * (this should work as well).
+    * --- remains to be tested in several ways --
+    */
+    private String getAliasForX509Cert(String issuer, BigInteger serialNumber,
+                                       boolean useSerialNumber)
+            throws WSSecurityException {
+        Vector issuerRDN = splitAndTrim(issuer);
+        X509Certificate x509cert = null;
+        Vector certRDN = null;
+        Certificate cert = null;
+
+        try {
+            for (Enumeration e = keystore.aliases(); e.hasMoreElements();) {
+                String alias = (String) e.nextElement();
+                Certificate[] certs = keystore.getCertificateChain(alias);
+                if (certs == null || certs.length == 0) {
+                    // no cert chain, so lets check if getCertificate gives us a  result.
+                    cert = keystore.getCertificate(alias);
+                    if (cert == null) {
+                        return null;
+                    }
+                } else {
+                    cert = certs[0];
+                }
+                if (!(cert instanceof X509Certificate)) {
+                    continue;
+                }
+                x509cert = (X509Certificate) cert;
+                if (!useSerialNumber ||
+                        useSerialNumber && x509cert.getSerialNumber().compareTo(serialNumber) == 0) {
+                    certRDN = splitAndTrim(x509cert.getIssuerDN().getName());
+                    if (certRDN.equals(issuerRDN)) {
+                        return alias;
+                    }
+                }
+            }
+        } catch (KeyStoreException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE, "keystore", null, e);
+        }
+        return null;
+    }
+
+    /**
+     * Lookup a X509 Certificate in the keystore according to a given
+     * SubjectKeyIdentifier.
+     * <p/>
+     * The search gets all alias names of the keystore and gets the certificate chain
+     * or certificate for each alias. Then the SKI for each user certificate
+     * is compared with the SKI parameter.
+     *
+     * @param skiBytes The SKI info bytes
+     * @return alias name of the certificate that matches serialNumber and issuer name
+     *         or null if no such certificate was found.
+     * @throws org.apache.ws.security.WSSecurityException
+     *          if problems during keystore handling or wrong certificate (no SKI data)
+     */
+
+    public String getAliasForX509Cert(byte[] skiBytes) throws WSSecurityException {
+        Certificate cert = null;
+
+        try {
+            for (Enumeration e = keystore.aliases(); e.hasMoreElements();) {
+                String alias = (String) e.nextElement();
+                Certificate[] certs = keystore.getCertificateChain(alias);
+                if (certs == null || certs.length == 0) {
+                    // no cert chain, so lets check if getCertificate gives us a  result.
+                    cert = keystore.getCertificate(alias);
+                    if (cert == null) {
+                        return null;
+                    }
+                } else {
+                    cert = certs[0];
+                }
+                if (!(cert instanceof X509Certificate)) {
+                    continue;
+                }
+                byte[] data = getSKIBytesFromCert((X509Certificate) cert);
+                if (data.length != skiBytes.length) {
+                    continue;
+                }
+                if (Arrays.equals(data, skiBytes)) {
+                    return alias;
+                }
+            }
+        } catch (KeyStoreException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE, "keystore", null, e);
+        }
+        return null;
+    }
+
+    /**
+     * Return a X509 Certificate alias in the keystore according to a given Certificate
+     * <p/>
+     *
+     * @param cert The certificate to lookup
+     * @return alias name of the certificate that matches the given certificate
+     *         or null if no such certificate was found.
+     */
+
+/*
+     * See comment above
+     */
+    public String getAliasForX509Cert(Certificate cert) throws WSSecurityException {
+        try {
+            String alias = keystore.getCertificateAlias(cert);
+            if (alias != null)
+                return alias;
+            // Use brute force search
+            Enumeration e = keystore.aliases();
+            while (e.hasMoreElements()) {
+                alias = (String) e.nextElement();
+                X509Certificate cert2 = (X509Certificate) keystore.getCertificate(alias);
+                if (cert2.equals(cert)) {
+                    return alias;
+                }
+            }
+        } catch (KeyStoreException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE, "keystore", null, e);
+        }
+        return null;
+    }
+
+
+    /**
+     * Gets the list of certificates for a given alias.
+     * <p/>
+     *
+     * @param alias Lookup certificate chain for this alias
+     * @return Array of X509 certificates for this alias name, or
+     *         null if this alias does not exist in the keystore
+     */
+    public X509Certificate[] getCertificates(String alias) throws WSSecurityException {
+        Certificate[] certs = null;
+        Certificate cert = null;
+        try {
+            if (this.keystore != null) {
+                //There's a chance that there can only be a set of trust stores
+                certs = keystore.getCertificateChain(alias);
+                if (certs == null || certs.length == 0) {
+                    // no cert chain, so lets check if getCertificate gives us a
+                    // result.
+                    cert = keystore.getCertificate(alias);
+                }
+            }
+
+            if (certs == null && cert == null && cacerts != null) {
+                // Now look into the trust stores
+                certs = cacerts.getCertificateChain(alias);
+                if (certs == null) {
+                    cert = cacerts.getCertificate(alias);
+                }
+            }
+
+            if (cert != null) {
+                certs = new Certificate[]{cert};
+            } else if (certs == null) {
+                // At this point we don't have certs or a cert
+                return null;
+            }
+        } catch (KeyStoreException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE, "keystore", null, e);
+        }
+
+        X509Certificate[] x509certs = new X509Certificate[certs.length];
+        for (int i = 0; i < certs.length; i++) {
+            x509certs[i] = (X509Certificate) certs[i];
+        }
+        return x509certs;
+    }
+
+    /**
+     * Lookup a X509 Certificate in the keystore according to a given
+     * Thumbprint.
+     * <p/>
+     * The search gets all alias names of the keystore, then reads the certificate chain
+     * or certificate for each alias. Then the thumbprint for each user certificate
+     * is compared with the thumbprint parameter.
+     *
+     * @param thumb The SHA1 thumbprint info bytes
+     * @return alias name of the certificate that matches the thumbprint
+     *         or null if no such certificate was found.
+     * @throws org.apache.ws.security.WSSecurityException
+     *          if problems during keystore handling or wrong certificate
+     */
+
+    public String getAliasForX509CertThumb(byte[] thumb) throws WSSecurityException {
+        Certificate cert = null;
+        MessageDigest sha = null;
+
+        try {
+            sha = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException e) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILURE, "noSHA1availabe", null, e
+            );
+        }
+        try {
+            for (Enumeration e = keystore.aliases(); e.hasMoreElements();) {
+                String alias = (String) e.nextElement();
+                Certificate[] certs = keystore.getCertificateChain(alias);
+                if (certs == null || certs.length == 0) {
+                    // no cert chain, so lets check if getCertificate gives us a  result.
+                    cert = keystore.getCertificate(alias);
+                    if (cert == null) {
+                        return null;
+                    }
+                } else {
+                    cert = certs[0];
+                }
+                if (!(cert instanceof X509Certificate)) {
+                    continue;
+                }
+                sha.reset();
+                try {
+                    sha.update(cert.getEncoded());
+                } catch (CertificateEncodingException ex) {
+                    throw new WSSecurityException(
+                        WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError",
+                        null, ex
+                    );
+                }
+                byte[] data = sha.digest();
+
+                if (Arrays.equals(data, thumb)) {
+                    return alias;
+                }
+            }
+        } catch (KeyStoreException e) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILURE, "keystore", null, e
+            );
+        }
+        return null;
+    }
+
+    /**
+     * A Hook for subclasses to set the keystore without having to
+     * load it from an <code>InputStream</code>.
+     *
+     * @param ks existing keystore
+     */
+    public void setKeyStore(KeyStore ks) {
+        keystore = ks;
+    }
+
+    /**
+     * Reads the SubjectKeyIdentifier information from the certificate.
+     * <p/>
+     * If the the certificate does not contain a SKI extension then
+     * try to compute the SKI according to RFC3280 using the
+     * SHA-1 hash value of the public key. The second method described
+     * in RFC3280 is not support. Also only RSA public keys are supported.
+     * If we cannot compute the SKI throw a WSSecurityException.
+     *
+     * @param cert The certificate to read SKI
+     * @return The byte array containing the binary SKI data
+     */
+    public byte[] getSKIBytesFromCert(X509Certificate cert)
+            throws WSSecurityException {
+        /*
+           * Gets the DER-encoded OCTET string for the extension value (extnValue)
+           * identified by the passed-in oid String. The oid string is represented
+           * by a set of positive whole numbers separated by periods.
+           */
+        byte[] derEncodedValue = cert.getExtensionValue(SKI_OID);
+
+        if (cert.getVersion() < 3 || derEncodedValue == null) {
+            PublicKey key = cert.getPublicKey();
+            if (!(key instanceof RSAPublicKey)) {
+                throw new WSSecurityException(
+                        1,
+                        "noSKIHandling",
+                        new Object[]{"Support for RSA key only"});
+            }
+            byte[] encoded = key.getEncoded();
+            // remove 22-byte algorithm ID and header
+            byte[] value = new byte[encoded.length - 22];
+            System.arraycopy(encoded, 22, value, 0, value.length);
+            MessageDigest sha;
+            try {
+                sha = MessageDigest.getInstance("SHA-1");
+            } catch (NoSuchAlgorithmException ex) {
+                throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_SECURITY_TOKEN, "noSKIHandling",
+                    new Object[]{"Wrong certificate version (<3) and no SHA1 message digest availabe"},
+                    ex
+                );
+            }
+            sha.reset();
+            sha.update(value);
+            return sha.digest();
+        }
+
+        /**
+         * Strip away first four bytes from the DerValue (tag and length of
+         * ExtensionValue OCTET STRING and KeyIdentifier OCTET STRING)
+         */
+        byte abyte0[] = new byte[derEncodedValue.length - 4];
+
+        System.arraycopy(derEncodedValue, 4, abyte0, 0, abyte0.length);
+        return abyte0;
+    }
+
+    public KeyStore getKeyStore() {
+        return this.keystore;
+    }
+    /**
+     * Lookup X509 Certificates in the keystore according to a given DN of the subject of the certificate
+     * <p/>
+     * The search gets all alias names of the keystore and gets the certificate (chain)
+     * for each alias. Then the DN of the certificate is compared with the parameters.
+     *
+     * @param subjectDN The DN of subject to look for in the keystore
+     * @return Vector with all alias of certificates with the same DN as given in the parameters
+     * @throws org.apache.ws.security.WSSecurityException
+     *
+     */
+    public String[] getAliasesForDN(String subjectDN) throws WSSecurityException {
+
+        // The DN to search the keystore for
+        Vector subjectRDN = splitAndTrim(subjectDN);
+        Vector aliases = getAlias(subjectRDN, keystore);
+        
+        //If we can't find the issuer in the keystore then look at cacerts
+        if(aliases.size() == 0) {
+            aliases = getAlias(subjectRDN, cacerts);
+        }
+        
+        // Convert the vector into an array
+        String[] result = new String[aliases.size()];
+        for (int i = 0; i < aliases.size(); i++)
+            result[i] = (String) aliases.elementAt(i);
+
+        return result;
+    }
+    
+    /**
+     * get a byte array given an array of X509 certificates.
+     * <p/>
+     *
+     * @param reverse If set the first certificate in the array data will
+     *                the last in the byte array
+     * @param certs   The certificates to convert
+     * @return The byte array for the certificates ordered according
+     *         to the reverse flag
+     * @throws WSSecurityException
+     */
+    public byte[] getCertificateData(boolean reverse, X509Certificate[] certs)
+            throws WSSecurityException {
+        Vector list = new Vector();
+        for (int i = 0; i < certs.length; i++) {
+            if (reverse) {
+                list.insertElementAt(certs[i], 0);
+            } else {
+                list.add(certs[i]);
+            }
+        }
+        try {
+            CertPath path = getCertificateFactory().generateCertPath(list);
+            return path.getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError",
+                null, e
+            );
+        } catch (CertificateException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "parseError",
+                null, e
+            );
+        }
+    }
+
+    /**
+     * Construct an array of X509Certificate's from the byte array.
+     * <p/>
+     *
+     * @param data    The <code>byte</code> array containing the X509 data
+     * @param reverse If set the first certificate in input data will
+     *                the last in the array
+     * @return An array of X509 certificates, ordered according to
+     *         the reverse flag
+     * @throws WSSecurityException
+     */
+    public X509Certificate[] getX509Certificates(byte[] data, boolean reverse)
+            throws WSSecurityException {
+        InputStream in = new ByteArrayInputStream(data);
+        CertPath path = null;
+        try {
+            path = getCertificateFactory().generateCertPath(in);
+        } catch (CertificateException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "parseError",
+                null, e
+            );
+        }
+        List l = path.getCertificates();
+        X509Certificate[] certs = new X509Certificate[l.size()];
+        Iterator iterator = l.iterator();
+        for (int i = 0; i < l.size(); i++) {
+            certs[(reverse) ? (l.size() - 1 - i) : i] = (X509Certificate) iterator.next();
+        }
+        return certs;
+    }
+
+    /**
+     * Overridden because there's a bug in the base class where they don't use
+     * the provider variant for the certificate validator.
+     *
+     * @param certs
+     *            Certificate chain to validate
+     * @return true if the certificate chain is valid, false otherwise
+     * @throws WSSecurityException
+     */
+    public boolean
+    validateCertPath(
+        java.security.cert.X509Certificate[] certs
+    )
+        throws org.apache.ws.security.WSSecurityException {
+
+        try {
+            // Generate cert path
+            java.util.List cert_list = java.util.Arrays.asList(certs);
+            java.security.cert.CertPath path =
+                getCertificateFactory().generateCertPath(cert_list);
+
+            // Use the certificates in the keystore as TrustAnchors
+            java.security.cert.PKIXParameters param =
+                new java.security.cert.PKIXParameters(this.keystore);
+
+            // Do not check a revocation list
+            param.setRevocationEnabled(false);
+
+            // Verify the trust path using the above settings
+            String provider = getCryptoProvider();
+            java.security.cert.CertPathValidator validator = null;
+            if (provider == null || provider.length() == 0) {
+                validator =
+                    java.security.cert.CertPathValidator.getInstance("PKIX");
+            } else {
+                validator =
+                    java.security.cert.CertPathValidator.getInstance(
+                        "PKIX",
+                        provider
+                    );
+            }
+            validator.validate(path, param);
+        } catch (java.security.NoSuchProviderException e) {
+                throw new org.apache.ws.security.WSSecurityException(
+                    org.apache.ws.security.WSSecurityException.FAILURE,
+                    "certpath",
+                    new Object[] { e.getMessage() },
+                    e
+                );
+        } catch (java.security.NoSuchAlgorithmException e) {
+                throw new org.apache.ws.security.WSSecurityException(
+                    org.apache.ws.security.WSSecurityException.FAILURE,
+                    "certpath", new Object[] { e.getMessage() },
+                    e
+                );
+        } catch (java.security.cert.CertificateException e) {
+                throw new org.apache.ws.security.WSSecurityException(
+                    org.apache.ws.security.WSSecurityException.FAILURE,
+                    "certpath", new Object[] { e.getMessage() },
+                    e
+                );
+        } catch (java.security.InvalidAlgorithmParameterException e) {
+                throw new org.apache.ws.security.WSSecurityException(
+                    org.apache.ws.security.WSSecurityException.FAILURE,
+                    "certpath",
+                    new Object[] { e.getMessage() },
+                    e
+                );
+        } catch (java.security.cert.CertPathValidatorException e) {
+                throw new org.apache.ws.security.WSSecurityException(
+                    org.apache.ws.security.WSSecurityException.FAILURE,
+                    "certpath",
+                    new Object[] { e.getMessage() },
+                    e
+                );
+        } catch (java.security.KeyStoreException e) {
+                throw new org.apache.ws.security.WSSecurityException(
+                    org.apache.ws.security.WSSecurityException.FAILURE,
+                    "certpath",
+                    new Object[] { e.getMessage() },
+                    e
+                );
+        }
+
+        return true;
+    }
+    
+    private Vector getAlias(Vector subjectRDN, KeyStore store) throws WSSecurityException {
+        // Store the aliases found
+        Vector aliases = new Vector();
+
+        Certificate cert = null;
+        
+        try {
+            for (Enumeration e = store.aliases(); e.hasMoreElements();) {
+                String alias = (String) e.nextElement();
+
+                Certificate[] certs = store.getCertificateChain(alias);
+                if (certs == null || certs.length == 0) {
+                    // no cert chain, so lets check if getCertificate gives us a  result.
+                    cert = store.getCertificate(alias);
+                    if (cert == null) {
+                        return null;
+                    }
+                    certs = new Certificate[]{cert};
+                } else {
+                    cert = certs[0];
+                }
+                if (cert instanceof X509Certificate) {
+                    Vector foundRDN = splitAndTrim(((X509Certificate) cert).getSubjectDN().getName());
+
+                    if (subjectRDN.equals(foundRDN)) {
+                        aliases.add(alias);
+                    }
+                }
+            }
+        } catch (KeyStoreException e) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILURE, "keystore", null, e
+            );
+        }
+        return aliases;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/components/crypto/CryptoFactory.java b/trunk/src/org/apache/ws/security/components/crypto/CryptoFactory.java
new file mode 100644
index 0000000..23b8a82
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/components/crypto/CryptoFactory.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.components.crypto;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.util.Loader;
+
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * CryptoFactory.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public abstract class CryptoFactory {
+    private static final Log log = LogFactory.getLog(CryptoFactory.class);
+    private static final String defaultCryptoClassName = "org.apache.ws.security.components.crypto.Merlin";
+
+    /**
+     * getInstance
+     * <p/>
+     * Returns an instance of Crypto. This method uses the file
+     * <code>crypto.properties</code> to determine which implementation to
+     * use. Thus the property <code>org.apache.ws.security.crypto.provider</code>
+     * must define the classname of the Crypto implementation. The file
+     * may contain other property definitions as well. These properties are
+     * handed over to the  Crypto implementation. The file
+     * <code>crypto.properties</code> is loaded with the
+     * <code>Loader.getResource()</code> method.
+     * <p/>
+     *
+     * @return The crypto implementation was defined
+     */
+    public static Crypto getInstance() {
+        return getInstance("crypto.properties");
+    }
+
+    /**
+     * getInstance
+     * <p/>
+     * Returns an instance of Crypto. The properties are handed over the the crypto
+     * implementation. The properties must at least contain the Crypto implementation
+     * class name as the value of the property : org.apache.ws.security.crypto.provider
+     * <p/>
+     *
+     * @param properties      The Properties that are forwarded to the crypto implementation 
+     *                        and the Crypto impl class name.
+     *                        These properties are dependent on the crypto implementation
+     * @return The cyrpto implementation or null if no cryptoClassName was defined
+     */
+    public static Crypto getInstance(Properties properties) {
+        String cryptoClassName = properties.getProperty("org.apache.ws.security.crypto.provider");
+        return loadClass(cryptoClassName, properties);
+    }
+
+    /**
+     * getInstance
+     * <p/>
+     * Returns an instance of Crypto loaded with the given classloader. 
+     * The properties are handed over the the crypto implementation. 
+     * The properties must at least contain the Crypto implementation
+     * class name as the value of the property : org.apache.ws.security.crypto.provider
+     * <p/>
+     *
+     * @param properties      The Properties that are forwarded to the crypto implementation 
+     *                        and the Crypto impl class name.
+     *                        These properties are dependent on the crypto implementation
+     * @param classLoader   The class loader to use
+     * @return The crypto implementation or null if no cryptoClassName was defined
+     */
+    public static Crypto getInstance(Properties properties, ClassLoader classLoader) {
+        String cryptoClassName = properties.getProperty("org.apache.ws.security.crypto.provider");
+        return loadClass(cryptoClassName, properties, classLoader);
+    }
+    
+    /**
+     * getInstance
+     * <p/>
+     * Returns an instance of Crypto. The properties are handed over the the crypto
+     * implementation. The properties can be <code>null</code>. It is dependent on the
+     * Crypto implementation how the initialization is done in this case.
+     * <p/>
+     *
+     * @param cryptoClassName This is the crypto implementation class. No default is
+     *                        provided here.
+     * @param properties      The Properties that are forwarded to the crypto implementation.
+     *                        These properties are dependent on the crypto implementation
+     * @return The crypto implementation or null if no cryptoClassName was defined
+     *
+     * @deprecated            use @link{#getInstance(java.lang.String, java.util.Map)} instead.
+     */
+    public static Crypto getInstance(String cryptoClassName, Properties properties) {
+        return loadClass(cryptoClassName, properties);
+    }
+    
+    /**
+     * getInstance
+     * <p/>
+     * Returns an instance of Crypto. The supplied map is handed over the the crypto
+     * implementation. The map can be <code>null</code>. It is dependent on the
+     * Crypto implementation how the initialization is done in this case.
+     * <p/>
+     *
+     * @param cryptoClassName This is the crypto implementation class. No default is
+     *                        provided here.
+     * @param map             The Maps that is forwarded to the crypto implementation.
+     *                        These contents of the map are dependent on the 
+     *                        underlying crypto implementation specified in the 
+     *                        cryptoClassName parameter.
+     * @return The crypto implementation or null if no cryptoClassName was defined
+     */
+    public static Crypto getInstance(String cryptoClassName, Map map) {
+        return loadClass(cryptoClassName, map);
+    }
+
+    /**
+     * getInstance
+     * <p/>
+     * Returns an instance of Crypto. This method uses the specified filename
+     * to load a property file. This file shall use the property
+     * <code>org.apache.ws.security.crypto.provider</code>
+     * to define the classname of the Crypto implementation. The file
+     * may contain other property definitions as well. These properties are
+     * handed over to the Crypto implementation. The specified file
+     * is loaded with the <code>Loader.getResource()</code> method.
+     * <p/>
+     *
+     * @param propFilename The name of the property file to load
+     * @return The crypto implementation that was defined
+     */
+    public static Crypto getInstance(String propFilename) {
+        Properties properties = null;
+        String cryptoClassName = null;
+
+        // cryptoClassName = System.getProperty("org.apache.ws.security.crypto.provider");
+        if ((cryptoClassName == null) || (cryptoClassName.length() == 0)) {
+            properties = getProperties(propFilename);
+            // use the default Crypto implementation
+            cryptoClassName = properties.getProperty("org.apache.ws.security.crypto.provider",
+                    defaultCryptoClassName);
+        }
+        return loadClass(cryptoClassName, properties);
+    }    
+    
+    public static Crypto getInstance(String propFilename, ClassLoader customClassLoader) {
+        Properties properties = null;
+        String cryptoClassName = null;
+
+        // cryptoClassName = System.getProperty("org.apache.ws.security.crypto.provider");
+        if ((cryptoClassName == null) || (cryptoClassName.length() == 0)) {
+            properties = getProperties(propFilename,customClassLoader);
+            // use the default Crypto implementation
+            cryptoClassName = properties.getProperty("org.apache.ws.security.crypto.provider",
+                    defaultCryptoClassName);
+        }
+        return loadClass(cryptoClassName, properties,customClassLoader);
+    }
+
+    private static Crypto loadClass(String cryptoClassName, Map map) {
+        return loadClass(cryptoClassName,map,CryptoFactory.class.getClassLoader());
+    }
+
+    /**
+     * This allows loading the classes with a custom class loader  
+     * @param cryptoClassName
+     * @param properties
+     * @param loader
+     * @return
+     */
+    private static Crypto loadClass(String cryptoClassName, Map map, ClassLoader loader) {
+        Class cryptogenClass = null;
+        Crypto crypto = null;
+        try {
+            // instruct the class loader to load the crypto implementation
+            cryptogenClass = Loader.loadClass(loader, cryptoClassName);
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(cryptoClassName + " Not Found");
+        }
+        log.debug("Using Crypto Engine [" + cryptoClassName + "]");
+        try {
+            Class[] classes = null;
+            //
+            // for backwards compat
+            //
+            if (map instanceof Properties) {
+                classes = new Class[]{Properties.class,ClassLoader.class};
+            } else {
+                classes = new Class[]{Map.class,ClassLoader.class};
+            }
+            Constructor c = cryptogenClass.getConstructor(classes);
+            crypto = (Crypto) c.newInstance(new Object[]{map,loader});
+            return crypto;
+        } catch (java.lang.Exception e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unable to instantiate (1): " + cryptoClassName, e);
+            }
+        }
+        try {
+            // try to instantiate the Crypto subclass
+            crypto = (Crypto) cryptogenClass.newInstance();
+            return crypto;
+        } catch (java.lang.Exception e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unable to instantiate (2): " + cryptoClassName, e);
+            }
+            throw new RuntimeException(cryptoClassName + " cannot create instance", e);
+        }
+    }
+    /**
+     * Gets the properties for crypto.
+     * The functions loads the property file via
+     * {@link Loader.getResource(String)}, thus the property file
+     * should be accessible via the classpath
+     *
+     * @param propFilename the properties file to load
+     * @return a <code>Properties</code> object loaded from the filename
+     */
+    private static Properties getProperties(String propFilename) {
+        return getProperties(propFilename, CryptoFactory.class.getClassLoader());
+    }
+    
+    
+    /**
+     * This allows loading the resources with a custom class loader
+     * @param propFilename
+     * @param loader
+     * @return
+     */
+    private static Properties getProperties(String propFilename, ClassLoader loader) {
+        Properties properties = new Properties();
+        try {
+            URL url = Loader.getResource(loader, propFilename);
+            properties.load(url.openStream());
+        } catch (Exception e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Cannot find crypto property file: " + propFilename, e);
+            }
+            throw new RuntimeException("CryptoFactory: Cannot load properties: " +
+                    propFilename, e);
+        }
+        return properties;
+    }
+
+}
+
diff --git a/trunk/src/org/apache/ws/security/components/crypto/Merlin.java b/trunk/src/org/apache/ws/security/components/crypto/Merlin.java
new file mode 100644
index 0000000..58f209b
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/components/crypto/Merlin.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.components.crypto;
+
+import org.apache.ws.security.WSSecurityException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * JDK1.4 based implementation of Crypto (uses keystore). <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class Merlin extends AbstractCrypto {
+   /**
+    * OID For the NameConstraints Extension to X.509
+    *
+    * http://java.sun.com/j2se/1.4.2/docs/api/
+    * http://www.ietf.org/rfc/rfc3280.txt (s. 4.2.1.11)
+    */
+    public static final String NAME_CONSTRAINTS_OID = "2.5.29.30";
+
+    /**
+     * Constructor. <p/>
+     * 
+     * @param properties
+     * @throws CredentialException
+     * @throws IOException
+     */
+    public Merlin(Properties properties) throws CredentialException,
+            IOException {
+        super(properties);
+    }
+
+    public Merlin(Properties properties, ClassLoader loader)
+            throws CredentialException, IOException {
+        super(properties, loader);
+    }
+
+    /**
+     * Construct an array of X509Certificate's from the byte array. <p/>
+     * 
+     * @param data
+     *            The <code>byte</code> array containing the X509 data
+     * @param reverse
+     *            If set the first certificate in input data will the last in
+     *            the array
+     * @return An array of X509 certificates, ordered according to the reverse
+     *         flag
+     * @throws WSSecurityException
+     */
+    public X509Certificate[] getX509Certificates(byte[] data, boolean reverse)
+            throws WSSecurityException {
+        InputStream in = new ByteArrayInputStream(data);
+        CertPath path = null;
+        try {
+            path = getCertificateFactory().generateCertPath(in);
+        } catch (CertificateException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "parseError", null, e
+            );
+        }
+        List l = path.getCertificates();
+        X509Certificate[] certs = new X509Certificate[l.size()];
+        Iterator iterator = l.iterator();
+        for (int i = 0; i < l.size(); i++) {
+            certs[(reverse) ? (l.size() - 1 - i) : i] = (X509Certificate) iterator
+                    .next();
+        }
+        return certs;
+    }
+
+    /**
+     * get a byte array given an array of X509 certificates. <p/>
+     * 
+     * @param reverse
+     *            If set the first certificate in the array data will the last
+     *            in the byte array
+     * @param certs
+     *            The certificates to convert
+     * @return The byte array for the certificates ordered according to the
+     *         reverse flag
+     * @throws WSSecurityException
+     */
+    public byte[] getCertificateData(boolean reverse, X509Certificate[] certs)
+            throws WSSecurityException {
+        Vector list = new Vector();
+        for (int i = 0; i < certs.length; i++) {
+            if (reverse) {
+                list.insertElementAt(certs[i], 0);
+            } else {
+                list.add(certs[i]);
+            }
+        }
+        try {
+            CertPath path = getCertificateFactory().generateCertPath(list);
+            return path.getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError", null, e
+            );
+        } catch (CertificateException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "parseError", null, e
+            );
+        }
+    }
+
+    public boolean validateCertPath(X509Certificate[] certs)
+            throws WSSecurityException {
+        try {
+            // Generate cert path
+            java.util.List certList = java.util.Arrays.asList(certs);
+            CertPath path = this.getCertificateFactory().generateCertPath(
+                    certList);
+
+            HashSet set = new HashSet();
+
+            Enumeration cacertsAliases = this.cacerts.aliases();
+            while (cacertsAliases.hasMoreElements()) {
+                String alias = (String) cacertsAliases.nextElement();
+                X509Certificate cert = (X509Certificate) this.cacerts
+                        .getCertificate(alias);
+                TrustAnchor anchor = new TrustAnchor(cert, cert
+                        .getExtensionValue(NAME_CONSTRAINTS_OID));
+                set.add(anchor);
+            }
+
+            // Add certificates from the keystore
+            Enumeration aliases = this.keystore.aliases();
+            while (aliases.hasMoreElements()) {
+                String alias = (String) aliases.nextElement();
+                X509Certificate cert = (X509Certificate) this.keystore
+                        .getCertificate(alias);
+                TrustAnchor anchor = new TrustAnchor(cert, cert
+                        .getExtensionValue(NAME_CONSTRAINTS_OID));
+                set.add(anchor);
+            }
+
+            PKIXParameters param = new PKIXParameters(set);
+
+            // Do not check a revocation list
+            param.setRevocationEnabled(false);
+
+            // Verify the trust path using the above settings
+            String provider = properties
+                    .getProperty("org.apache.ws.security.crypto.merlin.cert.provider");
+            CertPathValidator certPathValidator;
+            if (provider == null || provider.length() == 0) {
+                certPathValidator = CertPathValidator.getInstance("PKIX");
+            } else {
+                certPathValidator = CertPathValidator.getInstance("PKIX",
+                        provider);
+            }
+            certPathValidator.validate(path, param);
+        } catch (NoSuchProviderException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath", new Object[] { ex.getMessage() },
+                    (Throwable) ex);
+        } catch (NoSuchAlgorithmException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath", new Object[] { ex.getMessage() },
+                    (Throwable) ex);
+        } catch (CertificateException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath", new Object[] { ex.getMessage() },
+                    (Throwable) ex);
+        } catch (InvalidAlgorithmParameterException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath", new Object[] { ex.getMessage() },
+                    (Throwable) ex);
+        } catch (CertPathValidatorException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath", new Object[] { ex.getMessage() },
+                    (Throwable) ex);
+        } catch (KeyStoreException ex) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "certpath", new Object[] { ex.getMessage() },
+                    (Throwable) ex);
+        }
+
+        return true;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/components/crypto/X509NameTokenizer.java b/trunk/src/org/apache/ws/security/components/crypto/X509NameTokenizer.java
new file mode 100644
index 0000000..fae58a1
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/components/crypto/X509NameTokenizer.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.components.crypto;
+
+import java.util.ArrayList;
+
+import org.apache.xml.security.utils.RFC2253Parser;
+
+/**
+ * class for breaking up an X500 Name into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ */
+public class X509NameTokenizer {
+
+    private final java.util.List tokens = new ArrayList();
+    private int index = 0;
+
+    public X509NameTokenizer(String dn) {
+       final String _DN = RFC2253Parser.normalize(dn);
+       int i = 0;
+       int l = 0;
+       int k;
+       for (int j = 0; (k = _DN.indexOf(",", j)) >= 0; j = k + 1) {
+          l += countQuotes(_DN, j, k);
+          if ((k > 0) && (_DN.charAt(k - 1) != '\\') && (l % 2) == 0) {
+             tokens.add(_DN.substring(i, k).trim());
+             i = k + 1;
+             l = 0;
+          }
+       }
+       if (_DN.trim().length() != 0) {
+           tokens.add(trim(_DN.substring(i)));
+       }
+    }
+
+    public boolean hasMoreTokens() {
+        return (index < tokens.size());
+    }
+
+    public String nextToken() {
+        if (hasMoreTokens()) {
+            return (String) tokens.get(index++);
+        } else {
+            return "";
+        }
+    }
+
+
+    /**
+     * Returns the number of Quotation from i to j
+     *
+     * @param s
+     * @param i
+     * @param j
+     * @return number of quotes
+     */
+    private static int countQuotes(String s, int i, int j) {
+       int k = 0;
+       for (int l = i; l < j; l++) {
+          if (s.charAt(l) == '"') {
+             k++;
+          }
+       }
+       return k;
+    }
+
+    /**
+     * Method trim
+     *
+     * @param str
+     * @return the string
+     */
+    private static String trim(String str) {
+       String trimed = str.trim();
+       int i = str.indexOf(trimed) + trimed.length();
+       if ((str.length() > i) 
+           && trimed.endsWith("\\")
+           && !trimed.endsWith("\\\\")
+           && (str.charAt(i) == ' ')) {
+         trimed = trimed + " ";
+       }
+       return trimed;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/components/crypto/errors.properties b/trunk/src/org/apache/ws/security/components/crypto/errors.properties
new file mode 100644
index 0000000..4c475e5
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/components/crypto/errors.properties
@@ -0,0 +1,20 @@
+## defines error code - str message mapping
+0 = General security error
+1 = An unsupported token was provided
+2 = An unsupported signature or encryption algorithm was used
+3 = An error was discovered processing the <wsse:Security> header.
+4 = An invalid security token was provided
+5 = The security token could not be authenticated or authorized
+6 = The signature or decryption was invalid
+7 = Referenced security token could not be retrieved.
+
+proxyNotFound = Proxy file ({0}) not found.
+ioError00 = Failed to load credentials.
+secError00 = Failed to load credentials.
+error00 = Failed to load credentials.
+noCerts00 = No certificates loaded
+noKey00 = No private key loaded
+noSKIHandling = Problem with SKI information: {0}
+badBase64Data = Unable to decode Base64 encoded data
+badEncoding = Problem with Encoding: {0}
+noSHA1availabe = Crypto provider does not suppor1 SHA-1 digest
diff --git a/trunk/src/org/apache/ws/security/conversation/ConversationConstants.java b/trunk/src/org/apache/ws/security/conversation/ConversationConstants.java
new file mode 100755
index 0000000..390c714
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/conversation/ConversationConstants.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.conversation;
+
+/**
+ * Class ConversationConstants
+ */
+public class ConversationConstants {
+
+    public final static int VERSION_05_02 = 1;
+    
+    public final static int VERSION_05_12 = 2;
+    
+    public final static int DEFAULT_VERSION = VERSION_05_02; 
+    
+    /**
+     * WS-SecConv Feb 2005 version
+     */
+    public final static String WSC_NS_05_02 = "http://schemas.xmlsoap.org/ws/2005/02/sc"; 
+    
+    /**
+     * WS-Sx version
+     */
+    public final static String WSC_NS_05_12 = "http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512";
+    
+    /**
+     * Token type of DerivedKeyToken
+     */
+    public final static String TOKEN_TYPE_DERIVED_KEY_TOKEN =  "/dk";
+    
+    /**
+     * Token type of SecurityContextToken
+     */
+    public static final String TOKEN_TYPE_SECURITY_CONTEXT_TOKEN = "/sct";
+    
+    /**
+     * Field WSC_PREFIX
+     */
+    public final static String WSC_PREFIX = "wsc";
+
+    /**
+     * Field SECURITY_CONTEXT_TOKEN_LN
+     */
+    public static final String SECURITY_CONTEXT_TOKEN_LN =
+            "SecurityContextToken";
+
+    /**
+     * Field IDENTIFIER_LN
+     */
+    public static final String IDENTIFIER_LN = "Identifier";
+
+    /**
+     * Field EXPIRES_LN
+     */
+    public static final String EXPIRES_LN = "Expires";
+
+    /**
+     * Field KEYS_LN
+     */
+    public static final String KEYS_LN = "Keys";
+
+    /**
+     * Field SECURITY_TOKEN_REFERENCE_LN
+     */
+    public static final String SECURITY_TOKEN_REFERENCE_LN =
+            "SecurityTokenReference";
+
+    /**
+     * Field DERIVED_KEY_TOKEN_LN
+     */
+    public static final String DERIVED_KEY_TOKEN_LN = "DerivedKeyToken";
+
+    /**
+     * Field PROPERTIES_LN
+     */
+    public static final String PROPERTIES_LN = "Properties";
+
+    /**
+     * Field LENGTH_LN
+     */
+    public static final String LENGTH_LN = "Length";
+
+    /**
+     * Field GENERATION_LN
+     */
+    public static final String GENERATION_LN = "Generation";
+
+    /**
+     * Field OFFSET_LN
+     */
+    public static final String OFFSET_LN = "Offset";
+
+    /**
+     * Field LABEL_LN
+     */
+    public static final String LABEL_LN = "Label";
+
+    /**
+     * Field NONCE_LN
+     */
+    public static final String NONCE_LN = "Nonce";
+
+    public static final int DIRECT_GENERATED = 1;
+    public static final int STS_GENERATED = 2;
+    public static final int STSREQUEST_TOKEN = 3;
+    public static final int INTEROP_SCENE1 = 4;
+
+    public static final String IDENTIFIER = "SCT_Identifier";
+
+    public static final int DK_SIGN = 1;
+    public static final int DK_ENCRYPT = 2;
+    
+    public final static String DEFAULT_LABEL = "WS-SecureConversation";
+    
+    /**
+     * Key to hold the map of security context identifiers against the 
+     * service epr addresses (service scope) or wsa:Action values (operation 
+     * scope).
+     */
+    public final static String KEY_CONTEXT_MAP = "contextMap";
+    
+    public interface DerivationAlgorithm {
+        public final static String P_SHA_1 = "http://schemas.xmlsoap.org/ws/2005/02/sc/dk/p_sha1";
+    }
+    
+    public static String getWSCNs(int version) throws ConversationException {
+        if(VERSION_05_02 == version) {
+            return WSC_NS_05_02;
+        } else if(VERSION_05_12 == version) {
+            return WSC_NS_05_12;
+        } else {
+            throw new ConversationException("unsupportedSecConvVersion");
+        }
+    }
+    
+    public static int getWSTVersion(String ns) throws ConversationException {
+        if(WSC_NS_05_02.equals(ns)) {
+            return VERSION_05_02;
+        } else if(WSC_NS_05_12.equals(ns)) {
+            return VERSION_05_12;
+        } else {
+            throw new ConversationException("unsupportedSecConvVersion");
+        }
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/conversation/ConversationException.java b/trunk/src/org/apache/ws/security/conversation/ConversationException.java
new file mode 100755
index 0000000..de0adcc
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/conversation/ConversationException.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.conversation;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class ConversationException extends Exception {
+    
+    private static final long serialVersionUID = 970894530660804319L;
+    
+    public final static String BAD_CONTEXT_TOKEN = "BadContextToken";
+    public final static String UNSUPPORTED_CONTEXT_TOKEN = "UnsupportedContextToken";
+    public final static String UNKNOWN_DERIVATION_SOURCE = "UnknownDerivationSource";
+    public final static String RENEW_NEEDED = "RenewNeeded";
+    public final static String UNABLE_TO_REVIEW = "UnableToRenew";
+    
+    private static ResourceBundle resources;
+
+    private String faultCode;
+    private String faultString;
+    
+    static {
+        try {
+            resources = ResourceBundle.getBundle("org.apache.ws.security.conversation.errors");
+        } catch (MissingResourceException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+    
+    public ConversationException(String faultCode, Object[] args) {
+        super(getMessage(faultCode, args));
+        this.faultCode = getFaultCode(faultCode);
+        this.faultString = getMessage(faultCode, args);
+    }
+    
+    /**
+     * Construct the fault properly code for the standard faults
+     * @param faultCode2
+     * @return
+     */
+    private String getFaultCode(String code) {
+        if(BAD_CONTEXT_TOKEN.equals(code) ||
+           UNABLE_TO_REVIEW.equals(code) ||
+           UNKNOWN_DERIVATION_SOURCE.equals(code) ||
+           UNSUPPORTED_CONTEXT_TOKEN.equals(code) ||
+           RENEW_NEEDED.equals(code)) {
+            return ConversationConstants.WSC_PREFIX+ ":" + code;
+        } else {
+            return code;
+        }
+    }
+
+    public ConversationException(String faultCode) {
+        this(faultCode, (Object[])null);
+    }
+    
+    public ConversationException(String faultCode, Object[] args, Throwable e) {
+        super(getMessage(faultCode, args),e);
+        this.faultCode = faultCode;
+        this.faultString = getMessage(faultCode, args);
+    }
+    
+    public ConversationException(String faultCode, Throwable e) {
+        this(faultCode, null, e);
+    }
+
+    /**
+     * get the message from resource bundle.
+     * <p/>
+     *
+     * @return the message translated from the property (message) file.
+     */
+    protected static String getMessage(String faultCode, Object[] args) {
+        String msg = null;
+        try {
+            msg = MessageFormat.format(resources.getString(faultCode), args);
+        } catch (MissingResourceException e) {
+            throw new RuntimeException("Undefined '" + faultCode + "' resource property", e);
+        }
+        if(msg != null) {
+            return msg;
+        } else {
+            return faultCode;
+        }
+    }
+
+    /**
+     * @return Returns the faultCode.
+     */
+    protected String getFaultCode() {
+        return faultCode;
+    }
+
+    /**
+     * @return Returns the faultString.
+     */
+    protected String getFaultString() {
+        return faultString;
+    }
+    
+
+}
diff --git a/trunk/src/org/apache/ws/security/conversation/dkalgo/AlgoFactory.java b/trunk/src/org/apache/ws/security/conversation/dkalgo/AlgoFactory.java
new file mode 100755
index 0000000..0d7af03
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/conversation/dkalgo/AlgoFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.conversation.dkalgo;
+
+import org.apache.ws.security.conversation.ConversationConstants;
+import org.apache.ws.security.conversation.ConversationException;
+
+/**
+ * @author Ruchith Fernando
+ */
+
+public class AlgoFactory {
+
+    /**
+     * This gives a DerivationAlgorithm instance from the default set of algorithms provided
+     *
+     * @param algorithm The algo identifier @see DeivationAlgorithm
+     * @return A derivation algorithm
+     * @throws ConversationException If the specified algorithm is not available
+     *                               in default implementations
+     */
+    public static DerivationAlgorithm getInstance(String algorithm) throws
+            ConversationException {
+        if (algorithm.equals(ConversationConstants.DerivationAlgorithm.P_SHA_1)) {
+            return new P_SHA1();
+        } else {
+            throw new ConversationException("No such algorithm");
+        }
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/conversation/dkalgo/DerivationAlgorithm.java b/trunk/src/org/apache/ws/security/conversation/dkalgo/DerivationAlgorithm.java
new file mode 100755
index 0000000..0153117
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/conversation/dkalgo/DerivationAlgorithm.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.conversation.dkalgo;
+
+import org.apache.ws.security.conversation.ConversationException;
+
+/**
+ *
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public interface DerivationAlgorithm {
+
+    public byte[] createKey(byte[] secret, byte[] seed, int offset,
+            long length) throws ConversationException;
+}
diff --git a/trunk/src/org/apache/ws/security/conversation/dkalgo/P_SHA1.java b/trunk/src/org/apache/ws/security/conversation/dkalgo/P_SHA1.java
new file mode 100755
index 0000000..3ffe631
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/conversation/dkalgo/P_SHA1.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.conversation.dkalgo;
+
+/**
+ *
+ <pre>
+ P_SHA-1 DEFINITION
+ ==================
+ <b>P_SHA-1(secret, seed)</b> =
+ HMAC_SHA-1(secret, A(1) + seed) +
+ HMAC_SHA-1(secret, A(2) + seed) +
+ HMAC_SHA-1(secret, A(3) + seed) + ...
+ <i>Where + indicates concatenation.</i>
+ <br>
+ A() is defined as:
+ A(0) = seed
+ A(i) = HMAC_SHA-1(secret, A(i-1))
+ <br>
+ <i>Source : RFC 2246 - The TLS Protocol Version 1.0
+ Section 5. HMAC and the pseudorandom function</i>
+ </pre>
+ *
+ * @author Ruchith Fernando
+ */
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.ws.security.conversation.ConversationException;
+
+public class P_SHA1
+        implements DerivationAlgorithm {
+
+    public byte[] createKey(byte[] secret, byte[] seed, int offset,
+            long length) throws ConversationException {
+        try {
+            Mac mac = Mac.getInstance("HmacSHA1");
+
+            byte[] tempBytes = P_hash(secret, seed, mac,
+                    (offset + (int) length));
+
+            byte[] key = new byte[(int) length];
+
+            for (int i = 0; i < key.length; i++)
+                key[i] = tempBytes[i + offset];
+
+            return key;
+        } catch (Exception ex) {
+            throw new ConversationException("errorInKeyDerivation", null, ex);
+        }
+    }
+    
+    /**
+     * From WSUsernameToken  :-)
+     *
+     * @param secret
+     * @param seed
+     * @param mac
+     * @param required
+     * @return
+     * @throws java.lang.Exception
+     */
+    private static byte[] P_hash(byte[] secret, byte[] seed, Mac mac,
+                                 int required) throws Exception {
+        byte[] out = new byte[required];
+        int offset = 0, tocpy;
+        byte[] A, tmp;
+        A = seed;
+        while (required > 0) {
+            SecretKeySpec key = new SecretKeySpec(secret, "HMACSHA1");
+            mac.init(key);
+            mac.update(A);
+            A = mac.doFinal();
+            mac.reset();
+            mac.init(key);
+            mac.update(A);
+            mac.update(seed);
+            tmp = mac.doFinal();
+            tocpy = min(required, tmp.length);
+            System.arraycopy(tmp, 0, out, offset, tocpy);
+            offset += tocpy;
+            required -= tocpy;
+        }
+        return out;
+    }
+
+    private static int min(int a, int b) {
+        return (a > b) ? b : a;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/conversation/errors.properties b/trunk/src/org/apache/ws/security/conversation/errors.properties
new file mode 100644
index 0000000..619f23f
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/conversation/errors.properties
@@ -0,0 +1,9 @@
+BadContextToken = The requested context elements are insufficient or unsupported
+UnsupportedContextToken = Not all of the values associated with the SCT are supported
+UnknownDerivationSource = The specified source for the derivation is unknown
+RenewNeeded = The provided context token has expired
+UnableToRenew = The specified context token could not be renewed.
+
+
+errorInKeyDerivation = Error in key derivation
+unsupportedSecConvVersion = Unsupported WS-SecureConversation version
\ No newline at end of file
diff --git a/trunk/src/org/apache/ws/security/errors.properties b/trunk/src/org/apache/ws/security/errors.properties
new file mode 100644
index 0000000..997fd68
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/errors.properties
@@ -0,0 +1,87 @@
+## defines error code - str message mapping
+0 = General security error
+1 = An unsupported token was provided
+2 = An unsupported signature or encryption algorithm was used
+3 = An error was discovered processing the <wsse:Security> header
+4 = An invalid security token was provided
+5 = The security token could not be authenticated or authorized
+6 = The signature or decryption was invalid
+7 = Referenced security token could not be retrieved
+8 = The message has expired
+9 = Cannot encrypt data
+10 = Signature creation failed
+
+## detailed error msgs
+noToken = Reference \"{0}\"
+noReference = <Reference> token could not be retrieved
+badReferenceURI = Reference URI is null
+unhandledToken = Security token supported but currently not handled \"{0}\"
+unsupportedBinaryTokenType = Token type \"{0}\"
+invalidConstructor = Token impl. class \"{0}\" does not provide appropriate constructor
+invalidValueType = Bad ValueType \"{0}\"
+unsupportedKeyInfo = Unsupported KeyInfo type
+invalidX509Data = Unexpected number of X509Data: {0}
+unknownSignatureAlgorithm = An unknown signature algorithm was specified: {0}
+noUserCertsFound = No certificates for user {0} were found for {1}
+noCertsFound = No certificates were found for {0}
+invalidCertData = Unexpected number of certificates: {0}
+noSKIHandling = Error during processing of SKI data: {0}
+invalidDataRef = Cannot handle multiple data references
+noEncryptedData = Referenced encrypted data could not be retrieved. Reference \"{0}\"
+badElement = Bad element, expected \"{0}\" while got \"{1}\"
+badTokenType00 = Bad UsernameToken Type
+badTokenType01 = Bad UsernameToken Values
+failedAuthentication = User ({0}) not authenticated
+missingUsernameToken = UsernameToken is missing
+missingSecurityHeader = Security header is missing
+missingUsername = Username is missing
+missingPassword = Password is missing
+missingPasswordType =Password attribute type is missing
+missingNonce = Nonce is missing
+missingCreated = Created time is missing
+noSecProvider = Specified security provider not available
+parseError = Cannot parse/decode the certificate data
+encodeError = Cannot encode the certificate data
+invalidCertForSKI = An X509 certificate with version 3 must be used for SKI. The presented cert has version: {0}
+unsupportedCertType = Certificate type not supported by security provider
+invalidCert = The provided certificate is invalid
+noXMLSig = Cannot setup signature data structure
+noSKIHandling = Problem with SKI information: {0}
+keystore = Cannot access/read keystore data
+noCert = No certificate provided
+##
+noSigCryptoFile=WSSecurityEngine: No crypto property file supplied to verify signature
+noDecCryptoFile=WSSecurityEngine: No crypto property file supplied for decryption
+noCallback=WSSecurityEngine: No password callback supplied
+noPassword=WSSecurityEngine: Callback supplied no password for: {0}
+noKey=WSSecurityEngine: Callback supplied no key for: {0}
+noEncAlgo=WSSecurityEngine: xenc:EncryptedKey does not contain xenc:EncryptionMethod/@Algorithm
+unsupportedKeyTransp=unsupported key transport encryption algorithm: {0}
+noCipher=WSSecurityEngine: EncryptedKey does not contain xenc:CipherData/xenc:CipherValue
+noKeyinfo=WSSecurityEngine: EncryptedKey does not contain ds:KeyInfo
+noSecTokRef=WSSecurityEngine: EncryptedKey does not contain ds:KeyInfo/wsse:SecurityTokenReference
+unsupportedKeyId=Unsupported key identification
+dataRef=WSSecurityEngine: DataReference - referenced data not found
+noKeyname=WSSecurityEngine: ds:KeyName does not contain a key name
+noEncElement=WSEncryptBody/WSSignEnvelope: Element to encrypt/sign not found: {0}
+certpath=Error during certificate path validation: {0}
+invalidTimestamp=WSSecurityEngine: Invalid timestamp {0}
+noKeySupplied=WSEncryptBody: No symmetrical encryption key supplied
+#
+noSAMLdoc=Cannot convert SAML to DOM document
+invalidSAMLsecurity=SAML token security failure
+invalidSAMLToken = Invalid SAML assertion : {0}
+invalidData=Invalid data: {0}
+noKeyInSAMLToken=Provided SAML token does not contain a suitable key
+#
+decoding.divisible.four = It should be divisible by four
+decoding.general = Error while decoding
+
+unknownAction=Unknown Action {0}
+unableToLoadClass=Unable to load class {0}
+
+requiredElementNoID=Element {0} is not signed; it does not have a wsu:Id attribute
+noSignResult=No SIGN result in WSS4J result vector
+requiredElementNotSigned=Element {0} is not included in the signature
+
+invalidKeySize=Invalid keysize
\ No newline at end of file
diff --git a/trunk/src/org/apache/ws/security/handler/RequestData.java b/trunk/src/org/apache/ws/security/handler/RequestData.java
new file mode 100644
index 0000000..ca6a2c0
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/handler/RequestData.java
@@ -0,0 +1,239 @@
+package org.apache.ws.security.handler;
+
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.WSSecHeader;
+
+import java.util.Vector;
+import java.security.cert.X509Certificate;
+
+/**
+ * This class holds per request data.
+ *
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de)
+ */
+public class RequestData {
+    private Object msgContext = null;
+    private boolean noSerialization = false;
+    private SOAPConstants soapConstants = null;
+    private String actor = null;
+    private String username = null;
+    private String pwType = WSConstants.PASSWORD_DIGEST; // Make this the default when no password type is given.
+    private String[] utElements = null;
+    private Crypto sigCrypto = null;
+    private Crypto decCrypto = null;
+    private int sigKeyId = 0;
+    private String sigAlgorithm = null;
+    private Vector signatureParts = new Vector();
+    private Crypto encCrypto = null;
+    private int encKeyId = 0;
+    private String encSymmAlgo = null;
+    private String encKeyTransport = null;
+    private String encUser = null;
+    private Vector encryptParts = new Vector();
+    private X509Certificate encCert = null;
+    private int timeToLive = 300;   // Timestamp: time in seconds between creation and expiry
+    private WSSConfig wssConfig = null;
+    private Vector signatureValues = new Vector();
+    private WSSecHeader secHeader = null;
+
+    public void clear() {
+        soapConstants = null;
+        actor = username = pwType = sigAlgorithm = encSymmAlgo = encKeyTransport = encUser = null;
+        sigCrypto = decCrypto = encCrypto = null;
+        signatureParts.clear();
+        encryptParts.clear();
+        encCert = null;
+        utElements = null;
+        wssConfig = null;
+        signatureValues.clear();
+    }
+
+    public Object getMsgContext() {
+        return msgContext;
+    }
+
+    public void setMsgContext(Object msgContext) {
+        this.msgContext = msgContext;
+    }
+
+    public boolean isNoSerialization() {
+        return noSerialization;
+    }
+
+    public void setNoSerialization(boolean noSerialization) {
+        this.noSerialization = noSerialization;
+    }
+
+    public SOAPConstants getSoapConstants() {
+        return soapConstants;
+    }
+
+    public void setSoapConstants(SOAPConstants soapConstants) {
+        this.soapConstants = soapConstants;
+    }
+
+    public String getActor() {
+        return actor;
+    }
+
+    public void setActor(String actor) {
+        this.actor = actor;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPwType() {
+        return pwType;
+    }
+
+    public void setPwType(String pwType) {
+        this.pwType = pwType;
+    }
+
+    public String[] getUtElements() {
+        return utElements;
+    }
+
+    public void setUtElements(String[] utElements) {
+        this.utElements = utElements;
+    }
+
+    public Crypto getSigCrypto() {
+        return sigCrypto;
+    }
+
+    public void setSigCrypto(Crypto sigCrypto) {
+        this.sigCrypto = sigCrypto;
+    }
+
+    public Crypto getDecCrypto() {
+        return decCrypto;
+    }
+
+    public void setDecCrypto(Crypto decCrypto) {
+        this.decCrypto = decCrypto;
+    }
+
+    public int getSigKeyId() {
+        return sigKeyId;
+    }
+
+    public void setSigKeyId(int sigKeyId) {
+        this.sigKeyId = sigKeyId;
+    }
+
+    public String getSigAlgorithm() {
+        return sigAlgorithm;
+    }
+
+    public void setSigAlgorithm(String sigAlgorithm) {
+        this.sigAlgorithm = sigAlgorithm;
+    }
+
+    public Vector getSignatureParts() {
+        return signatureParts;
+    }
+
+    public Crypto getEncCrypto() {
+        return encCrypto;
+    }
+
+    public void setEncCrypto(Crypto encCrypto) {
+        this.encCrypto = encCrypto;
+    }
+
+    public int getEncKeyId() {
+        return encKeyId;
+    }
+
+    public void setEncKeyId(int encKeyId) {
+        this.encKeyId = encKeyId;
+    }
+
+    public String getEncSymmAlgo() {
+        return encSymmAlgo;
+    }
+
+    public void setEncSymmAlgo(String encSymmAlgo) {
+        this.encSymmAlgo = encSymmAlgo;
+    }
+
+    public String getEncKeyTransport() {
+        return encKeyTransport;
+    }
+
+    public void setEncKeyTransport(String encKeyTransport) {
+        this.encKeyTransport = encKeyTransport;
+    }
+
+    public String getEncUser() {
+        return encUser;
+    }
+
+    public void setEncUser(String encUser) {
+        this.encUser = encUser;
+    }
+
+    public Vector getEncryptParts() {
+        return encryptParts;
+    }
+
+    public X509Certificate getEncCert() {
+        return encCert;
+    }
+
+    public void setEncCert(X509Certificate encCert) {
+        this.encCert = encCert;
+    }
+
+    public int getTimeToLive() {
+        return timeToLive;
+    }
+
+    public void setTimeToLive(int timeToLive) {
+        this.timeToLive = timeToLive;
+    }
+
+    /**
+     * @return Returns the wssConfig.
+     */
+    public WSSConfig getWssConfig() {
+        return wssConfig;
+    }
+
+    /**
+     * @param wssConfig The wssConfig to set.
+     */
+    public void setWssConfig(WSSConfig wssConfig) {
+        this.wssConfig = wssConfig;
+    }
+    /**
+     * @return Returns the vector of stored signature values.
+     */
+    public Vector getSignatureValues() {
+        return signatureValues;
+    }
+
+    /**
+     * @return Returns the secHeader.
+     */
+    public WSSecHeader getSecHeader() {
+        return secHeader;
+    }
+
+    /**
+     * @param secHeader The secHeader to set.
+     */
+    public void setSecHeader(WSSecHeader secHeader) {
+        this.secHeader = secHeader;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/handler/WSHandler.java b/trunk/src/org/apache/ws/security/handler/WSHandler.java
new file mode 100644
index 0000000..656d6f8
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/handler/WSHandler.java
@@ -0,0 +1,1253 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.handler;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.action.Action;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.token.SignatureConfirmation;
+import org.apache.ws.security.message.token.Timestamp;
+import org.apache.ws.security.util.Loader;
+import org.apache.ws.security.util.StringUtil;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.XmlSchemaDateFormat;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Vector;
+
+
+/**
+ * Extracted from WSDoAllReceiver and WSDoAllSender
+ * Extended to all passwordless UsernameTokens and configurable identities.
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de).
+ * @author Marcel Ammerlaan (marcel.ammerlaan@gmail.com).
+ */
+public abstract class WSHandler {
+    public static String DONE = "done";
+    private static Log log = LogFactory.getLog(WSHandler.class.getName());
+    protected static final WSSecurityEngine secEngine = WSSecurityEngine.getInstance();
+    protected static Hashtable cryptos = new Hashtable(5);
+
+    private boolean doDebug = log.isDebugEnabled();
+
+    /**                                                             
+     * Performs all defined security actions to set-up the SOAP request.
+     * 
+     * 
+     * @param doAction a set defining the actions to do 
+     * @param doc   the request as DOM document 
+     * @param reqData a data storage to pass values around between methods
+     * @param actions a vector holding the actions to do in the order defined
+     *                in the deployment file or property
+     * @throws WSSecurityException
+     */
+    protected void doSenderAction(
+            int doAction, 
+            Document doc,
+            RequestData reqData, 
+            Vector actions, 
+            boolean isRequest
+    ) throws WSSecurityException {
+
+        boolean mu = decodeMustUnderstand(reqData);
+
+        WSSConfig wssConfig = reqData.getWssConfig();
+        if (wssConfig == null) {
+            wssConfig = WSSConfig.getNewInstance();
+        }
+
+        wssConfig
+        .setEnableSignatureConfirmation(decodeEnableSignatureConfirmation(reqData));
+
+        wssConfig
+        .setPrecisionInMilliSeconds(decodeTimestampPrecision(reqData));
+        reqData.setWssConfig(wssConfig);
+
+        Object mc = reqData.getMsgContext();
+        String actor = getString(WSHandlerConstants.ACTOR, mc);
+        reqData.setActor(actor);
+
+        WSSecHeader secHeader = new WSSecHeader(actor, mu);
+        secHeader.insertSecurityHeader(doc);
+
+        reqData.setSecHeader(secHeader);
+        reqData.setSoapConstants(WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement()));
+        /*
+         * Here we have action, username, password, and actor, mustUnderstand.
+         * Now get the action specific parameters.
+         */
+        if ((doAction & WSConstants.UT) == WSConstants.UT) {
+            decodeUTParameter(reqData);
+        }
+        /*
+         * Here we have action, username, password, and actor, mustUnderstand.
+         * Now get the action specific parameters.
+         */
+        if ((doAction & WSConstants.UT_SIGN) == WSConstants.UT_SIGN) {
+            decodeUTParameter(reqData);
+            decodeSignatureParameter(reqData);
+        }
+        /*
+         * Get and check the Signature specific parameters first because they
+         * may be used for encryption too.
+         */
+        if ((doAction & WSConstants.SIGN) == WSConstants.SIGN) {
+            reqData.setSigCrypto(loadSignatureCrypto(reqData));
+            decodeSignatureParameter(reqData);
+        }
+        /*
+         * If we need to handle signed SAML token then we need may of the
+         * Signature parameters. The handle procedure loads the signature crypto
+         * file on demand, thus don't do it here.
+         */
+        if ((doAction & WSConstants.ST_SIGNED) == WSConstants.ST_SIGNED) {
+            decodeSignatureParameter(reqData);
+        }
+        /*
+         * Set and check the encryption specific parameters, if necessary take
+         * over signature parameters username and crypto instance.
+         */
+        if ((doAction & WSConstants.ENCR) == WSConstants.ENCR) {
+            reqData.setEncCrypto(loadEncryptionCrypto(reqData));
+            decodeEncryptionParameter(reqData);
+        }
+        /*
+         * If after all the parsing no Signature parts defined, set here a
+         * default set. This is necessary because we add SignatureConfirmation
+         * and therefore the default (Body) must be set here. The default setting
+         * in WSSignEnvelope doesn't work because the vector is not empty anymore.
+         */
+        if (reqData.getSignatureParts().isEmpty()) {
+            WSEncryptionPart encP = new WSEncryptionPart(reqData.getSoapConstants()
+                    .getBodyQName().getLocalPart(), reqData.getSoapConstants()
+                    .getEnvelopeURI(), "Content");
+            reqData.getSignatureParts().add(encP);
+        }
+        /*
+         * If SignatureConfirmation is enabled and this is a response then
+         * insert SignatureConfrmation elements, note their wsu:id in the signature
+         * parts. They will be signed automatically during a (probably) defined
+         * SIGN action.
+         */
+        if (wssConfig.isEnableSignatureConfirmation() && !isRequest) {
+            String done = (String) 
+                getProperty(reqData.getMsgContext(), WSHandlerConstants.SIG_CONF_DONE);
+            if (!DONE.equals(done)
+                && (getProperty(reqData.getMsgContext(), WSHandlerConstants.RECV_RESULTS)) 
+                    != null) {
+                wssConfig.getAction(WSConstants.SC).execute(this, WSConstants.SC, doc, reqData);
+            }
+        }
+        /*
+         * Here we have all necessary information to perform the requested
+         * action(s).
+         */
+        for (int i = 0; i < actions.size(); i++) {
+
+            int actionToDo = ((Integer) actions.get(i)).intValue();
+            if (doDebug) {
+                log.debug("Performing Action: " + actionToDo);
+            }
+
+            switch (actionToDo) {
+            case WSConstants.UT:
+            case WSConstants.ENCR:
+            case WSConstants.SIGN:
+            case WSConstants.ST_SIGNED:
+            case WSConstants.ST_UNSIGNED:
+            case WSConstants.TS:
+            case WSConstants.UT_SIGN:
+                wssConfig.getAction(actionToDo).execute(this, actionToDo, doc, reqData);
+                break;
+            case WSConstants.NO_SERIALIZE:
+                reqData.setNoSerialization(true);
+                break;
+                //
+                // Handle any "custom" actions, similarly,
+                // but to preserve behavior from previous
+                // versions, consume (but log) action lookup failures.
+                //
+            default:
+                Action doit = null;
+            try {
+                doit = wssConfig.getAction(actionToDo);
+            } catch (final WSSecurityException e) {
+                log.warn(
+                        "Error trying to locate a custom action (" + actionToDo + ")", 
+                        e
+                );
+            }
+            if (doit != null) {
+                doit.execute(this, actionToDo, doc, reqData);
+            }
+            }
+        }
+        /*
+         * If this is a request then store all signature values. Add ours to
+         * already gathered values because of chained handlers, e.g. for
+         * other actors.
+         */
+
+        if (wssConfig.isEnableSignatureConfirmation() 
+                && isRequest
+                && reqData.getSignatureValues().size() > 0) {
+            Vector sigv = (Vector) 
+            getProperty(reqData.getMsgContext(), WSHandlerConstants.SEND_SIGV);
+            if (sigv == null) {
+                sigv = new Vector();
+                setProperty(reqData.getMsgContext(),
+                        WSHandlerConstants.SEND_SIGV, sigv);
+            }
+            // sigv.add(reqData.getSignatureValues());
+            sigv.addAll(reqData.getSignatureValues());
+        }
+    }
+
+
+
+    protected void doReceiverAction(int doAction, RequestData reqData)
+        throws WSSecurityException {
+
+        WSSConfig wssConfig = WSSConfig.getNewInstance();
+        wssConfig
+        .setEnableSignatureConfirmation(decodeEnableSignatureConfirmation(reqData));
+        wssConfig.setTimeStampStrict(decodeTimestampStrict(reqData));
+        wssConfig.setHandleCustomPasswordTypes(decodeCustomPasswordTypes(reqData));
+        reqData.setWssConfig(wssConfig);
+
+        if ((doAction & WSConstants.SIGN) == WSConstants.SIGN) {
+            decodeSignatureParameter2(reqData);
+        }
+
+        if ((doAction & WSConstants.ENCR) == WSConstants.ENCR) {
+            decodeDecryptionParameter(reqData);
+        }
+        if ((doAction & WSConstants.NO_SERIALIZE) == WSConstants.NO_SERIALIZE) {
+            reqData.setNoSerialization(true);
+        }
+    }
+
+    protected boolean checkReceiverResults(Vector wsResult, Vector actions) {
+        int resultActions = wsResult.size();
+        int size = actions.size();
+
+        int ai = 0;
+        for (int i = 0; i < resultActions; i++) {
+            final Integer actInt = (Integer) ((WSSecurityEngineResult) wsResult
+                    .get(i)).get(WSSecurityEngineResult.TAG_ACTION);
+            int act = actInt.intValue();
+            if (act == WSConstants.SC || act == WSConstants.BST) {
+                continue;
+            }
+            if (ai >= size || ((Integer) actions.get(ai++)).intValue() != act) {
+                return false;
+            }
+        }
+
+        if (ai != size) {
+            return false;
+        }
+
+        return true;
+    }
+
+    protected void checkSignatureConfirmation(RequestData reqData,
+            Vector wsResult) throws WSSecurityException{
+        if (doDebug) {
+            log.debug("Check Signature confirmation");
+        }
+
+        /*
+         * First get all Signature value stored during sending the request
+         */
+        Vector sigv = (Vector) getProperty(reqData.getMsgContext(),
+                WSHandlerConstants.SEND_SIGV);
+        /*
+         * Now get all results that hold a SignatureConfirmation element from
+         * the current run of receiver (we can have more than one run: if we
+         * have several security header blocks with different actors/roles)
+         */
+        Vector sigConf = new Vector();
+        WSSecurityUtil.fetchAllActionResults(wsResult, WSConstants.SC, sigConf);
+        /*
+         * now loop over all SignatureConfirmation results and check:
+         * - if there is a signature value and no Signature value generated in request: error
+         * - if there is a signature value and no matching Signature value found: error
+         * 
+         *  If a matching value found: remove from vector of stored signature values
+         */
+        for (int i = 0; i < sigConf.size(); i++) {
+            WSSecurityEngineResult result = 
+                (WSSecurityEngineResult)sigConf.get(i);
+            SignatureConfirmation sc = 
+                (SignatureConfirmation)result.get(WSSecurityEngineResult.TAG_SIGNATURE_CONFIRMATION);
+
+            byte[] sigVal = sc.getSignatureValue();
+            if (sigVal != null) {
+                if (sigv == null || sigv.size() == 0) {
+                    //If there are no store signature values
+                    if(sigVal.length != 0) {
+                        //If there's no value in the case where there are no
+                        //stored SV it is valid. Therefore if there IS a value 
+                        //in the sig confirmation element
+                        throw new WSSecurityException("WSHandler: Check Signature confirmation: got a SC element, but no stored SV");
+                    }
+                } else {
+                    //If we have stored signature values
+                    boolean found = false;
+                    for (int ii = 0; ii < sigv.size(); ii++) {
+                        byte[] storedValue = (byte[]) sigv.get(i);
+                        if (Arrays.equals(sigVal, storedValue)) {
+                            found = true;
+                            sigv.remove(ii);
+                            break;
+                        }
+                    }
+                    if (!found) {
+                        throw new WSSecurityException(
+                        "WSHandler: Check Signature confirmation: got SC element, but no matching SV");
+                    } 
+                }
+            }
+        }
+
+        /*
+         * This indicates this is the last handler: the vector holding the
+         * stored Signature values must be empty, otherwise we have an error
+         */
+        if (!reqData.isNoSerialization()) {
+            log.debug("Check Signature confirmation - last handler");
+            if (sigv != null && !sigv.isEmpty()) {
+                throw new WSSecurityException("WSHandler: Check Signature confirmation: stored SV vector not empty");
+            }
+        }
+    }
+    /**
+     * Hook to allow subclasses to load their Signature Crypto however they see
+     * fit.
+     */
+    public Crypto loadSignatureCrypto(RequestData reqData) 
+        throws WSSecurityException {
+        Crypto crypto = null;
+        /*
+         * Get crypto property file for signature. If none specified throw
+         * fault, otherwise get a crypto instance.
+         */
+        String sigPropFile = getString(WSHandlerConstants.SIG_PROP_FILE,
+                reqData.getMsgContext());
+        if (sigPropFile != null) {
+            crypto = (Crypto) cryptos.get(sigPropFile);
+            if (crypto == null) {
+                crypto = CryptoFactory.getInstance(sigPropFile, this
+                        .getClassLoader(reqData.getMsgContext()));
+                cryptos.put(sigPropFile, crypto);
+            }
+        } else if (getString(WSHandlerConstants.SIG_PROP_REF_ID, reqData
+                .getMsgContext()) != null) {
+            /*
+             * If the property file is missing then 
+             * look for the Properties object 
+             */
+            String refId = getString(WSHandlerConstants.SIG_PROP_REF_ID,
+                    reqData.getMsgContext());
+            if (refId != null) {
+                Object propObj = getProperty(reqData.getMsgContext(), refId);
+                if(propObj instanceof Properties) {
+                    crypto = (Crypto) cryptos.get(refId);
+                    if (crypto == null) {
+                        crypto = CryptoFactory.getInstance((Properties)propObj);
+                        cryptos.put(refId, crypto);
+                    }
+                } else {
+                    throw new WSSecurityException(
+                        "WSHandler: Signature: signaturePropRefId must hold a " 
+                            + "java.util.Properties object"
+                    );
+                }
+            }
+        } else {
+            throw new WSSecurityException(
+                "WSHandler: Signature: no crypto properties"
+            );
+        }
+        return crypto;
+    }
+
+    /**
+     * Hook to allow subclasses to load their Encryption Crypto however they
+     * see fit.
+     */
+    protected Crypto loadEncryptionCrypto(RequestData reqData) 
+        throws WSSecurityException {
+        Crypto crypto = null;
+        /*
+         * Get encryption crypto property file. If non specified take crypto
+         * instance from signature, if that fails: throw fault
+         */
+        String encPropFile = getString(WSHandlerConstants.ENC_PROP_FILE,
+                reqData.getMsgContext());
+        if (encPropFile != null) {
+            crypto = (Crypto) cryptos.get(encPropFile);
+            if (crypto == null) {
+                crypto = CryptoFactory.getInstance(encPropFile, this
+                        .getClassLoader(reqData.getMsgContext()));
+                cryptos.put(encPropFile, crypto);
+            }
+        } else if (getString(WSHandlerConstants.ENC_PROP_REF_ID, reqData
+                .getMsgContext()) != null) {
+            /*
+             * If the property file is missing then 
+             * look for the Properties object 
+             */
+            String refId = getString(WSHandlerConstants.ENC_PROP_REF_ID,
+                    reqData.getMsgContext());
+            if(refId != null) {
+                Object propObj = getProperty(reqData.getMsgContext(), refId);
+                if(propObj instanceof Properties) {
+                    crypto = (Crypto) cryptos.get(refId);
+                    if (crypto == null) {
+                        crypto = CryptoFactory.getInstance((Properties)propObj);
+                        cryptos.put(refId, crypto);
+                    }
+                } else {
+                    throw new WSSecurityException(
+                        "WSHandler: Encryption: encryptionPropRefId must hold a" 
+                            + " java.util.Properties object"
+                    );
+                }
+            }
+        } else if ((crypto = reqData.getSigCrypto()) == null) {
+            throw new WSSecurityException(
+                "WSHandler: Encryption: no crypto property file"
+            );
+        }
+        return crypto;
+    }
+
+    protected void decodeUTParameter(RequestData reqData) 
+        throws WSSecurityException {
+        Object mc = reqData.getMsgContext();
+
+        String type = getString(WSHandlerConstants.PASSWORD_TYPE, mc);
+        if (type != null) {
+            if(WSConstants.PW_TEXT.equals(type)) {
+                reqData.setPwType(WSConstants.PASSWORD_TEXT);
+            } else if(WSConstants.PW_DIGEST.equals(type)) {
+                reqData.setPwType(WSConstants.PASSWORD_DIGEST);
+            } else if(WSConstants.PW_NONE.equals(type)) {
+                // No password requested.
+                reqData.setPwType(null);
+            } else {
+                throw new WSSecurityException("Unknown password type encoding: " + type);
+            }
+        }
+
+        String add = getString(WSHandlerConstants.ADD_UT_ELEMENTS, mc);
+        if (add != null) {
+            reqData.setUtElements(StringUtil.split(add, ' '));
+        }
+    }
+
+    protected void decodeSignatureParameter(RequestData reqData) 
+        throws WSSecurityException {
+        Object mc = reqData.getMsgContext();
+        String keyId = getString(WSHandlerConstants.SIG_KEY_ID, mc);
+        if (keyId != null) {
+            Integer id = (Integer) WSHandlerConstants.keyIdentifier.get(keyId);
+            if (id == null) {
+                throw new WSSecurityException(
+                    "WSHandler: Signature: unknown key identification"
+                );
+            }
+            int tmp = id.intValue();
+            if (!(tmp == WSConstants.ISSUER_SERIAL
+                    || tmp == WSConstants.BST_DIRECT_REFERENCE
+                    || tmp == WSConstants.X509_KEY_IDENTIFIER
+                    || tmp == WSConstants.SKI_KEY_IDENTIFIER
+                    || tmp == WSConstants.THUMBPRINT_IDENTIFIER)) {
+                throw new WSSecurityException(
+                    "WSHandler: Signature: illegal key identification"
+                );
+            }
+            reqData.setSigKeyId(tmp);
+        }
+        String algo = getString(WSHandlerConstants.SIG_ALGO, mc);
+        reqData.setSigAlgorithm(algo);
+
+        String parts = getString(WSHandlerConstants.SIGNATURE_PARTS, mc);
+        if (parts != null) {
+            splitEncParts(parts, reqData.getSignatureParts(), reqData);
+        }
+    }
+
+    protected void decodeEncryptionParameter(RequestData reqData) 
+        throws WSSecurityException {
+        Object mc = reqData.getMsgContext();
+        String encUser = getString(WSHandlerConstants.ENCRYPTION_USER, mc);
+
+        if (encUser != null) {
+            reqData.setEncUser(encUser);
+        } else {
+            reqData.setEncUser(reqData.getUsername());
+        }
+        if (reqData.getEncUser() == null) {
+            throw new WSSecurityException("WSHandler: Encryption: no username");
+        }
+        /*
+         * String msgType = msgContext.getCurrentMessage().getMessageType(); if
+         * (msgType != null && msgType.equals(Message.RESPONSE)) {
+         * handleSpecialUser(encUser); }
+         */
+        handleSpecialUser(reqData);
+
+        /*
+         * If the following parameters are no used (they return null) then the
+         * default values of WSS4J are used.
+         */
+        String encKeyId = getString(WSHandlerConstants.ENC_KEY_ID, mc);
+        if (encKeyId != null) {
+            Integer id = (Integer) WSHandlerConstants.keyIdentifier.get(encKeyId);
+            if (id == null) {
+                throw new WSSecurityException(
+                    "WSHandler: Encryption: unknown key identification"
+                );
+            }
+            int tmp = id.intValue();
+            reqData.setEncKeyId(tmp);
+            if (!(tmp == WSConstants.ISSUER_SERIAL
+                    || tmp == WSConstants.X509_KEY_IDENTIFIER
+                    || tmp == WSConstants.SKI_KEY_IDENTIFIER
+                    || tmp == WSConstants.BST_DIRECT_REFERENCE
+                    || tmp == WSConstants.EMBEDDED_KEYNAME
+                    || tmp == WSConstants.THUMBPRINT_IDENTIFIER)) {
+                throw new WSSecurityException(
+                    "WSHandler: Encryption: illegal key identification"
+                );
+            }
+        }
+        String encSymAlgo = getString(WSHandlerConstants.ENC_SYM_ALGO, mc);
+        reqData.setEncSymmAlgo(encSymAlgo);
+
+        String encKeyTransport = 
+            getString(WSHandlerConstants.ENC_KEY_TRANSPORT, mc);
+        reqData.setEncKeyTransport(encKeyTransport);
+
+        String encParts = getString(WSHandlerConstants.ENCRYPTION_PARTS, mc);
+        if (encParts != null) {
+            splitEncParts(encParts, reqData.getEncryptParts(), reqData);
+        }
+    }
+
+    protected boolean decodeMustUnderstand(RequestData reqData) 
+        throws WSSecurityException {
+        String mu = 
+            getString(WSHandlerConstants.MUST_UNDERSTAND, reqData.getMsgContext());
+
+        if (mu == null) {return true;}
+
+        if ("0".equals(mu) || "false".equals(mu)) {return false;} 
+        if ("1".equals(mu) || "true".equals(mu)) {return true;}
+
+        throw new WSSecurityException(
+            "WSHandler: illegal mustUnderstand parameter"
+        );
+    }
+
+    public int decodeTimeToLive(RequestData reqData) {
+        String ttl = 
+            getString(WSHandlerConstants.TTL_TIMESTAMP, reqData.getMsgContext());
+        int ttl_i = 0;
+        if (ttl != null) {
+            try {
+                ttl_i = Integer.parseInt(ttl);
+            } catch (NumberFormatException e) {
+                ttl_i = reqData.getTimeToLive();
+            }
+        }
+        if (ttl_i <= 0) {
+            ttl_i = reqData.getTimeToLive();
+        }
+        return ttl_i;
+    }
+
+    protected boolean decodeEnableSignatureConfirmation(RequestData reqData) throws WSSecurityException {
+
+        String value = getString(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION,
+                reqData.getMsgContext());
+
+        if (value == null) {return true;}
+
+        if ("0".equals(value) || "false".equals(value)) {return false;} 
+        if ("1".equals(value) || "true".equals(value)) {return true;}
+
+        throw new WSSecurityException(
+            "WSHandler: illegal enableSignatureConfirmation parameter"
+        );
+    }
+
+    protected boolean decodeTimestampPrecision(RequestData reqData) 
+        throws WSSecurityException {
+        String value = getString(WSHandlerConstants.TIMESTAMP_PRECISION,
+                reqData.getMsgContext());
+
+        if (value == null) {return true;}
+
+        if ("0".equals(value) || "false".equals(value)) {return false;} 
+        if ("1".equals(value) || "true".equals(value)) {return true;}
+
+        throw new WSSecurityException(
+            "WSHandler: illegal precisionInMilliSeconds parameter"
+        );
+    }
+
+    protected boolean decodeCustomPasswordTypes(RequestData reqData) 
+        throws WSSecurityException {
+        String value = getString(
+                WSHandlerConstants.HANDLE_CUSTOM_PASSWORD_TYPES,
+                reqData.getMsgContext()
+        );
+
+        if (value == null) {return false;}
+
+        if ("0".equals(value) || "false".equals(value)) {return false;} 
+        if ("1".equals(value) || "true".equals(value)) {return true;}
+
+        throw new WSSecurityException(
+            "WSHandler: illegal handleCustomPasswordTypes parameter"
+        );
+    }
+
+    protected boolean decodeTimestampStrict(RequestData reqData) 
+        throws WSSecurityException {
+        String value = getString(WSHandlerConstants.TIMESTAMP_STRICT,
+                reqData.getMsgContext());
+
+        if (value == null) {return true;}
+
+        if ("0".equals(value) || "false".equals(value)) {return false;} 
+        if ("1".equals(value) || "true".equals(value)) {return true;}
+
+        throw new WSSecurityException(
+            "WSHandler: illegal timestampStrict parameter"
+        );
+    }
+
+    /**
+     * Get a password to construct a UsernameToken or sign a message.
+     * <p/>
+     * Try all possible sources to get a password.
+     */
+    public WSPasswordCallback getPassword(String username,
+            int doAction,
+            String clsProp,
+            String refProp,
+            RequestData reqData
+    ) throws WSSecurityException {
+        WSPasswordCallback pwCb = null;
+        CallbackHandler cbHandler = null;
+        String err = "provided null or empty password";
+        Object mc = reqData.getMsgContext();
+        String callback = getString(clsProp, mc);
+        if (callback != null) { // we have a password callback class
+            pwCb = readPwViaCallbackClass(callback, username, doAction, reqData);
+            // Null passwords are not always a problem: if the callback was called to provide a username instead.
+        } else if ((cbHandler = (CallbackHandler) getProperty(mc, refProp)) != null) {
+            pwCb = performCallback(cbHandler, username, doAction);
+        } else {
+            //
+            // If a callback isn't configured then try to get the password
+            // from the message context
+            //
+            String password = getPassword(mc);
+            if (password == null) {
+                throw new WSSecurityException("WSHandler: application " + err);
+            }
+            pwCb = constructPasswordCallback(username, doAction);
+            pwCb.setPassword(password);
+        }
+        return pwCb;
+    }
+
+    private WSPasswordCallback readPwViaCallbackClass(String callback,
+            String username,
+            int doAction,
+            RequestData requestData
+    ) throws WSSecurityException {
+
+        Class cbClass = null;
+        CallbackHandler cbHandler = null;
+        try {
+            cbClass = Loader.loadClass(getClassLoader(requestData
+                    .getMsgContext()), callback);
+        } catch (ClassNotFoundException e) {
+            throw new WSSecurityException("WSHandler: cannot load password callback class: "
+                    + callback,
+                    e);
+        }
+        try {
+            cbHandler = (CallbackHandler) cbClass.newInstance();
+        } catch (Exception e) {
+            throw new WSSecurityException("WSHandler: cannot create instance of password callback: "
+                    + callback,
+                    e);
+        }
+        return (performCallback(cbHandler, username, doAction));
+    }
+
+    /**
+     * Perform a callback to get a password.
+     * <p/>
+     * The called back function gets an indication why to provide a password:
+     * to produce a UsernameToken, Signature, or a password (key) for a given
+     * name.
+     */
+    private WSPasswordCallback performCallback(CallbackHandler cbHandler,
+            String username,
+            int doAction
+    ) throws WSSecurityException {
+
+        WSPasswordCallback pwCb = constructPasswordCallback(username, doAction);
+        Callback[] callbacks = new Callback[1];
+        callbacks[0] = pwCb;
+        /*
+         * Call back the application to get the password
+         */
+        try {
+            cbHandler.handle(callbacks);
+        } catch (Exception e) {
+            throw new WSSecurityException("WSHandler: password callback failed", e);
+        }
+        return pwCb;
+    }
+
+    private WSPasswordCallback constructPasswordCallback(
+            String username,
+            int doAction
+    ) throws WSSecurityException {
+
+        int reason = WSPasswordCallback.UNKNOWN;
+
+        switch (doAction) {
+        case WSConstants.UT:
+        case WSConstants.UT_SIGN:
+            reason = WSPasswordCallback.USERNAME_TOKEN;
+            break;
+        case WSConstants.SIGN:
+            reason = WSPasswordCallback.SIGNATURE;
+            break;
+        case WSConstants.ENCR:
+            reason = WSPasswordCallback.KEY_NAME;
+            break;
+        }
+        return new WSPasswordCallback(username, reason);
+    }
+
+    private void splitEncParts(String tmpS, Vector parts, RequestData reqData)
+        throws WSSecurityException {
+        WSEncryptionPart encPart = null;
+        String[] rawParts = StringUtil.split(tmpS, ';');
+
+        for (int i = 0; i < rawParts.length; i++) {
+            String[] partDef = StringUtil.split(rawParts[i], '}');
+
+            if (partDef.length == 1) {
+                if (doDebug) {
+                    log.debug("single partDef: '" + partDef[0] + "'");
+                }
+                encPart =
+                    new WSEncryptionPart(partDef[0].trim(),
+                            reqData.getSoapConstants().getEnvelopeURI(),
+                            "Content");
+            } else if (partDef.length == 3) {
+                String mode = partDef[0].trim();
+                if (mode.length() <= 1) {
+                    mode = "Content";
+                } else {
+                    mode = mode.substring(1);
+                }
+                String nmSpace = partDef[1].trim();
+                if (nmSpace.length() <= 1) {
+                    nmSpace = reqData.getSoapConstants().getEnvelopeURI();
+                } else {
+                    nmSpace = nmSpace.substring(1);
+                    if (nmSpace.equals(WSConstants.NULL_NS)) {
+                        nmSpace = null;
+                    }
+                }
+                String element = partDef[2].trim();
+                if (doDebug) {
+                    log.debug("partDefs: '"
+                            + mode
+                            + "' ,'"
+                            + nmSpace
+                            + "' ,'"
+                            + element
+                            + "'");
+                }
+                encPart = new WSEncryptionPart(element, nmSpace, mode);
+            } else {
+                throw new WSSecurityException("WSHandler: wrong part definition: " + tmpS);
+            }
+            parts.add(encPart);
+        }
+    }
+
+    private void handleSpecialUser(RequestData reqData) {
+        if (!WSHandlerConstants.USE_REQ_SIG_CERT.equals(reqData.getEncUser())) {
+            return;
+        }
+        Vector results = 
+            (Vector) getProperty(reqData.getMsgContext(), WSHandlerConstants.RECV_RESULTS);
+        if (results == null) {
+            return;
+        }
+        /*
+         * Scan the results for a matching actor. Use results only if the
+         * receiving Actor and the sending Actor match.
+         */
+        for (int i = 0; i < results.size(); i++) {
+            WSHandlerResult rResult =
+                (WSHandlerResult) results.get(i);
+            String hActor = rResult.getActor();
+            if (!WSSecurityUtil.isActorEqual(reqData.getActor(), hActor)) {
+                continue;
+            }
+            Vector wsSecEngineResults = rResult.getResults();
+            /*
+             * Scan the results for the first Signature action. Use the
+             * certificate of this Signature to set the certificate for the
+             * encryption action :-).
+             */
+            for (int j = 0; j < wsSecEngineResults.size(); j++) {
+                WSSecurityEngineResult wser =
+                    (WSSecurityEngineResult) wsSecEngineResults.get(j);
+                int wserAction = 
+                    ((java.lang.Integer)wser.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
+                if (wserAction == WSConstants.SIGN) {
+                    X509Certificate cert = 
+                        (X509Certificate)wser.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
+                    reqData.setEncCert(cert);
+                    return;
+                }
+            }
+        }
+    }
+
+    /**
+     * Hook to allow subclasses to load their Decryption Crypto however they 
+     * see fit.
+     */
+    protected Crypto loadDecryptionCrypto(RequestData reqData) 
+        throws WSSecurityException {
+
+        Crypto crypto = null;
+        String decPropFile = getString(WSHandlerConstants.DEC_PROP_FILE,
+                reqData.getMsgContext());
+        if (decPropFile != null) {
+            crypto = (Crypto) cryptos.get(decPropFile);
+            if (crypto == null) {
+                crypto = CryptoFactory.getInstance(decPropFile, this
+                        .getClassLoader(reqData.getMsgContext()));
+                cryptos.put(decPropFile, crypto);
+            }
+        } else if (getString(WSHandlerConstants.DEC_PROP_REF_ID, reqData
+                .getMsgContext()) != null) {
+            /*
+             * If the property file is missing then 
+             * look for the Properties object 
+             */
+            String refId = getString(WSHandlerConstants.DEC_PROP_REF_ID,
+                    reqData.getMsgContext());
+            if(refId != null) {
+                Object propObj = getProperty(reqData.getMsgContext(), refId);
+                if(propObj instanceof Properties) {
+                    crypto = (Crypto) cryptos.get(refId);
+                    if (crypto == null) {
+                        crypto = CryptoFactory.getInstance((Properties)propObj);
+                        cryptos.put(refId, crypto);
+                    }
+                } else {
+                    throw new WSSecurityException(
+                        "WSHandler: Decrytion: decryptionPropRefId must hold a" 
+                            + " java.util.Properties object"
+                    );
+                }
+            }
+        } else if ((crypto = reqData.getSigCrypto()) == null) {
+            throw new WSSecurityException(
+                "WSHandler: Encryption: no crypto property file"
+            );
+        }
+        return crypto;
+    }
+
+    protected void decodeSignatureParameter2(RequestData reqData) 
+        throws WSSecurityException {
+        reqData.setSigCrypto(loadSignatureCrypto(reqData));
+        /* There are currently no other signature parameters that need 
+         * to be handled here, but we call the load crypto hook rather 
+         * than just changing the visibility
+         * of this method to maintain parity with WSDoAllSender.
+         */
+    }
+
+    /*
+     * Set and check the decryption specific parameters, if necessary
+     * take over signature crypto instance.
+     */
+    protected void decodeDecryptionParameter(RequestData reqData) 
+        throws WSSecurityException {
+        reqData.setDecCrypto(loadDecryptionCrypto(reqData));
+        /* There are currently no other decryption parameters that need 
+         * to be handled here, but we call the load crypto hook rather 
+         * than just changing the visibility
+         * of this method to maintain parity with WSDoAllSender.
+         */
+    }
+
+    /**
+     * Get the password callback class and get an instance
+     * <p/>
+     */
+    protected CallbackHandler getPasswordCB(RequestData reqData) 
+        throws WSSecurityException {
+
+        Object mc = reqData.getMsgContext();
+        CallbackHandler cbHandler = null;
+        String callback = getString(WSHandlerConstants.PW_CALLBACK_CLASS, mc);
+        if (callback != null) {
+            Class cbClass = null;
+            try {
+                cbClass = Loader.loadClass(getClassLoader(reqData
+                        .getMsgContext()), callback);
+            } catch (ClassNotFoundException e) {
+                throw new WSSecurityException(
+                        "WSHandler: cannot load password callback class: "
+                        + callback, e);
+            }
+            try {
+                cbHandler = (CallbackHandler) cbClass.newInstance();
+            } catch (java.lang.Exception e) {
+                throw new WSSecurityException(
+                        "WSHandler: cannot create instance of password callback: "
+                        + callback, e);
+            }
+        } else {
+            cbHandler = (CallbackHandler) getProperty(mc, 
+                    WSHandlerConstants.PW_CALLBACK_REF);
+            if (cbHandler == null) {
+                throw new WSSecurityException(
+                        "WSHandler: no reference in callback property");
+            }
+        }
+        return cbHandler;
+    }
+
+    /**
+     * Evaluate whether a given certificate should be trusted.
+     * Hook to allow subclasses to implement custom validation methods however they see fit.
+     * <p/>
+     * Policy used in this implementation:
+     * 1. Search the keystore for the transmitted certificate
+     * 2. Search the keystore for a connection to the transmitted certificate
+     * (that is, search for certificate(s) of the issuer of the transmitted certificate
+     * 3. Verify the trust path for those certificates found because the search for the issuer might be fooled by a phony DN (String!)
+     *
+     * @param cert the certificate that should be validated against the keystore
+     * @return true if the certificate is trusted, false if not (AxisFault is thrown for exceptions during CertPathValidation)
+     * @throws WSSecurityException
+     */
+    protected boolean verifyTrust(X509Certificate cert, RequestData reqData) 
+        throws WSSecurityException {
+
+        // If no certificate was transmitted, do not trust the signature
+        if (cert == null) {
+            return false;
+        }
+
+        String[] aliases = null;
+        String alias = null;
+        X509Certificate[] certs;
+
+        String subjectString = cert.getSubjectDN().getName();
+        String issuerString = cert.getIssuerDN().getName();
+        BigInteger issuerSerial = cert.getSerialNumber();
+
+        if (doDebug) {
+            log.debug("WSHandler: Transmitted certificate has subject " + subjectString);
+            log.debug("WSHandler: Transmitted certificate has issuer " + issuerString + " (serial " + issuerSerial + ")");
+        }
+
+        // FIRST step
+        // Search the keystore for the transmitted certificate
+
+        // Search the keystore for the alias of the transmitted certificate
+        try {
+            alias = reqData.getSigCrypto().getAliasForX509Cert(issuerString, issuerSerial);
+        } catch (WSSecurityException ex) {
+            throw new WSSecurityException("WSHandler: Could not get alias for certificate with " + subjectString, ex);
+        }
+
+        if (alias != null) {
+            // Retrieve the certificate for the alias from the keystore
+            try {
+                certs = reqData.getSigCrypto().getCertificates(alias);
+            } catch (WSSecurityException ex) {
+                throw new WSSecurityException("WSHandler: Could not get certificates for alias " + alias, ex);
+            }
+
+            // If certificates have been found, the certificates must be compared
+            // to ensure against phony DNs (compare encoded form including signature)
+            if (certs != null && certs.length > 0 && cert.equals(certs[0])) {
+                if (doDebug) {
+                    log.debug("Direct trust for certificate with " + subjectString);
+                }
+                return true;
+            }
+        } else {
+            if (doDebug) {
+                log.debug("No alias found for subject from issuer with " + issuerString + " (serial " + issuerSerial + ")");
+            }
+        }
+
+        // SECOND step
+        // Search for the issuer of the transmitted certificate in the keystore
+
+        // Search the keystore for the alias of the transmitted certificates issuer
+        try {
+            aliases = reqData.getSigCrypto().getAliasesForDN(issuerString);
+        } catch (WSSecurityException ex) {
+            throw new WSSecurityException("WSHandler: Could not get alias for certificate with " + issuerString, ex);
+        }
+
+        // If the alias has not been found, the issuer is not in the keystore
+        // As a direct result, do not trust the transmitted certificate
+        if (aliases == null || aliases.length < 1) {
+            if (doDebug) {
+                log.debug("No aliases found in keystore for issuer " + issuerString + " of certificate for " + subjectString);
+            }
+            return false;
+        }
+
+        // THIRD step
+        // Check the certificate trust path for every alias of the issuer found in the keystore
+        for (int i = 0; i < aliases.length; i++) {
+            alias = aliases[i];
+
+            if (doDebug) {
+                log.debug("Preparing to validate certificate path with alias " + alias + " for issuer " + issuerString);
+            }
+
+            // Retrieve the certificate(s) for the alias from the keystore
+            try {
+                certs = reqData.getSigCrypto().getCertificates(alias);
+            } catch (WSSecurityException ex) {
+                throw new WSSecurityException("WSHandler: Could not get certificates for alias " + alias, ex);
+            }
+
+            // If no certificates have been found, there has to be an error:
+            // The keystore can find an alias but no certificate(s)
+            if (certs == null || certs.length < 1) {
+                throw new WSSecurityException("WSHandler: Could not get certificates for alias " + alias);
+            }
+
+            // Form a certificate chain from the transmitted certificate
+            // and the certificate(s) of the issuer from the keystore
+            // First, create new array
+            X509Certificate[] x509certs = new X509Certificate[certs.length + 1];
+            // Then add the first certificate ...
+            x509certs[0] = cert;
+            // ... and the other certificates
+            for (int j = 0; j < certs.length; j++) {
+                x509certs[j + 1] = certs[j];
+            }
+            certs = x509certs;
+
+            // Use the validation method from the crypto to check whether the subjects certificate was really signed by the issuer stated in the certificate
+            try {
+                if (reqData.getSigCrypto().validateCertPath(certs)) {
+                    if (doDebug) {
+                        log.debug("WSHandler: Certificate path has been verified for certificate with subject " + subjectString);
+                    }
+                    return true;
+                }
+            } catch (WSSecurityException ex) {
+                throw new WSSecurityException("WSHandler: Certificate path verification failed for certificate with subject " + subjectString, ex);
+            }
+        }
+
+        log.debug("WSHandler: Certificate path could not be verified for certificate with subject " + subjectString);
+        return false;
+    }
+
+    /**
+     * Evaluate whether a timestamp is considered valid on receiverside. Hook to
+     * allow subclasses to implement custom validation methods however they see
+     * fit.
+     * 
+     * Policy used in this implementation:
+     * 
+     * 1. The receiver can set its own time to live (besides from that set on
+     * sender side)
+     * 
+     * 2. If the message was created before (now-ttl) the message is rejected
+     * 
+     * @param timestamp
+     *            the timestamp that is validated
+     * @param timeToLive
+     *            the limit on receiverside, the timestamp is validated against
+     * @return true if the timestamp is before (now-timeToLive), false otherwise
+     * @throws WSSecurityException
+     */
+    protected boolean verifyTimestamp(Timestamp timestamp, int timeToLive) throws WSSecurityException {
+
+        // Calculate the time that is allowed for the message to travel
+        Calendar validCreation = Calendar.getInstance();
+        long currentTime = validCreation.getTime().getTime();
+        currentTime -= timeToLive * 1000;
+        validCreation.setTime(new Date(currentTime));
+
+        if (doDebug) {
+            log.debug("Preparing to verify the timestamp");
+            DateFormat zulu = new XmlSchemaDateFormat();
+            log.debug("Validation of Timestamp: Current time is "
+                    + zulu.format(Calendar.getInstance().getTime()));
+            log.debug("Validation of Timestamp: Valid creation is "
+                    + zulu.format(validCreation.getTime()));
+            if (timestamp.getCreated() != null) {
+                log.debug("Validation of Timestamp: Timestamp created is "
+                        + zulu.format(timestamp.getCreated().getTime()));
+            }
+        }
+        // Validate the time it took the message to travel
+        // if (timestamp.getCreated().before(validCreation) ||
+        // !timestamp.getCreated().equals(validCreation)) {
+        Calendar cre = timestamp.getCreated();
+        if (cre != null && !cre.after(validCreation)) {
+            if (doDebug) {
+                log.debug("Validation of Timestamp: The message was created too long ago");
+            }
+            return false;
+        }
+
+        if (doDebug) {
+            log.debug("Validation of Timestamp: Everything is ok");
+        }
+        return true;
+    }
+
+    /**
+     * Looks up key first via {@link #getOption(String)} and if not found
+     * there, via {@link #getProperty(Object, String)}
+     *
+     * @param key the key to search for. May not be null.
+     * @param mc the message context to search. 
+     * @return the value found.
+     * @throws IllegalArgumentException if <code>key</code> is null.
+     */
+    public String getString(String key, Object mc) { 
+        if (key == null) {
+            throw new IllegalArgumentException("Key cannot be null");
+        }
+        String s = getStringOption(key);
+        if (s != null) {
+            return s;
+        }
+        if (mc == null) {
+            throw new IllegalArgumentException("Message context cannot be null");
+        }
+        return (String) getProperty(mc, key);
+    }
+
+
+    /**
+     * Returns the option on <code>name</code>.
+     *
+     * @param key the non-null key of the option.
+     * @return the option on <code>key</code> if <code>key</code>
+     *  exists and is of type java.lang.String; otherwise null.
+     */
+    public String getStringOption(String key) {
+        Object o = getOption(key);
+        if (o instanceof String){
+            return (String) o;
+        } else {
+            return null;
+        }
+    }
+
+//  /**
+//  * Returns the classloader to be used for loading the callback class
+//  * 
+//  * @return class loader
+//  */
+//  public ClassLoader getClassLoader() {
+//  try {
+//  return Loader.getTCL();
+//  } catch (Throwable t) {
+//  return null;
+//  }
+//  }
+
+    /**
+     * Returns the classloader to be used for loading the callback class
+     * @param msgCtx The MessageContext 
+     * @return class loader
+     */
+    public ClassLoader getClassLoader(Object msgCtx) {
+        try {
+            return Loader.getTCL();
+        } catch (Throwable t) {
+            return null;
+        }
+    }
+
+    public abstract Object getOption(String key);
+    public abstract Object getProperty(Object msgContext, String key);
+
+    public abstract void setProperty(Object msgContext, String key, 
+            Object value);
+
+
+    public abstract String getPassword(Object msgContext);
+
+    public abstract void setPassword(Object msgContext, String password);
+}
diff --git a/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java b/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
new file mode 100644
index 0000000..d8dc788
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
@@ -0,0 +1,758 @@
+/*
+
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.handler;
+
+import org.apache.ws.security.WSConstants;
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * This class defines the names, actions, and other string for the deployment
+ * data of the WSS handler. Both the Axis handler as well as the JAX-RPC handler
+ * use this class.
+ *  
+ * @author Werner Dittmann (werner@apache.org)
+ */
+
+public class WSHandlerConstants {
+    /**
+     * The action parameter. The
+     * handlers use the value of this parameter to determine how
+     * to process the SOAP Envelope. For example in a Axis WSDD file:
+     * <pre>
+     * &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender">
+     * &lt;parameter name="action" value="UsernameToken"/>
+     * ...
+     * </pre>
+     * orders the handler to attach a <code>UsernameToken</code> to the SOAP
+     * enevelope. It is a blank separated list of actions to perform.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting)
+     */
+    public static final String ACTION = "action";
+    public static final String SEND = "send";
+    public static final String RECEIVE = "receive";
+
+    /**
+     * Perform nothing.
+     */
+    public static final String NO_SECURITY = "NoSecurity";
+
+    /**
+     * Perform a UsernameToken identification only.
+     */
+    public static final String USERNAME_TOKEN = "UsernameToken";
+
+    /**
+     * Perform a SAML Token identification.
+     */
+    public static final String SAML_TOKEN_UNSIGNED = "SAMLTokenUnsigned";
+    public static final String SAML_TOKEN_SIGNED = "SAMLTokenSigned";
+
+    /**
+     * Perform Signature.
+     * The signature specific parameters define how to sign, which keys
+     * to use, and so on
+     */
+    public static final String SIGNATURE = "Signature";
+
+    /**
+     * Perform Encryption.
+     * The encryption specific parameters define how to encrypt, which keys
+     * to use, and so on.
+     */
+    public static final String ENCRYPT = "Encrypt";
+
+    /**
+     * Add a timestamp to the security header.
+     */
+    public static final String TIMESTAMP = "Timestamp";
+
+    /**
+     * Supress the serialization of the SOAP message.
+     * <p/>
+     * Usually the handler serializes the processed SOAP message into a string
+     * and sets it into the Axis message context as new current message. To
+     * supress this action, define this action. In this case the handler
+     * stores the processed SOAP message as <code>Document</code> in the
+     * Axis message context with the property name <code>SND_SECURITY</code>.
+     * <p/>
+     * A chained handler can retrieve the SOAP message and process it. The
+     * last handler in the chain must set the processed SOAP message as
+     * current message in Axis message context.
+     */
+    public static final String NO_SERIALIZATION = "NoSerialization";
+
+    /**
+     * Use this to use a specific signature mechanism for .Net.
+     * This signature mechanism uses data from the username token and
+     * a well defined constant string and constructs a signature
+     * key. 
+     */
+    public static final String SIGN_WITH_UT_KEY = "UsernameTokenSignature";
+
+    /**
+     * This is an interal property name to support handler chaining.
+     * The Axis WSS4J handlers use this message context property to
+     * hand over the SOAP partially processed envelope document to
+     * the next WSS4J handler in the chain.
+     */
+    public static final String SND_SECURITY = "SND_SECURITY";
+
+    /**
+     * The actor name of the <code>wsse:Security</code> header.
+     * <p/>
+     * If this parameter is omitted, the actor name is not set. Please
+     * refer to {@link org.apache.axis.Constants#ATTR_ACTOR} and {@link org.apache.axis.Constants#ATTR_ROLE}
+     * about the parameter names. They are set to <code>"actor"</code>
+     * and <code>"role"</code> respectively.
+     * <p/>
+     * The value of the actor or role has to match the receiver's setting
+     * or may contain standard values.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.ACTOR, "ActorName");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     *
+     * @see org.apache.axis.Constants#URI_SOAP11_NEXT_ACTOR
+     * @see org.apache.axis.Constants#URI_SOAP12_NEXT_ROLE
+     */
+    public static final String ACTOR = "actor";
+
+    /**
+     * The role name of the <code>wsse:Security</code> header.
+     * This is used for SOAP 1.2. Refer also to {@link #ACTOR}.
+     */
+    public static final String ROLE = "role";
+
+    /**
+     * Sets the <code>mustUnderstand</code> flag.
+     * <p/>
+     * If the parameter has the value <code>1</code>
+     * or <code>true</code> the <code>mustUnderstand</code> is set.
+     * The values <code>0</code> or <code>false</code> supress the
+     * flag.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.MUST_UNDERSTAND, "false");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     * <p/>
+     * The default setting is <code>true</code>
+     * <p/>
+     * Please refer to {@link org.apache.axis.Constants#ATTR_MUST_UNDERSTAND}
+     * about the parameter name (<code>"mustUnderstand"</code>).
+     */
+    public static final String MUST_UNDERSTAND = "mustUnderstand";
+
+    /**
+     * The user's name. It is used differently by the WS Security functions.
+     * <ul>
+     * <li>The <i>UsernameToken</i> function sets this name in the
+     * <code>UsernameToken</code>.
+     * </li>
+     * <li>The <i>Signing</i> function uses this name as the alias name
+     * in the keystore to get user's certificate and private key to
+     * perform signing.
+     * </li>
+     * <li>The <i>encryption</i>
+     * functions uses this parameter as fallback if {@link #ENCRYPTION_USER}
+     * is not used.
+     * </li>
+     * </ul>
+     * It is also possible to set the user's name and the according password
+     * via the call function, for example:
+     * <pre>
+     * ...
+     * call.setUsername("name");
+     * call.setPassword("WSS4Java");
+     * ...
+     * </pre>
+     * The user parameter in the deployment descritor (WSDD) file overwrites
+     * the application's setting.
+     * </p>
+     * For an additional way to set the password refer to
+     * {@link #PW_CALLBACK_CLASS} and {@link #PW_CALLBACK_REF}.
+     * <p/>
+     * If the security functions uses the username from the message context, it
+     * clears the username from the message context
+     * after they copied it. This prevents sending of the username in the
+     * HTTP header.
+     * <p/>
+     * In this case the HTTP authentication mechansisms do <b>not</b> work
+     * anymore. User authentication shall be done via the username token or
+     * the certificate verification of the signature certificate.
+     */
+    public static final String USER = "user";
+
+    /**
+     * The Axis WSS4J handlers provide several ways to get the password required
+     * to construct a username token or to sign a message.
+     * In addition the callback class may check if a username/password
+     * combination is valid. Refer to the documentation of 
+     * {@link org.apache.ws.security.WSPasswordCallback} for more information
+     * about this feature.
+     * <ul>
+     * <li> A class that implements a callback interface (see below). The
+     * handler loads this class and calls the callback method. This
+     * class must have a public default constructor with not parameters.
+     * </li>
+     * <li> The application (or a preceeding handler) sets a reference to an
+     * object that implements the callback interface
+     * </li>
+     * <li> The application sets the password directly using the
+     * <code>setPassword</code> function of the <code>Call</code>.
+     * </ul>
+     * The callback class or callback object shall implement specific password
+     * getter methods, for example reading a database or directory.
+     * <p/>
+     * The handler first checks if it can get a the password via a callback
+     * class. If that fails it checks if it can get the password from the
+     * object reference, if that also fails the handler tries the password
+     * property.
+     * <p/>
+     * The following parameter defines a class that implements a callback
+     * handler interface. The handler loads the class and calls the callback
+     * handler method to get the password. The callback
+     * class needs to implement the
+     * {@link javax.security.auth.callback.CallbackHandler} interface.
+     * <p/>
+     * The callback function
+     * {@link javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])}
+     * gets an array of {@link org.apache.ws.security.WSPasswordCallback}
+     * objects. Only the first entry of the array is used. This object
+     * contains the username/keyname as identifier. The callback handler must
+     * set the password or key associated with this identifier before it returns.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, "PWCallbackClass");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     * <p/>
+     * Refer also to comment in {@link #USER} about HTTP authentication
+     * functions.
+     */
+    public static final String PW_CALLBACK_CLASS = "passwordCallbackClass";
+
+    /**
+     * An application may set an object reference to an object that implements
+     * the {@link javax.security.auth.callback.CallbackHandler} interface.
+     * Only the application can set this property using:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.PW_CALLBACK_REF, anPWCallbackObject);
+     * </pre>
+     * Refer to {@link #PW_CALLBACK_CLASS} for further information about
+     * password callback handling and the priority of the different
+     * methods.
+     * <p/>
+     * Note: every handler that preceeds this handler in the chain can set
+     * this property too. This may be useful on the server side.
+     */
+    public static final String PW_CALLBACK_REF = "passwordCallbackRef";
+
+    /**
+     * The user's name for encryption.
+     * <p/>
+     * The encryption functions uses the public key of this user's certificate
+     * to encrypt the generated symmetric key.
+     * <p/>
+     * If this parameter is not set, then the encryption
+     * function falls back to the {@link #USER} parameter to get the
+     * certificate.
+     * <p/>
+     * If <b>only</b> encryption of the SOAP body data is requested,
+     * it is recommended to use this parameter to define the username.
+     * The application can then use the standard user and password
+     * functions (see example at {@link #USER} to enable HTTP authentication
+     * functions.
+     * <p/>
+     * Encryption only does not authenticate a user / sender, therefore it
+     * does not need a password.
+     * <p/>
+     * Placing the username of the encryption certficate in the WSDD is not
+     * a security risk, because the public key of that certificate is used
+     * only.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.ENCYRPTION_USER, "encryptionuser");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     */
+    public static final String ENCRYPTION_USER = "encryptionUser";
+
+    /**
+     * Specifying this name as {@link #ENCRYPTION_USER}
+     * triggers a special action to get the public key to use for encryption.
+     * <p/>
+     * The handler uses the public key of the sender's certificate. Using this
+     * way to define an encryption key simplifies certificate management to
+     * a large extend.
+     */
+    public static final String USE_REQ_SIG_CERT = "useReqSigCert";
+
+    /**
+     * This parameter works in the same way as {@link #PW_CALLBACK_CLASS} but
+     * the Axis WSS4J handler uses it to get the key associated with a key name.
+     */
+    public static final String ENC_CALLBACK_CLASS = "EmbeddedKeyCallbackClass";
+
+    /**
+     * This parameter works in the same way as {@link #PW_CALLBACK_REF} but
+     * the Axis WSS4J handler uses it to get the key associated with a key name.
+     */
+    public static final String ENC_CALLBACK_REF = "EmbeddedKeyCallbackRef";
+
+    /**
+     * Text of the key name that needs to be sent
+     */
+    public static final String ENC_KEY_NAME = "EmbeddedKeyName";
+
+    /**
+     * The name of the crypto propterty file to use for SOAP Signature.
+     * <p/>
+     * The classloader loads this file. Therefore it must be accessible
+     * via the classpath.
+     * <p/>
+     * To locate the implementation of the
+     * {@link org.apache.ws.security.components.crypto.Crypto Crypto}
+     * interface implementation the property file must contain the property
+     * <code>org.apache.ws.security.crypto.provider</code>. The value of
+     * this property is the classname of the implementation class.
+     * <p/>
+     * The following line defines the standard implementation:
+     * <pre>
+     * org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+     * </pre>
+     * The other contents of the property file depend on the implementation
+     * of the {@link org.apache.ws.security.components.crypto.Crypto Crypto}
+     * interface implementation.
+     * <p/>
+     * The property file of the standard implementation
+     * {@link org.apache.ws.security.components.crypto.Merlin} uses
+     * the following properties:
+     * <pre>
+     * org.apache.ws.security.crypto.provider
+     * org.apache.ws.security.crypto.merlin.file
+     * org.apache.ws.security.crypto.merlin.keystore.type
+     * org.apache.ws.security.crypto.merlin.keystore.provider
+     * org.apache.ws.security.crypto.merlin.keystore.password
+     * org.apache.ws.security.crypto.merlin.keystore.alias
+     * org.apache.ws.security.crypto.merlin.cert.provider
+     * </pre>
+     * The entries are:
+     * <ul>
+     * <li> <code>org.apache.ws.security.crypto.provider</code> see
+     * description above
+     * </li>
+     * <li><code>org.apache.ws.security.crypto.merlin.file</code>
+     * The path to the keystore file. At first the classloader tries to load
+     * this file, if this fails the implementations performs a file system
+     * lookup.
+     * </li>
+     * <li><code>org.apache.ws.security.crypto.merlin.keystore.type</code>
+     * The keystore type, for example <code>JKS</code> for the Java key store.
+     * Other keystore type, such as <code>pkcs12</code> are also possible but depend
+     * on the actual <code>Crypto</code> implementation.
+     * </li>
+     * <li><code>org.apache.ws.security.crypto.merlin.keystore.password</code>
+     * The password to read the keystore. If this property is not set, then
+     * the <code>pwcallback</code>property must be defined.
+     * </li>
+     * </ul>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.SIG_PROP_FILE, "myCrypto.properties");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     * <p/>
+     * If a property file is not set and a signature is requested,
+     * the handler throws an <code>AxisFault</code>.
+     */
+    public static final String SIG_PROP_FILE = "signaturePropFile";
+
+    /**
+     * The key that hold the refernce of the <code>java.util.Properties</code> 
+     * object holding complete info about signature Crypto implementation. 
+     * This should contain all information that would contain in an equivalent 
+     * .properties file which includes the Crypto implementation class name.
+     * 
+     * Refer to documentation of {@link #SIG_PROP_FILE}.
+     */
+    public final static String SIG_PROP_REF_ID = "SignaturePropRefId";
+    
+    /**
+     * The WSDoAllReceiver handler stores a result <code>Vector</code>
+     * in this property.
+     * <p/>
+     * The vector contains <code>WSDoAllReceiverResult</code> objects
+     * for each chained WSDoAllReceiver handler.
+     */
+    public static final String RECV_RESULTS = "RECV_RESULTS";
+
+    /**
+     * The name of the crypto propterty file to use for SOAP Decryption.
+     * <p/>
+     * Refer to documentation of {@link #SIG_PROP_FILE}.
+     * <p/>
+     * Refer to {@link #SIG_PROP_FILE} for a detail description
+     * about the format and how to use this property file.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.DEC_PROP_FILE, "myCrypto.properties");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     * <p/>
+     * If this parameter is not used, but the signature crypto property
+     * file is defined (combined Encryption/Signature action), then the
+     * encryption function uses that file. Otherwise the handler throws
+     * an <code>AxisFault</code>.
+     */
+    public static final String DEC_PROP_FILE = "decryptionPropFile";
+    
+    /**
+     * The key that hold the refernce of the <code>java.util.Properties</code> 
+     * object holding complete info about decryption Crypto implementation. This
+     * should contain all information that would contain in an equivalent 
+     * .properties file which includes the Crypto implementation class name.
+     * 
+     * Refer to documentation of {@link #DEC_PROP_FILE}.
+     */
+    public final static String DEC_PROP_REF_ID = "decryptionPropRefId";
+
+    /**
+     * Specific parameter for UsernameToken action to define the encoding
+     * of the password.
+     * <p/>
+     * The parameter can be set to either {@link WSConstants#PW_DIGEST}
+     * or to {@link WSConstants#PW_TEXT}.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     * <p/>
+     * The default setting is PW_DIGEST.
+     */
+    public static final String PASSWORD_TYPE = "passwordType";
+    
+    /**
+     * This variable controls whether types other than PasswordDigest or PasswordText
+     * are allowed when processing UsernameTokens. 
+     * 
+     * By default this is set to false so that the user doesn't have to explicitly
+     * reject custom token types in the callback handler.
+     */
+    public static final String HANDLE_CUSTOM_PASSWORD_TYPES = "handleCustomPasswordTypes";
+
+    /**
+     * Parameter to generate additional elements in <code>UsernameToken</code>.
+     * <p/>
+     * The value of this parameter is a list of element names that are added
+     * to the UsernameToken. The names of the list a separated by spaces.
+     * <p/>
+     * The list may containe the names <code>nonce</code> and
+     * <code>created</code> only. Use this option if the password type is
+     * <code>passwordText</code> and the handler shall add the <code>Nonce</code>
+     * and/or <code>Created</code> elements.
+     */
+    public static final String ADD_UT_ELEMENTS = "addUTElements";
+
+    /**
+     * Defines which key identifier type to use. The WS-Security specifications
+     * recommends to use the identifier type <code>IssuerSerial</code>. For
+     * possible signature key identifier types refer to
+     * {@link #keyIdentifier}. For signature <code>IssuerSerial</code>
+     * and <code>DirectReference</code> are valid only.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     */
+    public static final String SIG_KEY_ID = "signatureKeyIdentifier";
+
+    /**
+     * Defines which signature algorithm to use. Currently this
+     * parameter is ignored - SHA1RSA is the only supported algorithm,
+     * will be enhanced soon.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.SIG_ALGO, "SHA1RSA");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     */
+    public static final String SIG_ALGO = "signatureAlgorithm";
+
+    /**
+     * Parameter to define which parts of the request shall be signed.
+     * <p/>
+     * Refer to {@link #ENCRYPTION_PARTS} for a detailed description of
+     * the format of the value string.
+     * <p/>
+     * If this parameter is not specified the handler signs the SOAP Body
+     * by default.
+     * <p/>
+     * The WS Security specifications define several formats to transfer the
+     * signature tokens (certificates) or  references to these tokens.
+     * Thus, the plain element name <code>Token</code>
+     * signs the token and takes care of the different format.
+     * <p/>
+     * To sign the SOAP body <b>and</b> the signature token the value of this
+     * parameter must contain:
+     * <pre>
+     * &lt;parameter name="signatureParts"
+     *   value="{}{http://schemas.xmlsoap.org/soap/envelope/}Body; Token" />
+     * </pre>
+     * To specify an element without a namespace use the string
+     * <code>Null</code> as the namespace name (this is a case sensitive
+     * string)
+     * <p/>
+     * If there is no other element in the request with a local name of
+     * <code>Body</code> then the SOAP namespace identifier can be empty
+     * (<code>{}</code>).
+     */
+    public static final String SIGNATURE_PARTS = "signatureParts";
+
+    /**
+     * The name of the crypto propterty file to use for SOAP Encryption.
+     * <p/>
+     * Refer to documentation of {@link #SIG_PROP_FILE}.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.ENC_PROP_FILE, "myCrypto.properties");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     * <p/>
+     * If this parameter is not used, but the signature crypto property
+     * file is defined (combined Encryption/Signature action), then the
+     * encryption function uses signature property file. Otherwise the
+     * handler throws an <code>AxisFault</code>.
+     */
+    public static final String ENC_PROP_FILE = "encryptionPropFile";
+    
+    /**
+     * The key that hold the refernce of the 
+     * <code>java.util.Properties</code> object holding complete info about 
+     * encryption Crypto implementation. This should contain all information 
+     * that would contain in an equivalent .properties file which includes the 
+     * Crypto implementation class name.
+     * 
+     * Refer to documentation of {@link #DEC_PROP_FILE}.
+     */
+    public final static String ENC_PROP_REF_ID = "encryptionPropRefId";
+
+
+    /**
+     * Defines which key identifier type to use. The WS-Security specifications
+     * recommends to use the identifier type <code>IssuerSerial</code>. For
+     * possible encryption key identifier types refer to
+     * {@link #keyIdentifier}. For encryption <code>IssuerSerial</code>,
+     * <code>X509KeyIdentifier</code>,  <code>DirectReference</code>, 
+     * <code>Thumbprint</code>, <code>SKIKeyIdentifier</code>, and
+     * <code>EmbeddedKeyName</code> are valid only.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.ENC_KEY_ID, "X509KeyIdentifier");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     */
+    public static final String ENC_KEY_ID = "encryptionKeyIdentifier";
+
+    /**
+     * Defines which symmetric encryption algorithm to use. WSS4J supports the
+     * following alorithms: {@link WSConstants#TRIPLE_DES},
+     * {@link WSConstants#AES_128}, {@link WSConstants#AES_256},
+     * and {@link WSConstants#AES_192}. Except for AES 192 all of these
+     * algorithms are required by the XML Encryption specification.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.ENC_SYM_ALGO, WSConstants.AES_256);
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     */
+    public static final String ENC_SYM_ALGO = "encryptionSymAlgorithm";
+
+    /**
+     * Defines which algorithm to use to encrypt the generated symmetric key.
+     * Currently WSS4J supports {@link WSConstants#KEYTRANSPORT_RSA15} only.
+     * <p/>
+     * The application may set this parameter using the following method:
+     * <pre>
+     * call.setProperty(WSHandlerConstants.ENC_KEY_TRANSPORT, "RSA15");
+     * </pre>
+     * However, the parameter in the WSDD deployment file overwrites the
+     * property setting (deployment setting overwrites application setting).
+     */
+    public static final String ENC_KEY_TRANSPORT =
+            "encryptionKeyTransportAlgorithm";
+
+    /**
+     * Parameter to define which parts of the request shall be encrypted.
+     * <p/>
+     * The value of this parameter is a list of semi-colon separated
+     * element names that identify the elements to encrypt. An encryption mode
+     * specifier and a namespace identification, each inside a pair of curly
+     * brackets, may preceed each element name.
+     * <p/>
+     * The encryption mode specifier is either <code>{Content}</code> or
+     * <code>{Element}</code>. Please refer to the W3C XML Encryption
+     * specification about the differences between Element and Content
+     * encryption. The encryption mode defaults to <code>Content</code>
+     * if it is omitted. Example of a list:
+     * <pre>
+     * &lt;parameter name="encryptionParts"
+     *   value="{Content}{http://example.org/paymentv2}CreditCard;
+     *             {Element}{}UserName" />
+     * </pre>
+     * The the first entry of the list identifies the element
+     * <code>CreditCard</code> in the namespace
+     * <code>http://example.org/paymentv2</code>, and will encrypt its content.
+     * Be aware that the element name, the namespace identifier, and the
+     * encryption modifier are case sensitive.
+     * <p/>
+     * The encryption modifier and the namespace identifier can be ommited.
+     * In this case the encryption mode defaults to <code>Content</code> and
+     * the namespace is set to the SOAP namespace.
+     * <p/>
+     * An empty encryption mode defaults to <code>Content</code>, an empty
+     * namespace identifier defaults to the SOAP namespace.
+     * The second line of the example defines <code>Element</code> as
+     * encryption mode for an <code>UserName</code> element in the SOAP
+     * namespace.
+     * <p/>
+     * To specify an element without a namespace use the string
+     * <code>Null</code> as the namespace name (this is a case sensitive
+     * string)
+     * <p/>
+     * If no list is specified, the handler encrypts the SOAP Body in
+     * <code>Content</code> mode by default.
+     */
+    public static final String ENCRYPTION_PARTS = "encryptionParts";
+
+    /**
+     * The name of the SAML Issuer factory property file.
+     * The classloader loads this file. Therefore it must be accessible
+     * via the classpath.
+     */
+    public static final String SAML_PROP_FILE = "samlPropFile";
+
+    /**
+     * Time-To-Live is the time difference between creation and expiry time in
+     * the WSS Timestamp.
+     * The time-to-live in seconds. After this time the SOAP request is
+     * invalid (at least the security data shall be treated this way).
+     * <p/>
+     * If this parameter is not defined, contains a value less or equal
+     * zero, or an illegal format the handlers use a default TTL of
+     * 300 seconds (5 minutes).
+     */
+    public static final String TTL_TIMESTAMP = "timeToLive";
+
+    /**
+     * Whether to enable signatureConfirmation or not
+     * By default signatureConfirmation is enabled
+     */
+    public static final String ENABLE_SIGNATURE_CONFIRMATION = "enableSignatureConfirmation";
+    
+    /**
+     * Should timestamps have precision in milliseconds
+     */
+    public static final String TIMESTAMP_PRECISION = "precisionInMilliseconds";
+    
+    /**
+     * Set the value of this parameter to true to enable strict timestamp
+     * handling.
+     * 
+     * Strict Timestamp handling: throw an exception if a Timestamp contains
+     * an <code>Expires</code> element and the semantics of the request are
+     * expired, i.e. the current time at the receiver is past the expires time. 
+     */
+    public static final String TIMESTAMP_STRICT = "timestampStrict";
+    
+    /**
+     * Define the parameter values to set the key identifier types. These are:
+     * <ul>
+     * <li><code>DirectReference</code> for {@link WSConstants#BST_DIRECT_REFERENCE}
+     * </li>
+     * <li><code>IssuerSerial</code> for {@link WSConstants#ISSUER_SERIAL}
+     * </li>
+     * <li><code>X509KeyIdentifier</code> for {@link WSConstants#X509_KEY_IDENTIFIER}
+     * </li>
+     * <li><code>SKIKeyIdentifier</code> for {@link WSConstants#SKI_KEY_IDENTIFIER}
+     * </li>
+     * <li><code>EmbeddedKeyName</code> for {@link WSConstants#EMBEDDED_KEYNAME}
+     * </li>
+     * <li><code>Thumbprint</code> for {@link WSConstants#THUMBPRINT}
+     * </li>
+     * </ul
+     * See {@link #SIG_KEY_ID} {@link #ENC_KEY_ID}.
+     */
+    public static Map keyIdentifier = new Hashtable();
+
+    static {
+        keyIdentifier.put("DirectReference",
+                new Integer(WSConstants.BST_DIRECT_REFERENCE));
+        keyIdentifier.put("IssuerSerial",
+                new Integer(WSConstants.ISSUER_SERIAL));
+        keyIdentifier.put("X509KeyIdentifier",
+                new Integer(WSConstants.X509_KEY_IDENTIFIER));
+        keyIdentifier.put("SKIKeyIdentifier",
+                new Integer(WSConstants.SKI_KEY_IDENTIFIER));
+        keyIdentifier.put("EmbeddedKeyName",
+                new Integer(WSConstants.EMBEDDED_KEYNAME));
+        keyIdentifier.put("Thumbprint",
+                new Integer(WSConstants.THUMBPRINT_IDENTIFIER));
+    }
+    /*
+     * internally used property names to store values inside the message context
+     * that must have the same livetime as a message (request/response model).
+     */
+    public static final String SEND_SIGV = "_sendSignatureValues_";
+    public static final String SIG_CONF_DONE = "_sigConfDone_";
+}
+
diff --git a/trunk/src/org/apache/ws/security/handler/WSHandlerResult.java b/trunk/src/org/apache/ws/security/handler/WSHandlerResult.java
new file mode 100644
index 0000000..4975a7a
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/handler/WSHandlerResult.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.handler;
+
+import java.util.Vector;
+
+/**
+ * @author Werner Dittmann (Werner.Dittmann@Siemens.com)
+ */
+public class WSHandlerResult {
+    private String actor;
+    private Vector wsSecurityResults;
+
+    /**
+     * constructor
+     * @param actor
+     * @param wsResults
+     */ 
+    public WSHandlerResult(String actor, Vector wsResults) {
+        this.actor = actor;
+        this.wsSecurityResults = wsResults;
+    }
+
+    /**
+     * gets the actor
+     * @return actor
+     */
+    public String getActor() {
+        return actor;
+    }
+
+    /**
+     * gets the the security results
+     * @return vector
+     */
+    public Vector getResults() {
+        return wsSecurityResults;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/handler/WSS4JHandler.java b/trunk/src/org/apache/ws/security/handler/WSS4JHandler.java
new file mode 100755
index 0000000..c0f66fd
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/handler/WSS4JHandler.java
@@ -0,0 +1,587 @@
+/*
+* Copyright  2003-2004 The Apache Software Foundation.
+*
+*  Licensed 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.ws.security.handler;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.message.token.Timestamp;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.utils.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.rpc.Call;
+import javax.xml.rpc.JAXRPCException;
+import javax.xml.rpc.handler.Handler;
+import javax.xml.rpc.handler.HandlerInfo;
+import javax.xml.rpc.handler.MessageContext;
+import javax.xml.rpc.handler.soap.SOAPMessageContext;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPHeader;
+import javax.xml.soap.SOAPHeaderElement;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPPart;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Iterator;
+import java.util.Vector;
+
+/**
+ * Merged and converted the the axis handlers WSDoAllReceiver and WSDoAllSender
+ * into a single JAX-RPC Handler. All the axis dependencies are removed.
+ *
+ * @author Venkat Reddy (vreddyp@gmail.com).
+ */
+public class WSS4JHandler extends WSHandler implements Handler {
+    private HandlerInfo handlerInfo;
+    
+    private static Log log = LogFactory.getLog(WSS4JHandler.class.getName());
+
+    private static boolean doDebug = log.isDebugEnabled();
+
+    static final String DEPLOYMENT = "deployment";
+    static final String CLIENT_DEPLOYMENT = "client";
+    static final String SERVER_DEPLOYMENT = "server";
+    static final String FLOW = "flow";
+    static final String REQUEST_ONLY = "request-only";
+    static final String RESPONSE_ONLY = "response-only";
+    static final String ALLOW_FORM_OPTIMIZATION = "axis.form.optimization";
+
+    /**
+     * Initializes the instance of the handler.
+     */
+    public void init(HandlerInfo hi) {
+        handlerInfo = hi;
+    }
+
+    /**
+     * Destroys the Handler instance.
+     */
+    public void destroy() {
+    }
+
+    public QName[] getHeaders() {
+        return handlerInfo.getHeaders();
+    }
+
+    public boolean handleRequest(MessageContext mc) {
+        mc.setProperty(ALLOW_FORM_OPTIMIZATION,
+            Boolean.TRUE);
+        try {
+            return processMessage(mc, true);
+        } catch (WSSecurityException e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+            throw new JAXRPCException(e);
+        }
+    }
+
+    public boolean handleResponse(MessageContext mc) {
+        mc.setProperty(ALLOW_FORM_OPTIMIZATION,
+            Boolean.TRUE);
+        try {
+            return processMessage(mc, false);
+        } catch (WSSecurityException e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+            throw new JAXRPCException(e);
+        }
+    }
+
+    /**
+     * Handles SOAP Faults that may occur during message processing
+     */
+    public boolean handleFault(MessageContext mc) {
+        if (doDebug) {
+            log.debug("Entered handleFault");
+        }
+        return true;
+    }
+
+    /**
+     * Switch for transferring control to doReceiver and doSender
+     */
+    public boolean processMessage(MessageContext mc, boolean isRequestMessage) throws WSSecurityException {
+
+        RequestData reqData = new RequestData();
+        reqData.setMsgContext(mc);
+
+        doDebug = log.isDebugEnabled();
+        String deployment = null;
+        String handleFlow = null;
+
+        if ((deployment = (String) getOption(DEPLOYMENT)) == null) {
+            deployment = (String) mc.getProperty(DEPLOYMENT);
+        }
+        if (deployment == null) {
+            throw new JAXRPCException("WSS4JHandler.processMessage: No deployment defined");
+        }
+        if ((handleFlow = (String) getOption(FLOW)) == null) {
+            handleFlow = (String) mc.getProperty(FLOW);
+        }
+        if (handleFlow == null) {
+            handleFlow = "";
+        }
+
+        // call doSender if we are -
+        // (handling request and client-side deployment) or (handling response and server-side deployment).
+        // call doReceiver if we are -
+        // (handling request and server-side deployment) or (handling response and client-side deployment).
+
+        boolean needsHandling = ( isRequestMessage && !handleFlow.equals(RESPONSE_ONLY)) ||
+                                (!isRequestMessage && !handleFlow.equals(REQUEST_ONLY));
+        try {
+            if (deployment.equals(CLIENT_DEPLOYMENT) ^ isRequestMessage) {
+                if (needsHandling) {
+                    return doReceiver(mc, reqData, isRequestMessage);
+                }
+            } else {
+                if (needsHandling) {
+                    return doSender(mc, reqData, isRequestMessage);
+                }
+            }
+        } finally {
+            reqData.clear();
+            reqData = null;
+        }
+        return true;
+    }
+
+    /**
+     * Handles incoming web service requests and outgoing responses
+     */
+    public boolean doSender(MessageContext mc, RequestData reqData, boolean isRequest) throws WSSecurityException {
+
+        reqData.getSignatureParts().removeAllElements();
+        reqData.getEncryptParts().removeAllElements();
+        reqData.setNoSerialization(false);
+        /*
+        * Get the action first.
+        */
+        Vector actions = new Vector();
+        String action = (String) getOption(WSHandlerConstants.SEND + '.' + WSHandlerConstants.ACTION);
+        if (action == null) {
+            if ((action = (String) getOption(WSHandlerConstants.ACTION)) == null) {
+                action = (String) mc.getProperty(WSHandlerConstants.ACTION);
+            }
+        }
+        if (action == null) {
+            throw new JAXRPCException("WSS4JHandler: No action defined");
+        }
+        int doAction = WSSecurityUtil.decodeAction(action, actions);
+        if (doAction == WSConstants.NO_SECURITY) {
+            return true;
+        }
+        
+        /*
+        * For every action we need a username, so get this now. The username
+        * defined in the deployment descriptor takes precedence.
+        */
+        reqData.setUsername((String) getOption(WSHandlerConstants.USER));
+        if (reqData.getUsername() == null || reqData.getUsername().equals("")) {
+            reqData.setUsername((String) mc.getProperty(WSHandlerConstants.USER));
+            mc.setProperty(WSHandlerConstants.USER, null);
+        }
+
+        /*
+        * Now we perform some set-up for UsernameToken and Signature
+        * functions. No need to do it for encryption only. Check if username
+        * is available and then get a password.
+        */
+        if ((doAction & (WSConstants.SIGN | WSConstants.UT | WSConstants.UT_SIGN)) != 0) {
+            /*
+            * We need a username - if none throw an JAXRPCException. For encryption
+            * there is a specific parameter to get a username.
+            */
+            if (reqData.getUsername() == null || reqData.getUsername().equals("")) {
+                throw new JAXRPCException("WSS4JHandler: Empty username for specified action");
+            }
+        }
+        if (doDebug) {
+            log.debug("Action: " + doAction);
+            log.debug("Actor: " + reqData.getActor());
+        }
+        /*
+        * Now get the SOAP part from the request message and convert it into a
+        * Document.
+        *
+        * This forces Axis to serialize the SOAP request into FORM_STRING.
+        * This string is converted into a document.
+        *
+        * During the FORM_STRING serialization Axis performs multi-ref of
+        * complex data types (if requested), generates and inserts references
+        * for attachments and so on. The resulting Document MUST be the
+        * complete and final SOAP request as Axis would send it over the wire.
+        * Therefore this must shall be the last (or only) handler in a chain.
+        *
+        * Now we can perform our security operations on this request.
+        */
+        Document doc = null;
+        SOAPMessage message = ((SOAPMessageContext)mc).getMessage();
+        Boolean propFormOptimization = (Boolean)mc.getProperty("axis.form.optimization");
+        log.debug("Form optimization: " + propFormOptimization);
+        /*
+        * If the message context property contains a document then this is a
+        * chained handler.
+        */
+        SOAPPart sPart = message.getSOAPPart();
+        if ((doc = (Document) mc.getProperty(WSHandlerConstants.SND_SECURITY))
+                == null) {
+            try {
+                doc = messageToDocument(message);
+            } catch (Exception e) {
+                if (doDebug) {
+                    log.debug(e.getMessage(), e);
+                }
+                throw new JAXRPCException("WSS4JHandler: cannot get SOAP envlope from message", e);
+            }
+        }
+        if (doDebug) {
+            log.debug("WSS4JHandler: orginal SOAP request: ");
+            log.debug(org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc));
+        }
+        doSenderAction(doAction, doc, reqData, actions, isRequest);
+ 
+        /*
+        * If required convert the resulting document into a message first. The
+        * outputDOM() method performs the necessary c14n call. After that we
+        * extract it as a string for further processing.
+        *
+        * Set the resulting byte array as the new SOAP message.
+        *
+        * If noSerialization is false, this handler shall be the last (or only)
+        * one in a handler chain. If noSerialization is true, just set the
+        * processed Document in the transfer property. The next Axis WSS4J
+        * handler takes it and performs additional security processing steps.
+        *
+        */
+        if (reqData.isNoSerialization()) {
+            mc.setProperty(WSHandlerConstants.SND_SECURITY, doc);
+        } else {
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            XMLUtils.outputDOM(doc, os, true);
+            if (doDebug) {
+                String osStr = null;
+                try {
+                    osStr = os.toString("UTF-8");
+                } catch (UnsupportedEncodingException e) {
+                    if (doDebug) {
+                        log.debug(e.getMessage(), e);
+                    }
+                    osStr = os.toString();
+                }
+                log.debug("Send request:");
+                log.debug(osStr);
+            }
+
+            try {
+                sPart.setContent(new StreamSource(new ByteArrayInputStream(os.toByteArray())));
+            } catch (SOAPException se) {
+                if (doDebug) {
+                    log.debug(se.getMessage(), se);
+                }
+                throw new JAXRPCException("Couldn't set content on SOAPPart" + se.getMessage(), se);
+            }
+            mc.setProperty(WSHandlerConstants.SND_SECURITY, null);
+        }
+        if (doDebug) {
+            log.debug("WSS4JHandler: exit invoke()");
+        }
+        return true;
+    }
+
+    /**
+     * handle responses
+     *
+     * @param mc
+     * @param reqData
+     * @return true on successful processing
+     * @throws WSSecurityException
+     */
+    public boolean doReceiver(MessageContext mc, RequestData reqData, boolean isRequest) throws WSSecurityException {
+
+        Vector actions = new Vector();
+        String action = (String) getOption(WSHandlerConstants.RECEIVE + '.' + WSHandlerConstants.ACTION);
+        if (action == null) {
+            if ((action = (String) getOption(WSHandlerConstants.ACTION)) == null) {
+                action = (String) mc.getProperty(WSHandlerConstants.ACTION);
+            }
+        }
+        if (action == null) {
+            throw new JAXRPCException("WSS4JHandler: No action defined");
+        }
+        int doAction = WSSecurityUtil.decodeAction(action, actions);
+
+        String actor = (String) getOption(WSHandlerConstants.ACTOR);
+
+        SOAPMessage message = ((SOAPMessageContext)mc).getMessage();
+        SOAPPart sPart = message.getSOAPPart();
+        Document doc = null;
+        try {
+            doc = messageToDocument(message);
+        } catch (Exception ex) {
+            if (doDebug) {
+                log.debug(ex.getMessage(), ex);
+            }
+            throw new JAXRPCException("WSS4JHandler: cannot convert into document",
+                    ex);
+        }
+        /*
+        * Check if it's a fault. Don't process faults.
+        *
+        */
+        SOAPConstants soapConstants =
+                WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
+        if (WSSecurityUtil
+                .findElement(doc.getDocumentElement(),
+                        "Fault",
+                        soapConstants.getEnvelopeURI())
+                != null) {
+            return false;
+        }
+
+        /*
+        * To check a UsernameToken or to decrypt an encrypted message we need
+        * a password.
+        */
+        CallbackHandler cbHandler = null;
+        if ((doAction & (WSConstants.ENCR | WSConstants.UT)) != 0) {
+            cbHandler = getPasswordCB(reqData);
+        }
+
+        /*
+        * Get and check the Signature specific parameters first because they
+        * may be used for encryption too.
+        */
+        doReceiverAction(doAction, reqData);
+
+        Vector wsResult = null;
+        try {
+            wsResult =
+                    secEngine.processSecurityHeader(doc,
+                            actor,
+                            cbHandler,
+                            reqData.getSigCrypto(),
+                            reqData.getDecCrypto());
+        } catch (WSSecurityException ex) {
+            if (doDebug) {
+                log.debug(ex.getMessage(), ex);
+            }
+            throw new JAXRPCException("WSS4JHandler: security processing failed",
+                    ex);
+        }
+        if (wsResult == null) {         // no security header found
+            if (doAction == WSConstants.NO_SECURITY) {
+                return true;
+            } else {
+                throw new JAXRPCException("WSS4JHandler: Request does not contain required Security header");
+            }
+        }
+        if (reqData.getWssConfig().isEnableSignatureConfirmation() && !isRequest) {
+            checkSignatureConfirmation(reqData, wsResult);
+        }
+
+        /*
+        * If we had some security processing, get the original
+        * SOAP part of Axis' message and replace it with new SOAP
+        * part. This new part may contain decrypted elements.
+        */
+
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        XMLUtils.outputDOM(doc, os, true);
+        try {
+            sPart.setContent(new StreamSource(new ByteArrayInputStream(os.toByteArray())));
+        } catch (SOAPException se) {
+            if (doDebug) {
+                log.debug(se.getMessage(), se);
+            }
+            throw new JAXRPCException(
+                "Couldn't set content on SOAPPart" + se.getMessage(), se
+            );
+        }
+
+        if (doDebug) {
+            log.debug("Processed received SOAP request");
+        }
+
+        /*
+        * After setting the new current message, probably modified because
+        * of decryption, we need to locate the security header. That is,
+        * we force Axis (with getSOAPEnvelope()) to parse the string, build
+        * the new header. Then we examine, look up the security header
+        * and set the header as processed.
+        *
+        * Please note: find all header elements that contain the same
+        * actor that was given to processSecurityHeader(). Then
+        * check if there is a security header with this actor.
+        */
+
+        SOAPHeader sHeader = null;
+        try {
+            sHeader = message.getSOAPPart().getEnvelope().getHeader();
+        } catch (Exception ex) {
+            if (doDebug) {
+                log.debug(ex.getMessage(), ex);
+            }
+            throw new JAXRPCException("WSS4JHandler: cannot get SOAP header after security processing", ex);
+        }
+
+        Iterator headers = sHeader.examineHeaderElements(actor);
+
+        SOAPHeaderElement headerElement = null;
+        while (headers.hasNext()) {
+            SOAPHeaderElement hE = (SOAPHeaderElement) headers.next();
+            if (hE.getElementName().getLocalName().equals(WSConstants.WSSE_LN)
+                    && ((Node) hE).getNamespaceURI().equals(WSConstants.WSSE_NS)) {
+                headerElement = hE;
+                break;
+            }
+        }
+
+        /* JAXRPC conversion changes */
+        headerElement.setMustUnderstand(false); // is this sufficient?
+
+        /*
+        * Now we can check the certificate used to sign the message.
+        * In the following implementation the certificate is only trusted
+        * if either it itself or the certificate of the issuer is installed
+        * in the keystore.
+        *
+        * Note: the method verifyTrust(X509Certificate) allows custom
+        * implementations with other validation algorithms for subclasses.
+        */
+
+        // Extract the signature action result from the action vector
+
+        WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(wsResult, WSConstants.SIGN);
+
+        if (actionResult != null) {
+            X509Certificate returnCert = 
+                (X509Certificate)actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
+
+            if (returnCert != null) {
+                if (!verifyTrust(returnCert, reqData)) {
+                    throw new JAXRPCException("WSS4JHandler: The certificate used for the signature is not trusted");
+                }
+            }
+        }
+
+        /*
+        * Perform further checks on the timestamp that was transmitted in the header.
+        * In the following implementation the timestamp is valid if it was
+        * created after (now-ttl), where ttl is set on server side, not by the client.
+        *
+        * Note: the method verifyTimestamp(Timestamp) allows custom
+        * implementations with other validation algorithms for subclasses.
+        */
+
+        // Extract the timestamp action result from the action vector
+        actionResult = WSSecurityUtil.fetchActionResult(wsResult, WSConstants.TS);
+
+        if (actionResult != null) {
+            Timestamp timestamp = 
+                (Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP);
+
+            if (timestamp != null && reqData.getWssConfig().isTimeStampStrict()) {
+                if (!verifyTimestamp(timestamp, decodeTimeToLive(reqData))) {
+                    throw new JAXRPCException("WSS4JHandler: The timestamp could not be validated");
+                }
+            }
+        }
+
+        /*
+        * now check the security actions: do they match, in right order?
+        */
+        if (!checkReceiverResults(wsResult, actions)) {
+            throw new JAXRPCException("WSS4JHandler: security processing failed (actions mismatch)");
+        }
+
+        /*
+        * All ok up to this point. Now construct and setup the
+        * security result structure. The service may fetch this
+        * and check it.
+        */
+        Vector results = null;
+        if ((results = (Vector) mc.getProperty(WSHandlerConstants.RECV_RESULTS))
+                == null) {
+            results = new Vector();
+            mc.setProperty(WSHandlerConstants.RECV_RESULTS, results);
+        }
+        WSHandlerResult rResult =
+                new WSHandlerResult(actor,
+                        wsResult);
+        results.add(0, rResult);
+        if (doDebug) {
+            log.debug("WSS4JHandler: exit invoke()");
+        }
+
+        return true;
+    }
+
+    /**
+     * Utility method to convert SOAPMessage to org.w3c.dom.Document
+     */
+    public static Document messageToDocument(SOAPMessage message) {
+        try {
+            Source content = message.getSOAPPart().getContent();
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+            dbf.setNamespaceAware(true);
+            DocumentBuilder builder = dbf.newDocumentBuilder();
+            return builder.parse(org.apache.ws.security.util.XMLUtils.sourceToInputSource(content));
+        } catch (Exception ex) {
+            if (doDebug) {
+                log.debug(ex.getMessage(), ex);
+            }
+            throw new JAXRPCException("messageToDocument: cannot convert SOAPMessage into Document", ex);
+        }
+    }
+
+    public Object getOption(String key) {
+        return handlerInfo.getHandlerConfig().get(key);
+    }
+
+    public Object getProperty(Object msgContext, String key) {
+        return ((MessageContext)msgContext).getProperty(key);
+    }
+
+    public void setProperty(Object msgContext, String key, Object value) {
+        ((MessageContext)msgContext).setProperty(key, value);
+    }
+
+    public String getPassword(Object msgContext) {
+        return (String) ((MessageContext)msgContext).getProperty(Call.PASSWORD_PROPERTY);
+    }
+
+    public void setPassword(Object msgContext, String password) {
+        ((MessageContext)msgContext).setProperty(Call.PASSWORD_PROPERTY, password);
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/EnvelopeIdResolver.java b/trunk/src/org/apache/ws/security/message/EnvelopeIdResolver.java
new file mode 100644
index 0000000..987cfa1
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/EnvelopeIdResolver.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.signature.XMLSignatureInput;
+import org.apache.xml.security.utils.resolver.ResourceResolverException;
+import org.apache.xml.security.utils.resolver.ResourceResolverSpi;
+import org.apache.xml.utils.URI;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * XML-Security resolver that is used for resolving same-document URIs like URI="#id".
+ * It is designed to work only with SOAPEnvelopes.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class EnvelopeIdResolver extends ResourceResolverSpi {
+    private static Log log =
+            LogFactory.getLog(EnvelopeIdResolver.class.getName());
+
+    private static EnvelopeIdResolver resolver = null;
+
+    private boolean doDebug = false;
+
+    /**
+     * Singleton instance of the resolver.
+     * <p/>
+     *
+     * @return TODO
+     */
+    public synchronized static ResourceResolverSpi getInstance() {
+        if (resolver == null) {
+            resolver = new EnvelopeIdResolver();
+        }
+        return resolver;
+    }
+
+    private EnvelopeIdResolver() {
+    }
+
+    /**
+     * This is the workhorse method used to resolve resources.
+     * <p/>
+     *
+     * @param uri
+     * @param BaseURI
+     * @return TODO
+     * @throws ResourceResolverException
+     */
+    public XMLSignatureInput engineResolve(Attr uri, String BaseURI)
+            throws ResourceResolverException {
+
+        doDebug = log.isDebugEnabled();
+
+        String uriNodeValue = uri.getNodeValue();
+
+        if (doDebug) {
+            log.debug("enter engineResolve, look for: " + uriNodeValue);
+        }
+
+        Document doc = uri.getOwnerDocument();
+
+        /*
+         * URI="#chapter1"
+         * Identifies a node-set containing the element with ID attribute
+         * value 'chapter1' of the XML resource containing the signature.
+         * XML Signature (and its applications) modify this node-set to
+         * include the element plus all descendents including namespaces and
+         * attributes -- but not comments.
+         */
+         
+        /*
+         * First lookup the SOAP Body element (processed by default) and
+         * check if it contains an Id and if it matches
+         */
+        String id = uriNodeValue.substring(1);
+        SOAPConstants sc = WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
+        Element selectedElem = WSSecurityUtil.findBodyElement(doc, sc);
+        if (selectedElem == null) {
+            throw new ResourceResolverException("generic.EmptyMessage",
+                    new Object[]{"Body element not found"},
+                    uri,
+                    BaseURI);
+        }
+        String cId = selectedElem.getAttributeNS(WSConstants.WSU_NS, "Id");
+
+        /*
+         * If Body Id match fails, look for a generic Id (without a namespace)
+         * that matches the URI. If that lookup fails, try to get a namespace
+         * qualified Id that matches the URI.
+         */
+        if (!id.equals(cId)) {
+            cId = null;
+            if ((selectedElem = WSSecurityUtil.getElementByWsuId(doc, uriNodeValue)) != null) {
+                cId = selectedElem.getAttributeNS(WSConstants.WSU_NS,"Id");
+            } else if ((selectedElem = WSSecurityUtil.getElementByGenId(doc, uriNodeValue)) != null) {
+                cId = selectedElem.getAttribute("Id");
+            }
+            if (cId == null) {
+                throw new ResourceResolverException("generic.EmptyMessage",
+                        new Object[]{"Id not found"},
+                        uri,
+                        BaseURI);
+            }
+        }
+
+        XMLSignatureInput result = new XMLSignatureInput(selectedElem);
+        result.setMIMEType("text/xml");
+        try {
+            URI uriNew = new URI(new URI(BaseURI), uri.getNodeValue());
+            result.setSourceURI(uriNew.toString());
+        } catch (URI.MalformedURIException ex) {
+            result.setSourceURI(BaseURI);
+        }
+        if (doDebug) {
+            log.debug("exit engineResolve, result: " + result);
+        }
+        return result;
+    }
+
+    /**
+     * This method helps the ResourceResolver to decide whether a
+     * ResourceResolverSpi is able to perform the requested action.
+     * <p/>
+     *
+     * @param uri
+     * @param BaseURI
+     * @return TODO
+     */
+    public boolean engineCanResolve(Attr uri, String BaseURI) {
+        if (uri == null) {
+            return false;
+        }
+        String uriNodeValue = uri.getNodeValue();
+        return uriNodeValue.startsWith("#");
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSAddSignatureConfirmation.java b/trunk/src/org/apache/ws/security/message/WSAddSignatureConfirmation.java
new file mode 100644
index 0000000..ca1fbde
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSAddSignatureConfirmation.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.message.token.SignatureConfirmation;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Builds a WS SignatureConfirmation and inserts it into the SOAP Envelope.
+ * 
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de).
+ */
+
+public class WSAddSignatureConfirmation extends WSBaseMessage {
+    private static Log log = LogFactory.getLog(WSAddSignatureConfirmation.class
+            .getName());
+
+    private SignatureConfirmation sc = null;
+
+    private String id = null;
+
+    /**
+     * Constructor.
+     * 
+     * @deprecated replaced by {@link WSSecSignatureConfirmation#WSSecSignatureConfirmation()}
+     */
+    public WSAddSignatureConfirmation() {
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param actor
+     *            the name of the actor of the <code>wsse:Security</code>
+     *            header
+     * 
+     * @deprecated replaced by {@link WSSecSignatureConfirmation#WSSecSignatureConfirmation()}
+     *             and {@link WSSecHeader} for actor specification.
+     */
+    public WSAddSignatureConfirmation(String actor) {
+        super(actor);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param actor
+     *            The name of the actor of the <code>wsse:Security</code>
+     *            header
+     * @param mu
+     *            Set <code>mustUnderstand</code> to true or false
+     * 
+     * @deprecated replaced by {@link WSSecSignatureConfirmation#WSSecSignatureConfirmation()}
+     *             and {@link WSSecHeader} for actor and mustunderstand
+     *             specification.
+     */
+    public WSAddSignatureConfirmation(String actor, boolean mu) {
+        super(actor, mu);
+    }
+
+    /**
+     * Adds a new <code>SignatureConfirmation</code> to a soap envelope.
+     * 
+     * A complete <code>SignatureConfirmation</code> is constructed and added
+     * to the <code>wsse:Security</code> header.
+     * 
+     * @param doc
+     *            The SOAP enevlope as W3C document
+     * @param sigVal
+     *            the Signature value. This will be the content of the "Value"
+     *            attribute.
+     * @return Document with SignatureConfirmation added
+     * 
+     * @deprecated replaced by
+     *             {@link WSSecSignatureConfirmation#build(Document, byte[], WSSecHeader)}
+     */
+    public Document build(Document doc, byte[] sigVal) {
+        log.debug("Begin add signature confirmation...");
+        Element securityHeader = insertSecurityHeader(doc);
+        sc = new SignatureConfirmation(doc, sigVal);
+        if (id != null) {
+            sc.setID(id);
+        }
+        WSSecurityUtil.prependChildElement(doc, securityHeader,
+                sc.getElement(), true);
+        sc = null;
+        return doc;
+    }
+
+    /**
+     * Set the wsu:Id value of the SignatureConfirmation
+     * 
+     * @param id
+     * 
+     * @deprecated no replacement, id is created by default in
+     *             {@link WSSecSignatureConfirmation}
+     */
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    /**
+     * Get the wsu:Id value of the SignatureConfirmation
+     * 
+     * @return Returns the wsu:id value
+     * 
+     * @deprecated replaced by {@link WSSecSignatureConfirmation#getId()}
+     */
+    public String getId() {
+        return id;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSAddTimestamp.java b/trunk/src/org/apache/ws/security/message/WSAddTimestamp.java
new file mode 100644
index 0000000..42d687e
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSAddTimestamp.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.message.token.Timestamp;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Builds a WS Timestamp and inserts it into the SOAP Envelope. Refer to the WS
+ * specification 1.0. chapter 10 / appendix A.2
+ * 
+ * @author Christof Soehngen (Christof.Soehngen@syracom.de).
+ */
+
+public class WSAddTimestamp extends WSBaseMessage {
+    private static Log log = LogFactory.getLog(WSAddTimestamp.class.getName());
+
+    private Timestamp ts = null;
+
+    private String id = null;
+
+    /**
+     * Constructor.
+     * 
+     * @deprecated replaced by {@link WSSecTimestamp#WSSecTimestamp()}
+     */
+    public WSAddTimestamp() {
+    }
+
+    /**
+     * Constructor. <p/>
+     * 
+     * @param actor
+     *            the name of the actor of the <code>wsse:Security</code>
+     *            header
+     * 
+     * @deprecated replaced by {@link WSSecTimestamp#WSSecTimestamp()} and
+     *             {@link WSSecHeader} for actor specification.
+     */
+    public WSAddTimestamp(String actor) {
+        super(actor);
+    }
+
+    /**
+     * Constructor. <p/>
+     * 
+     * @param actor
+     *            The name of the actor of the <code>wsse:Security</code>
+     *            header
+     * @param mu
+     *            Set <code>mustUnderstand</code> to true or false
+     * @deprecated replaced by {@link WSSecTimestamp#WSSecTimestamp()} and
+     *             {@link WSSecHeader} for actor and mustunderstand
+     *             specification.
+     */
+    public WSAddTimestamp(String actor, boolean mu) {
+        super(actor, mu);
+    }
+
+    /**
+     * Adds a new <code>Timestamp</code> to a soap envelope.
+     * 
+     * A complete <code>Timestamp</code> is constructed and added to the
+     * <code>wsse:Security</code> header.
+     * 
+     * @param doc
+     *            The SOAP enevlope as W3C document
+     * @param ttl
+     *            This is the time difference in seconds between the
+     *            <code>Created</code> and the <code>Expires</code> in
+     *            <code>Timestamp</code>, set to zero if <code>Expires</code>
+     *            should not be added.
+     * @return Document with Timestamp added
+     * @throws Exception
+     * @deprecated replaced by
+     *             {@link WSSecTimestamp#build(Document, WSSecHeader)} and
+     *             {@link WSSecTimestamp#setTimeToLive(int)}
+     */
+    public Document build(Document doc, int ttl) {
+        log.debug("Begin add timestamp...");
+        Element securityHeader = insertSecurityHeader(doc);
+        ts = new Timestamp(wssConfig.isPrecisionInMilliSeconds(), doc, ttl);
+        if (id != null) {
+            ts.setID(id);
+        }
+        WSSecurityUtil.prependChildElement(doc, securityHeader,
+                ts.getElement(), true);
+        return doc;
+    }
+
+    /**
+     * Set the wsu:Id value of the Timestamp
+     * 
+     * @param id
+     * @deprecated no replacement, id is created by default in
+     *             {@link WSSecTimestamp}
+     */
+    public void setId(String id) {
+        this.id = id;
+        if (ts != null)
+            ts.setID(id);
+    }
+
+    /**
+     * Get the wsu:Id value of the Timestamp
+     * 
+     * @return TODO
+     *
+     * @deprecated replaced by {@link WSSecTimestamp#getId()}
+     */
+    public String getId() {
+        return id;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSBaseMessage.java b/trunk/src/org/apache/ws/security/message/WSBaseMessage.java
new file mode 100644
index 0000000..8fdb120
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSBaseMessage.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.Vector;
+
+/**
+ * This is the base class for WS Security messages. It provides common functions
+ * and fields used by the specific message classes such as sign, encrypt, and
+ * username token.
+ * 
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de)
+ */
+public class WSBaseMessage {
+    protected String actor = null;
+
+    protected boolean mustunderstand = true;
+
+    protected String user = null;
+
+    protected String password = null;
+
+    protected int keyIdentifierType = WSConstants.ISSUER_SERIAL;
+
+    protected Vector parts = null;
+
+    protected int timeToLive = 300; // time between Created and Expires
+
+    protected boolean doDebug = false;
+
+    protected WSSConfig wssConfig = WSSConfig.getDefaultWSConfig();
+
+    /**
+     * Constructor.
+     * 
+     * @deprecated replaced by {@link WSSecBase#WSSecBase()}
+     */
+    public WSBaseMessage() {
+    }
+
+    /**
+     * Constructor. <p/>
+     * 
+     * @param actor
+     *            The actor name of the <code>wsse:Security</code> header
+     * @deprecated replaced by {@link WSSecBase#WSSecBase()} and
+     *             {@link WSSecHeader} for actor specification.
+     */
+    public WSBaseMessage(String actor) {
+        this(actor, true);
+    }
+
+    /**
+     * Constructor. <p/>
+     * 
+     * @param actor
+     *            The actor name of the <code>wsse:Security</code> header
+     * @param mu
+     *            Set <code>mustUnderstand</code> to true or false
+     * 
+     * @deprecated replaced by {@link WSSecBase#WSSecBase()} and
+     *             {@link WSSecHeader} for actor and mustunderstand
+     *             specification.
+     */
+    public WSBaseMessage(String actor, boolean mu) {
+        setActor(actor);
+        setMustUnderstand(mu);
+    }
+
+    /**
+     * set actor name. <p/>
+     * 
+     * @param act
+     *            The actor name of the <code>wsse:Security</code> header
+     * @deprecated replaced by {@link WSSecHeader#setActor(String)}
+     */
+    public void setActor(String act) {
+        actor = act;
+    }
+
+    /**
+     * Set the time to live. This is the time difference in seconds between the
+     * <code>Created</code> and the <code>Expires</code> in
+     * <code>Timestamp</code>. <p/>
+     * 
+     * @param ttl
+     *            The time to live in second
+     * @deprecated replaced by {@link WSSecTimestamp#setTimeToLive(int)}
+     */
+    public void setTimeToLive(int ttl) {
+        timeToLive = ttl;
+    }
+
+    /**
+     * Set which parts of the message to encrypt/sign. <p/>
+     * 
+     * @param parts
+     *            The vector containing the WSEncryptionPart objects
+     * @deprecated replaced by {@link WSSecBase#setParts(Vector)}
+     */
+    public void setParts(Vector parts) {
+        this.parts = parts;
+    }
+
+    /**
+     * Set the <code>mustUnderstand</code> flag for the
+     * <code>wsse:Security</code> header
+     * 
+     * @param mu
+     *            Set <code>mustUnderstand</code> to true or false
+     * @deprecated replaced by {@link WSSecHeader#setMustUnderstand(boolean)}
+     */
+    public void setMustUnderstand(boolean mu) {
+        mustunderstand = mu;
+    }
+
+    /**
+     * Sets which key identifier to use. <p/> Defines the key identifier type to
+     * use in the {@link WSSignEnvelope#build(Document, Crypto) signature} or
+     * the {@link WSEncryptBody#build(Document, Crypto) ecnryption} function to
+     * set up the key identification elements.
+     * 
+     * @param keyIdType
+     * @see WSConstants#ISSUER_SERIAL
+     * @see WSConstants#BST_DIRECT_REFERENCE
+     * @see WSConstants#X509_KEY_IDENTIFIER
+     * @see WSConstants#SKI_KEY_IDENTIFIER
+     * @deprecated replaced by {@link WSSecBase#setKeyIdentifierType(int)}
+     */
+    public void setKeyIdentifierType(int keyIdType) {
+        keyIdentifierType = keyIdType;
+    }
+
+    /**
+     * Gets the value of the <code>keyIdentifyerType</code>.
+     * 
+     * @return The <code>keyIdentifyerType</code>.
+     * @see WSConstants#ISSUER_SERIAL
+     * @see WSConstants#BST_DIRECT_REFERENCE
+     * @see WSConstants#X509_KEY_IDENTIFIER
+     * @see WSConstants#SKI_KEY_IDENTIFIER
+     * @deprecated replaced by {@link WSSecBase#getKeyIdentifierType()}
+     */
+    public int getKeyIdentifierType() {
+        return keyIdentifierType;
+    }
+
+    /**
+     * @param wsConfig
+     *            The wsConfig to set.
+     * @deprecated replaced by {@link WSSecBase#setWsConfig(WSSConfig)}
+     */
+    public void setWsConfig(WSSConfig wsConfig) {
+        this.wssConfig = wsConfig;
+    }
+
+    /**
+     * Looks up or adds a body id. <p/> First try to locate the
+     * <code>wsu:Id</code> in the SOAP body element. If one is found, the
+     * value of the <code>wsu:Id</code> attribute is returned. Otherwise the
+     * methode generates a new <code>wsu:Id</code> and an appropriate value.
+     * 
+     * @param doc
+     *            The SOAP envelope as <code>Document</code>
+     * @return The value of the <code>wsu:Id</code> attribute of the SOAP body
+     * @throws Exception
+     * @deprecated replaced by {@link WSSecBase#setBodyID(Document)}
+     */
+    protected String setBodyID(Document doc) throws Exception {
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+        Element bodyElement = (Element) WSSecurityUtil.getDirectChild(doc
+                .getFirstChild(), soapConstants.getBodyQName().getLocalPart(),
+                soapConstants.getEnvelopeURI());
+        if (bodyElement == null) {
+            throw new Exception("SOAP Body Element node not found");
+        }
+        return setWsuId(bodyElement);
+    }
+
+    protected String setWsuId(Element bodyElement) {
+        String id = null;
+        id = bodyElement.getAttributeNS(WSConstants.WSU_NS, "Id");
+
+        if ((id == null) || (id.length() == 0)) {
+            id = "id-" + Integer.toString(bodyElement.hashCode());
+            String prefix = WSSecurityUtil.setNamespace(bodyElement,
+                    WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+            bodyElement.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+        }
+        return id;
+    }
+
+    /**
+     * Set the user and password info. <p/> Both information is used to get the
+     * user's private signing key.
+     * 
+     * @param user
+     *            This is the user's alias name in the keystore that identifies
+     *            the private key to sign the document
+     * @param password
+     *            The user's password to get the private signing key from the
+     *            keystore
+     * @deprecated replaced by {@link WSSecBase#setUserInfo(String, String)}
+     */
+    public void setUserInfo(String user, String password) {
+        this.user = user;
+        this.password = password;
+    }
+
+    /**
+     * Creates a security header and inserts it as child into the SOAP Envelope.
+     * <p/> Check if a WS Security header block for an actor is already
+     * available in the document. If a header block is found return it,
+     * otherwise a new wsse:Security header block is created and the attributes
+     * set
+     * 
+     * @param doc
+     *            A SOAP envelope as <code>Document</code>
+     * @return A <code>wsse:Security</code> element
+     * @deprecated replaced by
+     *             {@link WSSecHeader#insertSecurityHeader(Document)}
+     */
+    protected Element insertSecurityHeader(Document doc) {
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+        // lookup a security header block that matches actor
+        Element securityHeader = WSSecurityUtil.getSecurityHeader(doc, actor,
+                soapConstants);
+        if (securityHeader == null) { // create if nothing found
+            securityHeader = WSSecurityUtil.findWsseSecurityHeaderBlock(doc,
+                    doc.getDocumentElement(), actor, true);
+
+            String soapPrefix = WSSecurityUtil.getPrefixNS(soapConstants
+                    .getEnvelopeURI(), securityHeader);
+            if (actor != null && actor.length() > 0) {
+                // Check for SOAP 1.2 here and use "role" instead of "actor"
+                securityHeader.setAttributeNS(soapConstants.getEnvelopeURI(),
+                        soapPrefix
+                                + ":"
+                                + soapConstants.getRoleAttributeQName()
+                                        .getLocalPart(), actor);
+            }
+            if (mustunderstand) {
+                securityHeader.setAttributeNS(soapConstants.getEnvelopeURI(),
+                        soapPrefix + ":" + WSConstants.ATTR_MUST_UNDERSTAND,
+                        soapConstants.getMustUnderstand());
+            }
+        }
+        return securityHeader;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSEncryptBody.java b/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
new file mode 100644
index 0000000..8595332
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
@@ -0,0 +1,787 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.EncryptedData;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.Vector;
+
+/**
+ * Encrypts a SOAP body inside a SOAP envelope according to WS Specification,
+ * X509 profile, and adds the encryption data.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com).
+ */
+public class WSEncryptBody extends WSBaseMessage {
+    private static Log log = LogFactory.getLog(WSEncryptBody.class.getName());
+    private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
+
+    protected String symEncAlgo = WSConstants.AES_128;
+    protected String keyEncAlgo = WSConstants.KEYTRANSPORT_RSA15;
+    protected String encCanonAlgo = null;
+    protected byte[] embeddedKey = null;
+    protected String embeddedKeyName = null;
+    protected X509Certificate useThisCert = null;
+
+    /**
+     * Symmetric key used in the EncrytpedKey.
+     */
+    protected SecretKey symmetricKey = null;
+
+    /**
+     * Symmetric key that's actually used.
+     */
+    protected SecretKey encryptionKey = null;
+
+    /**
+     * Parent node to which the EncryptedKeyElement should be added.
+     */
+    protected Element parentNode = null;
+
+    /**
+     * SecurityTokenReference to be inserted into EncryptedData/keyInfo element.
+     */
+    protected SecurityTokenReference securityTokenReference = null;
+
+    /**
+     * Constructor.
+     * @deprecated replaced by {@link WSSecEncrypt#WSSecEncrypt()}
+    */
+    public WSEncryptBody() {
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param actor The actor name of the <code>wsse:Security</code>
+     *              header
+     * 
+     * @deprecated replaced by {@link WSSecEncrypt#WSSecEncrypt()}
+     *             and {@link WSSecHeader} for actor specification.
+     */
+    public WSEncryptBody(String actor) {
+        super(actor);
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param actor The actor name of the <code>wsse:Security</code> header
+     * @param mu    Set <code>mustUnderstand</code> to true or false
+     * 
+     * @deprecated replaced by {@link WSSecEncrypt#WSSecEncrypt()}
+     *             and {@link WSSecHeader} for actor and mustunderstand
+     *             specification.
+     */
+    public WSEncryptBody(String actor, boolean mu) {
+        super(actor, mu);
+    }
+
+    /**
+     * Sets the key to use during embedded encryption.
+     * <p/>
+     *
+     * @param key to use during encryption. The key must fit the
+     *            selected symmetrical encryption algorithm
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#setKey(byte[])}
+     */
+    public void setKey(byte[] key) {
+        this.embeddedKey = key;
+    }
+
+    /**
+     * Sets the algorithm to encode the symmetric key.
+     * <p/>
+     * Default is the <code>WSConstants.KEYTRANSPORT_RSA15</code>
+     * algorithm.
+     *
+     * @param keyEnc specifies the key encoding algorithm.
+     * @see WSConstants#KEYTRANSPORT_RSA15
+     * @see WSConstants#KEYTRANSPORT_RSAOEP
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#setKeyEnc(String)}
+     */
+    public void setKeyEnc(String keyEnc) {
+        keyEncAlgo = keyEnc;
+    }
+
+    /**
+     * Set the user name to get the encryption certificate. The public
+     * key of this certificate is used, thus no password necessary.
+     * The user name is a keystore alias usually.
+     * <p/>
+     *
+     * @param user
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#setUserInfo(String)}
+     */
+    public void setUserInfo(String user) {
+        this.user = user;
+    }
+
+    /**
+     * Set the key name for EMBEDDED_KEYNAME
+     *
+     * @param embeddedKeyName
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#setEmbeddedKeyName(String)}
+     */
+    public void setEmbeddedKeyName(String embeddedKeyName) {
+        this.embeddedKeyName = embeddedKeyName;
+    }
+
+    /**
+     * Set the X509 Certificate to use for encryption.
+     * If this is set <b>and</b> the key identifier is set
+     * to <code>DirectReference</code> then use this certificate
+     * to get the public key for encryption.
+     *
+     * @param cert is the X509 certificate to use for encryption
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#setUseThisCert(X509Certificate)}
+     */
+    public void setUseThisCert(X509Certificate cert) {
+        useThisCert = cert;
+    }
+
+    /**
+     * Set the name of the symmetric encryption algorithm to use.
+     * <p/>
+     * This encryption alogrithm is used to encrypt
+     * the data, i.e. the SOAP Body. If the algorithm
+     * is not set then Triple DES is used. Refer to
+     * WSConstants which algorithms are supported.
+     * <p/>
+     *
+     * @param algo Is the name of the encryption algorithm
+     * @see WSConstants#TRIPLE_DES
+     * @see WSConstants#AES_128
+     * @see WSConstants#AES_192
+     * @see WSConstants#AES_256
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#setSymmetricEncAlgorithm(String)}
+     */
+    public void setSymmetricEncAlgorithm(String algo) {
+        symEncAlgo = algo;
+    }
+
+    /**
+     * Set the name of an optional canonicalization algorithm to use
+     * before encryption.
+     * <p/>
+     * This c14n alogrithm is used to serialize the data before
+     * encryption, i.e. the SOAP Body. If the algorithm
+     * is not set then a standard serialization is used (provided
+     * by XMLCipher, usually a XMLSerializer according to DOM 3
+     * specification).
+     * <p/>
+     *
+     * @param algo Is the name of the canonicalization algorithm
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#setEncCanonicalization(String)}
+     */
+    public void setEncCanonicalization(String algo) {
+        encCanonAlgo = algo;
+    }
+
+    /**
+     * Get the name of symmetric encryption algorithm to use.
+     * <p/>
+     * The name of the encryption alogrithm to encrypt
+     * the data, i.e. the SOAP Body. Refer to
+     * WSConstants which algorithms are supported.
+     * <p/>
+     *
+     * @return the name of the currently selected symmetric encryption
+     *         algorithm
+     * @see WSConstants#TRIPLE_DES
+     * @see WSConstants#AES_128
+     * @see WSConstants#AES_192
+     * @see WSConstants#AES_256
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#getSymmetricEncAlgorithm()}
+     */
+    public String getSymmetricEncAlgorithm() {
+        return symEncAlgo;
+    }
+
+    /**
+     * Builds the SOAP envelope with encrypted Body and adds encrypted key.
+     * <p/>
+     * This function performs several steps:
+     * <p/>
+     * <ul>
+     * <li>    First step: set the encoding namespace in the SOAP:Envelope </li>
+     * <li>    Second step: generate a symmetric key (session key) for
+     * the selected symmetric encryption algorithm, and set the cipher
+     * into encryption mode.
+     * </li>
+     * <li> Third step: get the data to encrypt.
+     * We always encrypt the complete first child element of
+     * the SOAP Body element
+     * </li>
+     * <li>    Forth step: encrypt data, and set neccessary attributes in
+     * <code>xenc:EncryptedData</code>
+     * </li>
+     * <li>    Fifth step: get the certificate that contains the public key for
+     * the    public key algorithm that will encrypt the generated symmetric
+     * (session) key. Up to now we support RSA 1-5 as public key
+     * algorithm.
+     * </li>
+     * <li>    Sixth step: setup the <code>wsse:Security</code> header block </li>
+     * </ul>
+     *
+     * @param doc    the SOAP envelope as <code>Document</code> with
+     *               plaintext Body
+     * @param crypto an instance of the Crypto API to handle keystore and
+     *               Certificates
+     * @return the SOAP envelope with encrypted Body as <code>Document
+     *         </code>
+     * @throws WSSecurityException
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#build(Document, Crypto, WSSecHeader)}
+     */
+    public Document build(Document doc, Crypto crypto) throws WSSecurityException {
+        doDebug = log.isDebugEnabled();
+
+        if (keyIdentifierType == WSConstants.EMBEDDED_KEYNAME ||
+            keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
+            return buildEmbedded(doc);
+        }
+
+        long t0 = 0, t1 = 0, t2 = 0, t3 = 0;
+        if (tlog.isDebugEnabled()) {
+            t0 = System.currentTimeMillis();
+        }
+        if (doDebug) {
+            log.debug("Beginning Encryption...");
+        }
+
+        /*
+         * Second step: generate a symmetric key (session key) for
+         * this alogrithm, and set the cipher into encryption mode.
+         */
+        // This variable is made a classs attribute :: SecretKey symmetricKey = null;
+        this.encryptionKey = this.symmetricKey;
+        if (encryptionKey == null) {
+            KeyGenerator keyGen = getKeyGenerator();
+            this.encryptionKey = keyGen.generateKey();
+        }
+        Vector encDataRefs = doEncryption(doc, this.encryptionKey);
+
+        if (tlog.isDebugEnabled()) {
+            t1 = System.currentTimeMillis();
+        }
+
+        /*
+         * At this point data is encrypted with the symmetric key and can be
+         * referenced via the above Id
+         */
+
+        /*
+         * Fifth step: get the certificate that contains the public key for the
+         * public key algorithm that will encrypt
+         * the generated symmetric (session) key.
+         * Up to now we support RSA 1-5 as public key algorithm
+         */
+        X509Certificate remoteCert = null;
+        if (useThisCert != null) {
+            remoteCert = useThisCert;
+        } else {
+            X509Certificate[] certs = crypto.getCertificates(user);
+            if (certs == null || certs.length <= 0) {
+                throw new WSSecurityException(
+                    WSSecurityException.FAILURE,
+                    "noUserCertsFound", 
+                    new Object[] { user, "encryption" }
+                );
+            }
+            remoteCert = certs[0];
+        }
+        String certUri = "EncCertId-" + remoteCert.hashCode();
+        if (tlog.isDebugEnabled()) {
+            t2 = System.currentTimeMillis();
+        }
+        Cipher cipher = WSSecurityUtil.getCipherInstance(keyEncAlgo);
+        try {
+            cipher.init(Cipher.ENCRYPT_MODE, remoteCert);
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e);
+        }
+        byte[] encKey = this.encryptionKey.getEncoded();
+        if (doDebug) {
+            log.debug("cipher blksize: "
+                    + cipher.getBlockSize()
+                    + ", symm key length: "
+                    + encKey.length);
+        }
+        if (cipher.getBlockSize() < encKey.length) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unsupportedKeyTransp",
+                    new Object[]{"public key algorithm too weak to encrypt symmetric key"});
+        }
+        byte[] encryptedKey = null;
+        try {
+            encryptedKey = cipher.doFinal(encKey);
+        } catch (IllegalStateException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e1);
+        } catch (IllegalBlockSizeException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e1);
+        } catch (BadPaddingException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e1);
+        }
+        Text keyText =
+                WSSecurityUtil.createBase64EncodedTextNode(doc, encryptedKey);
+
+        /*
+         * Now we need to setup the wsse:Security header block
+         * 1) get (or create) the wsse:Security header block
+         * 2) create the xenc:EncryptedKey element. This already includes
+         *    the ExcrpytionMethod element with attributes that define
+         *    the key transport encryption algorithm
+         * 3) Generate ds:KeyInfo element, this wraps the wsse:SecurityTokenReference
+         * 4) set up the SecurityTokenReference, either with KeyIdentifier or
+         *    X509IssuerSerial. The SecTokenRef defines how to get to security
+         *    token used to encrypt the session key (this security token usually
+         *    contains a public key)
+         * 5) Create the CipherValue element structure and insert the encrypted
+         *    session key
+         * 6) The last step sets up the reference list that pints to the encrypted
+         *    data that was encrypted with this encrypted session key :-)
+         */
+        Element wsseSecurity = insertSecurityHeader(doc);
+        Element xencEncryptedKey = createEncryptedKey(doc, keyEncAlgo);
+        if (parentNode == null) {
+            WSSecurityUtil.prependChildElement(doc,
+                    wsseSecurity,
+                    xencEncryptedKey,
+                    true);
+        } else {
+            WSSecurityUtil.prependChildElement(doc,
+                    parentNode,
+                    xencEncryptedKey,
+                    true);
+        }
+        SecurityTokenReference secToken = new SecurityTokenReference(doc);
+
+        switch (keyIdentifierType) {
+            case WSConstants.X509_KEY_IDENTIFIER:
+                secToken.setKeyIdentifier(remoteCert);
+                // build a key id class??
+                break;
+
+            case WSConstants.SKI_KEY_IDENTIFIER:
+                secToken.setKeyIdentifierSKI(remoteCert, crypto);
+                break;
+                
+            case WSConstants.THUMBPRINT_IDENTIFIER:
+                secToken.setKeyIdentifierThumb(remoteCert);
+                break;
+
+            case WSConstants.ISSUER_SERIAL:
+                XMLX509IssuerSerial data = new XMLX509IssuerSerial(doc, remoteCert);
+                X509Data x509Data = new X509Data(doc); 
+                x509Data.add(data);
+                secToken.setX509IssuerSerial(x509Data);                
+                break;
+
+            case WSConstants.BST_DIRECT_REFERENCE:
+                Reference ref = new Reference(doc);
+                ref.setURI("#" + certUri);
+                BinarySecurity bstToken = null;
+                bstToken = new X509Security(doc);
+                ((X509Security) bstToken).setX509Certificate(remoteCert);
+                bstToken.setID(certUri);
+                ref.setValueType(bstToken.getValueType());
+                secToken.setReference(ref);
+                WSSecurityUtil.prependChildElement(doc,
+                        wsseSecurity,
+                        bstToken.getElement(),
+                        false);
+                break;
+
+            default :
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "unsupportedKeyId");
+        }
+        KeyInfo keyInfo = new KeyInfo(doc);
+        keyInfo.addUnknownElement(secToken.getElement());
+        WSSecurityUtil.appendChildElement(
+                doc, xencEncryptedKey, keyInfo.getElement());
+
+        Element xencCipherValue = createCipherValue(doc, xencEncryptedKey);
+        xencCipherValue.appendChild(keyText);
+        createDataRefList(doc, xencEncryptedKey, encDataRefs);
+        log.debug("Encryption complete.");
+        if (tlog.isDebugEnabled()) {
+            t3 = System.currentTimeMillis();
+            tlog.debug("EncryptBody: symm-enc "
+                    + (t1 - t0)
+                    + " cert "
+                    + (t2 - t1)
+                    + " key-encrypt "
+                    + (t3 - t2));
+        }
+        return doc;
+    }
+
+    private Vector doEncryption(Document doc, SecretKey encryptKey)
+        throws WSSecurityException {
+        return doEncryption(doc, encryptKey, null);
+    }
+
+    private Vector doEncryption(Document doc,
+                                SecretKey encryptKey,
+                                KeyInfo keyInfo)
+            throws WSSecurityException {
+        /*
+         * First step: set the encryption encoding namespace in the SOAP:Envelope
+         */
+        Element envelope = doc.getDocumentElement();
+        envelope.setAttributeNS(WSConstants.XMLNS_NS,
+                "xmlns:" + WSConstants.ENC_PREFIX,
+                WSConstants.ENC_NS);
+
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+
+        XMLCipher xmlCipher = null;
+        try {
+            xmlCipher = XMLCipher.getInstance(symEncAlgo);
+        } catch (XMLEncryptionException e3) {
+            throw new WSSecurityException(WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
+        }
+
+        // if no encryption parts set - use the default
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP =
+                    new WSEncryptionPart(soapConstants.getBodyQName().getLocalPart(),
+                            soapConstants.getEnvelopeURI(),
+                            "Content");
+            parts.add(encP);
+        }
+
+        Vector encDataRefs = new Vector();
+
+        for (int part = 0; part < parts.size(); part++) {
+            WSEncryptionPart encPart = (WSEncryptionPart) parts.get(part);
+            String elemName = encPart.getName();
+            String nmSpace = encPart.getNamespace();
+            String modifier = encPart.getEncModifier();
+            /*
+             * Third step: get the data to encrypt.
+             */
+            Element body =
+                    (Element) WSSecurityUtil.findElement(envelope,
+                            elemName,
+                            nmSpace);
+            if (body == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noEncElement",
+                        new Object[]{"{" + nmSpace + "}" + elemName});
+            }
+
+            boolean content = modifier.equals("Content") ? true : false;
+            String xencEncryptedDataId = "EncDataId-" + body.hashCode();
+
+            /*
+             * Forth step: encrypt data, and set neccessary attributes in
+             * xenc:EncryptedData
+             */
+            try {
+                xmlCipher.init(XMLCipher.ENCRYPT_MODE, encryptKey);
+                EncryptedData encData = xmlCipher.getEncryptedData();
+                encData.setId(xencEncryptedDataId);
+                encData.setKeyInfo(keyInfo);
+                xmlCipher.doFinal(doc, body, content);
+            } catch (Exception e2) {
+                throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION, null, null, e2);
+            }
+            encDataRefs.add(new String("#" + xencEncryptedDataId));
+        }
+        return encDataRefs;
+    }
+
+    private Document buildEmbedded(Document doc)
+            throws WSSecurityException {
+        doDebug = log.isDebugEnabled();
+
+        long t0 = 0, t1 = 0;
+        if (tlog.isDebugEnabled()) {
+            t0 = System.currentTimeMillis();
+        }
+        if (doDebug) {
+            log.debug("Beginning Encryption embedded...");
+        }
+
+
+        /*
+         * Second step: generate a symmetric key from the specified
+         * key (password) for this algorithm, and set the cipher into
+         * encryption mode.
+         */
+        this.encryptionKey = this.symmetricKey;
+        if (this.encryptionKey == null) {
+            if (embeddedKey == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noKeySupplied");
+            }
+            this.encryptionKey = WSSecurityUtil.prepareSecretKey(
+                    symEncAlgo,
+                    embeddedKey);
+        }
+
+        KeyInfo keyInfo = null;
+        if (this.keyIdentifierType == WSConstants.EMBEDDED_KEYNAME) {
+            keyInfo = new KeyInfo(doc);
+            keyInfo.addKeyName(embeddedKeyName == null ? user : embeddedKeyName);
+        } else if (this.keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
+            /* This means that we want to embed a <wsse:SecurityTokenReference>
+            * into keyInfo element.
+            * If we need this functionality, this.secRef MUST be set before
+            * calling the build(doc, crypto) method.
+            * So if secRef is null then throw an exception.
+            */
+            if (this.securityTokenReference == null) {
+                throw new WSSecurityException(
+                        WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+                        "You must set keyInfo element, if the keyIdentifier " +
+                        "== EMBED_SECURITY_TOKEN_REF");
+            } else {
+                keyInfo = new KeyInfo(doc);
+                Element tmpE = securityTokenReference.getElement();
+                tmpE.setAttributeNS(WSConstants.XMLNS_NS,
+                        "xmlns:" + tmpE.getPrefix(),
+                        tmpE.getNamespaceURI());
+                keyInfo.addUnknownElement(securityTokenReference.getElement());
+            }
+        }
+
+        Vector encDataRefs = doEncryption(doc, this.encryptionKey, keyInfo);
+
+        /*
+         * At this point data is encrypted with the symmetric key and can be
+         * referenced via the above Id
+         */
+
+        /*
+         * Now we need to setup the wsse:Security header block
+         * 1) get (or create) the wsse:Security header block
+         * 2) The last step sets up the reference list that pints to the encrypted
+         *    data that was encrypted with this encrypted session key :-)
+         */
+        Element wsseSecurity = insertSecurityHeader(doc);
+
+        Element tmpE = doc.createElement("temp");
+        Element refList = createDataRefList(doc, tmpE, encDataRefs);
+        WSSecurityUtil.prependChildElement(doc, wsseSecurity, refList, true);
+
+        if (tlog.isDebugEnabled()) {
+            tlog.debug("EncryptBody embedded: symm-enc " + (t1 - t0));
+        }
+        return doc;
+    }
+
+    private KeyGenerator getKeyGenerator() throws WSSecurityException {
+        KeyGenerator keyGen = null;
+        try {
+            /*
+             * Assume AES as default, so initialize it
+             */
+            keyGen = KeyGenerator.getInstance("AES");
+            if (symEncAlgo.equalsIgnoreCase(WSConstants.TRIPLE_DES)) {
+                keyGen = KeyGenerator.getInstance("DESede");
+            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_128)) {
+                keyGen.init(128);
+            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_192)) {
+                keyGen.init(192);
+            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_256)) {
+                keyGen.init(256);
+            } else {
+                return null;
+            }
+        } catch (NoSuchAlgorithmException e) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
+        }
+        return keyGen;
+    }
+
+    /**
+     * Create DOM subtree for <code>xenc:EncryptedKey</code>
+     * 
+     * @param doc
+     *            the SOAP envelope parent document
+     * @param keyTransportAlgo
+     *            specifies which algorithm to use to encrypt the symmetric key
+     * @return an <code>xenc:EncryptedKey</code> element
+     */
+    public static Element createEncryptedKey(Document doc, String keyTransportAlgo) {
+        Element encryptedKey =
+                doc.createElementNS(WSConstants.ENC_NS,
+                        WSConstants.ENC_PREFIX + ":EncryptedKey");
+
+        WSSecurityUtil.setNamespace(encryptedKey,
+                WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX);
+        Element encryptionMethod =
+                doc.createElementNS(WSConstants.ENC_NS,
+                        WSConstants.ENC_PREFIX + ":EncryptionMethod");
+        encryptionMethod.setAttributeNS(null, "Algorithm", keyTransportAlgo);
+        WSSecurityUtil.appendChildElement(doc, encryptedKey, encryptionMethod);
+        return encryptedKey;
+    }
+    
+    /**
+     * Create DOM subtree for <code>xenc:EncryptedKey</code>
+     * 
+     * @param doc
+     *            the SOAP envelope parent document
+     * @param keyTransportAlgo
+     *            specifies which algorithm to use to encrypt the symmetric key
+     * @return an <code>xenc:EncryptedKey</code> element
+     * @deprecated use createEncryptedKey(Document doc, String keyTransportAlgo) instead
+     */
+    public static Element createEnrcyptedKey(Document doc, String keyTransportAlgo) {
+        return createEncryptedKey(doc, keyTransportAlgo);
+    }
+
+    public static Element createCipherValue(Document doc,
+                                            Element encryptedKey) {
+        Element cipherData =
+                doc.createElementNS(WSConstants.ENC_NS,
+                        WSConstants.ENC_PREFIX + ":CipherData");
+        Element cipherValue =
+                doc.createElementNS(WSConstants.ENC_NS,
+                        WSConstants.ENC_PREFIX + ":CipherValue");
+        cipherData.appendChild(cipherValue);
+        WSSecurityUtil.appendChildElement(doc, encryptedKey, cipherData);
+        return cipherValue;
+    }
+
+    public static Element createDataRefList(Document doc,
+                                            Element encryptedKey,
+                                            Vector encDataRefs) {
+        Element referenceList =
+                doc.createElementNS(WSConstants.ENC_NS,
+                        WSConstants.ENC_PREFIX + ":ReferenceList");
+        for (int i = 0; i < encDataRefs.size(); i++) {
+            String dataReferenceUri = (String) encDataRefs.get(i);
+            Element dataReference =
+                    doc.createElementNS(WSConstants.ENC_NS,
+                            WSConstants.ENC_PREFIX + ":DataReference");
+            dataReference.setAttributeNS(null, "URI", dataReferenceUri);
+            referenceList.appendChild(dataReference);
+        }
+        WSSecurityUtil.appendChildElement(doc, encryptedKey, referenceList);
+        return referenceList;
+    }
+
+    /**
+     * Sets the parent node of the EncryptedKeyElement
+     *
+     * @param element
+     * @deprecated
+     */
+    public void setParentNode(Element element) {
+        parentNode = element;
+    }
+
+    /**
+     * @return TODO
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#getSymmetricKey()}
+     */
+    public SecretKey getSymmetricKey() {
+        return symmetricKey;
+    }
+
+    /**
+     * Set the symmetric key to be used for encryption
+     * @param key
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#setSymmetricKey(SecretKey)}
+     */
+    public void setSymmetricKey(SecretKey key) {
+        this.symmetricKey = key;
+    }
+
+    /**
+     * Get the symmetric key used for encryption. This may be the same as
+     * the symmetric key field.
+     *
+     * @return The symmetric key
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#getEncryptedEphemeralKey()}
+     */
+    public SecretKey getEncryptionKey() {
+        return this.encryptionKey;
+    }
+
+    /**
+     * @return TODO
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#getSecurityTokenReference()}
+     */
+    public SecurityTokenReference getSecurityTokenReference() {
+        return securityTokenReference;
+    }
+
+    /**
+     * @param reference
+     * @deprecated replaced by
+     *             {@link WSSecEncrypt#setSecurityTokenReference(SecurityTokenReference)}
+     */
+    public void setSecurityTokenReference(SecurityTokenReference reference) {
+        securityTokenReference = reference;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSAddSAMLToken.java b/trunk/src/org/apache/ws/security/message/WSSAddSAMLToken.java
new file mode 100644
index 0000000..a60f31c
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSAddSAMLToken.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.opensaml.SAMLAssertion;
+import org.opensaml.SAMLException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Builds a WS SAML Assertion and inserts it into the SOAP Envelope. Refer to
+ * the WS specification, SAML Token profile
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class WSSAddSAMLToken extends WSBaseMessage {
+
+    private static Log log = LogFactory.getLog(WSSAddSAMLToken.class.getName());
+
+    /**
+     * Constructor.
+     * 
+     * @deprecated replaced by {@link WSSecSAMLToken#WSSecSAMLToken()}
+     */
+    public WSSAddSAMLToken() {
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param actor the name of the actor of the <code>wsse:Security</code>
+     *              header
+     * @deprecated replaced by {@link WSSecSAMLToken#WSSecSAMLToken()}
+     *             and {@link WSSecHeader} for actor specification.
+     */
+    public WSSAddSAMLToken(String actor) {
+        super(actor);
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param actor The name of the actor of the <code>wsse:Security</code>
+     *              header
+     * @param mu    Set <code>mustUnderstand</code> to true or false
+     * 
+     * @deprecated replaced by {@link WSSecSAMLToken#WSSecSAMLToken()}
+     *             and {@link WSSecHeader} for actor and mustunderstand
+     *             specification.
+     */
+    public WSSAddSAMLToken(String actor, boolean mu) {
+        super(actor, mu);
+    }
+
+    /**
+     * Adds a new <code>SAMLAssertion</code> to a soap envelope.
+     * <p/>
+     * A complete <code>SAMLAssertion</code> is added to the
+     * <code>wsse:Security</code> header.
+     *
+     * @param doc      The SOAP enevlope as W3C document
+     * @param assertion TODO
+     * @return Document with UsernameToken added
+     * @deprecated replaced by {@link WSSecSAMLToken#build(Document, SAMLAssertion, WSSecHeader)}
+     */
+    public Document build(Document doc, SAMLAssertion assertion) {
+        log.debug("Begin add SAMLAssertion token...");
+        try {
+            Element element = (Element) assertion.toDOM(doc);
+            Element securityHeader = insertSecurityHeader(doc);
+            WSSecurityUtil.prependChildElement(doc,
+                    securityHeader,
+                    element,
+                    true);
+        } catch (SAMLException ex) {
+            if (log.isDebugEnabled()) {
+                log.debug(ex.getMessage(), ex);
+            }
+            throw new RuntimeException(ex.toString(), ex);
+        }
+        return doc;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSAddUsernameToken.java b/trunk/src/org/apache/ws/security/message/WSSAddUsernameToken.java
new file mode 100644
index 0000000..d13bfb5
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSAddUsernameToken.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Builds a WS UsernameToken and inserts it into the SOAP Envelope.
+ * Refer to the WS specification, UsernameToken profile
+ *
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com).
+ */
+
+public class WSSAddUsernameToken extends WSBaseMessage {
+    private static Log log = LogFactory.getLog(WSSAddUsernameToken.class.getName());
+    private String passwordType = WSConstants.PASSWORD_DIGEST;
+
+    private UsernameToken ut = null;
+    private String id = null;
+    
+    /**
+     * Constructor.
+     * 
+     * @deprecated replaced by {@link WSSecUsernameToken#WSSecUsernameToken()}
+     */
+    public WSSAddUsernameToken() {
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param actor the name of the actor of the <code>wsse:Security</code> header
+     * @deprecated replaced by {@link WSSecUsernameToken#WSSecUsernameToken()}
+     *             and {@link WSSecHeader} for actor specification.
+     */
+    public WSSAddUsernameToken(String actor) {
+        super(actor);
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param actor The name of the actor of the <code>wsse:Security</code> header
+     * @param mu    Set <code>mustUnderstand</code> to true or false
+     * @deprecated replaced by {@link WSSecUsernameToken#WSSecUsernameToken()}
+     *             and {@link WSSecHeader} for actor and mustunderstand
+     *             specification.
+     */
+    public WSSAddUsernameToken(String actor, boolean mu) {
+        super(actor, mu);
+    }
+
+    /**
+     * Defines how to construct the password element of the
+     * <code>UsernameToken</code>.
+     *
+     * @param pwType contains the password type. Only allowed values are
+     *               {@link WSConstants#PASSWORD_DIGEST} and
+     *               {@link WSConstants#PASSWORD_TEXT}.
+     * @deprecated replaced by {@link WSSecUsernameToken#setPasswordType(String)}
+     */
+    public void setPasswordType(String pwType) {
+        if (pwType == null) {
+            passwordType = WSConstants.PASSWORD_DIGEST;
+        } else if (pwType.equals(WSConstants.PASSWORD_DIGEST) || pwType.equals(WSConstants.PASSWORD_TEXT)) {
+            passwordType = pwType;
+        }
+    }
+
+    /**
+     * Creates and adds a Nonce element to the UsernameToken.
+     * @deprecated replaced by {@link WSSecUsernameToken#addNonce()}
+     */
+    public void addNonce(Document doc) {
+        ut.addNonce(doc);
+    }
+
+    /**
+     * Creates and adds a Created element to the UsernameToken.
+     * @deprecated replaced by {@link WSSecUsernameToken#addCreated()}
+     */
+    public void addCreated(Document doc) {
+        ut.addCreated(wssConfig.isPrecisionInMilliSeconds(), doc);
+    }
+
+    /**
+     * set the id
+     * @param id
+     * @deprecated no replacement, id is created by default in
+     *             {@link WSSecUsernameToken}
+     */ 
+    public void setId(String id) {
+        this.id = id;
+        if (ut != null)
+            ut.setID(id);
+    }
+
+    /**
+     * Get a secret key derived from values in UsernameToken.
+     * @return a secret key
+     * @deprecated replaced by {@link WSSecUsernameToken#getSecretKey()}
+     */
+    public byte[] getSecretKey() {
+        return ut.getSecretKey();
+    }
+    /**
+     * get the id
+     * @return The id
+     * @deprecated replaced by {@link WSSecUsernameToken#getId()}
+     */ 
+    public String getId() {
+        return id;
+    }
+
+    public Document preSetUsernameToken(Document doc, String username, String password) {
+        ut = new UsernameToken(wssConfig.isPrecisionInMilliSeconds(), doc, passwordType);
+        ut.setName(username);
+        ut.setPassword(password);
+        return doc;
+    }
+    /**
+     * Adds a new <code>UsernameToken</code> to a soap envelope.
+     * <p/>
+     * A complete <code>UsernameToken</code> is constructed and added to
+     * the <code>wsse:Security</code> header.
+     *
+     * @param doc      The SOAP envelope as W3C document
+     * @param username The username to set in the UsernameToken
+     * @param password The password of the user
+     * @return Document with UsernameToken added
+     * @deprecated replaced by
+     *             {@link WSSecUsernameToken#build(Document, WSSecHeader)} and
+     *             {@link WSSecBase#setUserInfo(String, String)}
+     */
+    public Document build(Document doc, String username, String password) { // throws Exception {
+        log.debug("Begin add username token...");
+        Element securityHeader = insertSecurityHeader(doc);
+        if (ut == null) {
+            preSetUsernameToken(doc, username, password);
+        }
+        if (id != null)
+            ut.setID(id);
+        WSSecurityUtil.prependChildElement(doc, securityHeader, ut.getElement(), true);
+        return doc;
+    }
+
+}
+
diff --git a/trunk/src/org/apache/ws/security/message/WSSecBase.java b/trunk/src/org/apache/ws/security/message/WSSecBase.java
new file mode 100644
index 0000000..d0e9825
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecBase.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.util.Vector;
+
+/**
+ * This is the base class for WS Security messages. It provides common functions
+ * and fields used by the specific message classes such as sign, encrypt, and
+ * username token.
+ * 
+ * @author Werner Dittmann (Werner.Dittmann@apache.org)
+ */
+public class WSSecBase {
+    protected String user = null;
+
+    protected String password = null;
+
+    protected int keyIdentifierType = WSConstants.ISSUER_SERIAL;
+
+    protected Vector parts = null;
+
+    protected boolean doDebug = false;
+
+    protected WSSConfig wssConfig = WSSConfig.getDefaultWSConfig();
+
+    /**
+     * Constructor.
+     */
+    public WSSecBase() {
+    }
+
+    /**
+     * Set which parts of the message to encrypt/sign. <p/>
+     * 
+     * @param parts
+     *            The vector containing the WSEncryptionPart objects
+     */
+    public void setParts(Vector parts) {
+        this.parts = parts;
+    }
+
+    /**
+     * Sets which key identifier to use. 
+     * 
+     * <p/> 
+     * 
+     * Defines the key identifier type to
+     * use in the {@link WSSecSignature#prepare(Document, Crypto, WSSecHeader) method} or
+     * the {@link WSSecEncrypt#prepare(Document, Crypto) method} function to
+     * set up the key identification elements.
+     * 
+     * @param keyIdType
+     * @see WSConstants#ISSUER_SERIAL
+     * @see WSConstants#BST_DIRECT_REFERENCE
+     * @see WSConstants#X509_KEY_IDENTIFIER
+     * @see WSConstants#SKI_KEY_IDENTIFIER
+     */
+    public void setKeyIdentifierType(int keyIdType) {
+        keyIdentifierType = keyIdType;
+    }
+
+    /**
+     * Gets the value of the <code>keyIdentifyerType</code>.
+     * 
+     * @return The <code>keyIdentifyerType</code>.
+     * @see WSConstants#ISSUER_SERIAL
+     * @see WSConstants#BST_DIRECT_REFERENCE
+     * @see WSConstants#X509_KEY_IDENTIFIER
+     * @see WSConstants#SKI_KEY_IDENTIFIER
+     */
+    public int getKeyIdentifierType() {
+        return keyIdentifierType;
+    }
+
+    /**
+     * @param wsConfig
+     *            The wsConfig to set.
+     */
+    public void setWsConfig(WSSConfig wsConfig) {
+        this.wssConfig = wsConfig;
+    }
+
+    /**
+     * Looks up or adds a body id. <p/> First try to locate the
+     * <code>wsu:Id</code> in the SOAP body element. If one is found, the
+     * value of the <code>wsu:Id</code> attribute is returned. Otherwise the
+     * method generates a new <code>wsu:Id</code> and an appropriate value.
+     * 
+     * @param doc
+     *            The SOAP envelope as <code>Document</code>
+     * @return The value of the <code>wsu:Id</code> attribute of the SOAP body
+     * @throws Exception
+     */
+    protected String setBodyID(Document doc) throws Exception {
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+        Element bodyElement = (Element) WSSecurityUtil.getDirectChild(doc
+                .getFirstChild(), soapConstants.getBodyQName().getLocalPart(),
+                soapConstants.getEnvelopeURI());
+        if (bodyElement == null) {
+            throw new Exception("SOAP Body Element node not found");
+        }
+        return setWsuId(bodyElement);
+    }
+
+    protected String setWsuId(Element bodyElement) {
+        String id = null;
+        id = bodyElement.getAttributeNS(WSConstants.WSU_NS, "Id");
+
+        if ((id == null) || (id.length() == 0)) {
+            id = "id-" + Integer.toString(bodyElement.hashCode());
+            String prefix = WSSecurityUtil.setNamespace(bodyElement,
+                    WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+            bodyElement.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+        }
+        return id;
+    }
+
+    /**
+     * Set the user and password info. 
+     * 
+     * Both information is used to get the user's private signing key.
+     * 
+     * @param user
+     *            This is the user's alias name in the keystore that identifies
+     *            the private key to sign the document
+     * @param password
+     *            The user's password to get the private signing key from the
+     *            keystore
+     */
+    public void setUserInfo(String user, String password) {
+        this.user = user;
+        this.password = password;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java b/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java
new file mode 100644
index 0000000..2d68f1a
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecDKEncrypt.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.conversation.ConversationException;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.EncryptedData;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.crypto.SecretKey;
+
+import java.util.Vector;
+
+/**
+ * Encrypts and signs parts of a message with derived keys derived from a
+ * symmetric key. This symmetric key will be included as an EncryptedKey
+ * 
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public class WSSecDKEncrypt extends WSSecDerivedKeyBase {
+
+    protected String symEncAlgo = WSConstants.AES_128;
+    
+    public Document build(Document doc, WSSecHeader secHeader)
+            throws WSSecurityException, ConversationException {
+        
+        /*
+         * Setup the encrypted key
+         */
+        prepare(doc);
+        
+        this.envelope =  doc.getDocumentElement();
+        /*
+         * prepend elements in the right order to the security header
+         */
+        prependDKElementToHeader(secHeader);
+                
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+        Element externRefList = encryptForExternalRef(null, parts);
+        addExternalRefElement(externRefList, secHeader);
+
+        return doc;
+    }
+
+    private Vector doEncryption(Document doc, byte[] secretKey, Vector references) throws WSSecurityException {
+
+        SecretKey key = WSSecurityUtil.prepareSecretKey(this.symEncAlgo, secretKey);
+        
+        
+        XMLCipher xmlCipher = null;
+        try {
+            xmlCipher = XMLCipher.getInstance(symEncAlgo);
+        } catch (XMLEncryptionException e3) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
+        }
+
+        Vector encDataRefs = new Vector();
+        
+        if(envelope == null) {
+            envelope = doc.getDocumentElement();
+        }
+        
+        for (int part = 0; part < references.size(); part++) {
+            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
+
+            String idToEnc = encPart.getId();
+            
+            String elemName = encPart.getName();
+            String nmSpace = encPart.getNamespace();
+            String modifier = encPart.getEncModifier();
+            /*
+             * Third step: get the data to encrypt.
+             */
+            Element body = null;
+            if (idToEnc != null) {
+                body = WSSecurityUtil.findElementById(document
+                        .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
+                if (body == null) {
+                    body = WSSecurityUtil.findElementById(document
+                            .getDocumentElement(), idToEnc, null);
+                }
+            } else {
+                body = (Element) WSSecurityUtil.findElement(envelope, elemName,
+                        nmSpace);
+            }
+            if (body == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noEncElement", new Object[] { "{" + nmSpace + "}"
+                                + elemName });
+            }
+
+            boolean content = modifier.equals("Content") ? true : false;
+            String xencEncryptedDataId = "EncDataId-" + body.hashCode();
+
+            /*
+             * Forth step: encrypt data, and set necessary attributes in
+             * xenc:EncryptedData
+             */
+            try {
+                //Create the SecurityTokenRef to the DKT
+                KeyInfo keyInfo = new KeyInfo(document);
+                SecurityTokenReference secToken = new SecurityTokenReference(document);
+                Reference ref = new Reference(document);
+                ref.setURI("#" + dktId);
+                secToken.setReference(ref);
+
+                keyInfo.addUnknownElement(secToken.getElement());
+                Element keyInfoElement = keyInfo.getElement();
+                keyInfoElement.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                        + WSConstants.SIG_PREFIX, WSConstants.SIG_NS);
+
+                xmlCipher.init(XMLCipher.ENCRYPT_MODE, key);
+                EncryptedData encData = xmlCipher.getEncryptedData();
+                encData.setId(xencEncryptedDataId);
+                encData.setKeyInfo(keyInfo);
+                xmlCipher.doFinal(doc, body, content);
+            } catch (Exception e2) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_ENCRYPTION, null, null, e2);
+            }
+            encDataRefs.add(new String("#" + xencEncryptedDataId));
+        }
+        return encDataRefs;
+    }
+    
+    /**
+     * Encrypt one or more parts or elements of the message (external).
+     * 
+     * This method takes a vector of <code>WSEncryptionPart</code> object that
+     * contain information about the elements to encrypt. The method call the
+     * encryption method, takes the reference information generated during
+     * encryption and add this to the <code>xenc:Reference</code> element.
+     * This method can be called after <code>prepare()</code> and can be
+     * called multiple times to encrypt a number of parts or elements.
+     * 
+     * </p>
+     * 
+     * The method generates a <code>xenc:Reference</code> element that <i>must</i>
+     * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
+     * 
+     * </p>
+     * 
+     * If the <code>dataRef</code> parameter is <code>null</code> the method
+     * creates and initializes a new Reference element.
+     * 
+     * @param dataRef
+     *            A <code>xenc:Reference</code> element or <code>null</code>
+     * @param references
+     *            A vector containing WSEncryptionPart objects
+     * @return Returns the updated <code>xenc:Reference</code> element
+     * @throws WSSecurityException
+     */
+    public Element encryptForExternalRef(Element dataRef, Vector references)
+            throws WSSecurityException {
+
+
+        Vector encDataRefs = doEncryption(document, derivedKeyBytes,
+                references);
+        Element referenceList = dataRef;
+        if (referenceList == null) {
+            referenceList = document.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":ReferenceList");
+        }
+        createDataRefList(document, referenceList, encDataRefs);
+        return referenceList;
+    }
+    
+    /**
+     * Adds (prepends) the external Reference element to the Security header.
+     * 
+     * The reference element <i>must</i> be created by the
+     * <code>encryptForExternalRef() </code> method. The method adds the
+     * reference element in the SecurityHeader.
+     * 
+     * @param referenceList
+     *            The external <code>enc:Reference</code> element
+     * @param secHeader
+     *            The security header.
+     */
+    public void addExternalRefElement(Element referenceList, WSSecHeader secHeader) {
+        Node node = dkt.getElement().getNextSibling();
+        if(node == null || (node != null && !(node instanceof Element))) {
+            //If (at this moment) DerivedKeyToken is the LAST element of 
+            //the security header 
+            secHeader.getSecurityHeader().appendChild(referenceList);
+        } else {
+            secHeader.getSecurityHeader().insertBefore(referenceList, node);
+        }
+        
+    }
+
+    public static Element createDataRefList(Document doc,
+            Element referenceList, Vector encDataRefs) {
+        for (int i = 0; i < encDataRefs.size(); i++) {
+            String dataReferenceUri = (String) encDataRefs.get(i);
+            Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":DataReference");
+            dataReference.setAttributeNS(null, "URI", dataReferenceUri);
+            referenceList.appendChild(dataReference);
+        }
+        return referenceList;
+    }
+
+    
+    public void setSymmetricEncAlgorithm(String algo) {
+        symEncAlgo = algo;
+    }
+
+    /**
+     * @see org.apache.ws.security.message.WSSecDerivedKeyBase#getDerivedKeyLength()
+     */
+    protected int getDerivedKeyLength() throws WSSecurityException{
+        return (this.derivedKeyLength > 0) ? this.derivedKeyLength : 
+            WSSecurityUtil.getKeyLength(this.symEncAlgo);
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecDKSign.java b/trunk/src/org/apache/ws/security/message/WSSecDKSign.java
new file mode 100644
index 0000000..232d201
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecDKSign.java
@@ -0,0 +1,488 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSDocInfoStore;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.conversation.ConversationException;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.saml.SAMLUtil;
+import org.apache.ws.security.transform.STRTransform;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.algorithms.SignatureAlgorithm;
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.signature.XMLSignatureException;
+import org.apache.xml.security.transforms.TransformationException;
+import org.apache.xml.security.transforms.Transforms;
+import org.apache.xml.security.transforms.params.InclusiveNamespaces;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xml.security.utils.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ * Builder to sign with derived keys
+ * 
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ * @author Davanum Srinivas (dims@yahoo.com)
+ * @author Werner Dittmann (werner@apache.org)
+ */
+public class WSSecDKSign extends WSSecDerivedKeyBase {
+
+    private static Log log = LogFactory.getLog(WSSecDKSign.class.getName());
+
+    protected String sigAlgo = XMLSignature.ALGO_ID_MAC_HMAC_SHA1;
+
+    protected String canonAlgo = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
+
+    protected byte[] signatureValue = null;
+    
+    private XMLSignature sig = null;
+    
+    private KeyInfo keyInfo = null;
+
+    private String keyInfoUri = null;
+
+    private SecurityTokenReference secRef = null;
+
+    private String strUri = null;
+    
+    private WSDocInfo wsDocInfo;
+
+
+    public Document build(Document doc, WSSecHeader secHeader)
+            throws WSSecurityException, ConversationException {
+        
+        this.prepare(doc, secHeader);
+        
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+        
+        addReferencesToSign(parts, secHeader);
+        
+        this.computeSignature();
+        
+        this.prependSigToHeader(secHeader);
+        /*
+         * prepend elements in the right order to the security header
+         */
+        this.prependDKElementToHeader(secHeader);
+
+        return doc;
+    }
+    
+    public void prepare(Document doc, WSSecHeader secHeader)
+                            throws WSSecurityException, ConversationException {
+        super.prepare(doc);
+        
+        wsDocInfo = new WSDocInfo(doc.hashCode());
+        
+        /*
+         * Get an initialize a XMLSignature element.
+         */
+        if (canonAlgo.equals(WSConstants.C14N_EXCL_OMIT_COMMENTS)) {
+            Element canonElem = XMLUtils.createElementInSignatureSpace(doc,
+                    Constants._TAG_CANONICALIZATIONMETHOD);
+
+            canonElem.setAttributeNS(null, Constants._ATT_ALGORITHM, canonAlgo);
+
+            if (wssConfig.isWsiBSPCompliant()) {
+                Set prefixes = getInclusivePrefixes(secHeader
+                        .getSecurityHeader(), false);
+
+                InclusiveNamespaces inclusiveNamespaces = new InclusiveNamespaces(
+                        doc, prefixes);
+
+                canonElem.appendChild(inclusiveNamespaces.getElement());
+            }
+
+            try {
+                SignatureAlgorithm signatureAlgorithm = new SignatureAlgorithm(
+                        doc, sigAlgo);
+                sig = new XMLSignature(doc, null, signatureAlgorithm
+                        .getElement(), canonElem);
+            } catch (XMLSecurityException e) {
+                log.error("", e);
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e
+                );
+            }
+        } else {
+            try {
+                sig = new XMLSignature(doc, null, sigAlgo, canonAlgo);
+            } catch (XMLSecurityException e) {
+                log.error("", e);
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e
+                );
+            }
+        }
+        
+        sig.addResourceResolver(EnvelopeIdResolver.getInstance());
+        String sigUri = "Signature-" + sig.hashCode();
+        sig.setId(sigUri);
+        
+        keyInfo = sig.getKeyInfo();
+        keyInfoUri = "KeyId-" + keyInfo.hashCode();
+        keyInfo.setId(keyInfoUri);
+        
+        secRef = new SecurityTokenReference(doc);
+        strUri = "STRId-" + secRef.hashCode();
+        secRef.setID(strUri);
+        
+        Reference refUt = new Reference(document);
+        refUt.setURI("#" + this.dktId);
+        secRef.setReference(refUt);
+        
+        keyInfo.addUnknownElement(secRef.getElement());
+    }
+    
+    
+    protected Set getInclusivePrefixes(Element target) {
+        return getInclusivePrefixes(target, true);
+    }
+
+    protected Set getInclusivePrefixes(Element target, boolean excludeVisible) {
+        Set result = new HashSet();
+        Node parent = target;
+        NamedNodeMap attributes;
+        Node attribute;
+        while (!(parent.getParentNode() instanceof Document)) {
+            parent = parent.getParentNode();
+            attributes = parent.getAttributes();
+            for (int i = 0; i < attributes.getLength(); i++) {
+                attribute = attributes.item(i);
+                if (attribute.getNamespaceURI() != null
+                        && attribute.getNamespaceURI().equals(
+                                org.apache.ws.security.WSConstants.XMLNS_NS)) {
+                    if (attribute.getNodeName().equals("xmlns")) {
+                        result.add("#default");
+                    } else {
+                        result.add(attribute.getLocalName());
+                    }
+                }
+            }
+        }
+
+        if (excludeVisible == true) {
+            attributes = target.getAttributes();
+            for (int i = 0; i < attributes.getLength(); i++) {
+                attribute = attributes.item(i);
+                if (attribute.getNamespaceURI() != null
+                        && attribute.getNamespaceURI().equals(
+                                org.apache.ws.security.WSConstants.XMLNS_NS)) {
+                    if (attribute.getNodeName().equals("xmlns")) {
+                        result.remove("#default");
+                    } else {
+                        result.remove(attribute.getLocalName());
+                    }
+                }
+                if (attribute.getPrefix() != null) {
+                    result.remove(attribute.getPrefix());
+                }
+            }
+
+            if (target.getPrefix() == null) {
+                result.remove("#default");
+            } else {
+                result.remove(target.getPrefix());
+            }
+        }
+
+        return result;
+    }
+    
+    /**
+     * This method adds references to the Signature.
+     * 
+     * The added references are signed when calling
+     * <code>computeSignature()</code>. This method can be called several
+     * times to add references as required. <code>addReferencesToSign()</code>
+     * can be called any time after <code>prepare</code>.
+     * 
+     * @param references
+     *            A vector containing <code>WSEncryptionPart</code> objects
+     *            that define the parts to sign.
+     * @param secHeader
+     *            Used to compute namespaces to be inserted by
+     *            InclusiveNamespaces to be WSI compliant.
+     * @throws WSSecurityException
+     */
+    public void addReferencesToSign(Vector references, WSSecHeader secHeader)
+            throws WSSecurityException {
+        Transforms transforms = null;
+
+        Element envel = document.getDocumentElement();
+
+        for (int part = 0; part < references.size(); part++) {
+            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
+
+            String idToSign = encPart.getId();
+
+            String elemName = encPart.getName();
+            String nmSpace = encPart.getNamespace();
+
+            /*
+             * Set up the elements to sign. There are two reserved element
+             * names: "Token" and "STRTransform" "Token": Setup the Signature to
+             * either sign the information that points to the security token or
+             * the token itself. If its a direct reference sign the token,
+             * otherwise sign the KeyInfo Element. "STRTransform": Setup the
+             * ds:Reference to use STR Transform
+             * 
+             */
+            transforms = new Transforms(document);
+            try {
+                if (idToSign != null) {
+                    Element toSignById = WSSecurityUtil.findElementById(
+                            document.getDocumentElement(), idToSign,
+                            WSConstants.WSU_NS);
+                    if (toSignById == null) {
+                        toSignById = WSSecurityUtil.findElementById(document
+                                .getDocumentElement(), idToSign, null);
+                    }
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(document,
+                                        getInclusivePrefixes(toSignById))
+                                        .getElement());
+                    }
+                    sig.addDocument("#" + idToSign, transforms);
+                } else if (elemName.equals("Token")) {
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(document,
+                                        getInclusivePrefixes(keyInfo
+                                                .getElement()))
+                                        .getElement());
+                    }
+                    sig.addDocument("#" + keyInfoUri, transforms);
+                } else if (elemName.equals("STRTransform")) { // STRTransform
+                    Element ctx = createSTRParameter(document);
+                    transforms.addTransform(
+                            STRTransform.implementedTransformURI, ctx);
+                    sig.addDocument("#" + strUri, transforms);
+                } else if (elemName.equals("Assertion")) { // Assertion
+
+                    String id = null;
+                    id = SAMLUtil.getAssertionId(envel, elemName, nmSpace);
+
+                    Element body = (Element) WSSecurityUtil.findElement(
+                            envel, elemName, nmSpace);
+                    if (body == null) {
+                        throw new WSSecurityException(
+                                WSSecurityException.FAILURE, "noEncElement",
+                                new Object[] { nmSpace + ", " + elemName });
+                    }
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(document,
+                                        getInclusivePrefixes(body))
+                                        .getElement());
+                    }
+                    String prefix = WSSecurityUtil.setNamespace(body,
+                            WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+                    body.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+                    sig.addDocument("#" + id, transforms);
+
+                } else {
+                    Element body = (Element) WSSecurityUtil.findElement(
+                            envel, elemName, nmSpace);
+                    if (body == null) {
+                        throw new WSSecurityException(
+                                WSSecurityException.FAILURE, "noEncElement",
+                                new Object[] { nmSpace + ", " + elemName });
+                    }
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(document,
+                                        getInclusivePrefixes(body))
+                                        .getElement());
+                    }
+                    sig.addDocument("#" + setWsuId(body), transforms);
+                }
+            } catch (TransformationException e1) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null,
+                        e1);
+            } catch (XMLSignatureException e1) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null,
+                        e1);
+            }
+        }
+    }
+    
+    protected Element createSTRParameter(Document doc) {
+        Element transformParam = doc.createElementNS(WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX + ":TransformationParameters");
+
+        WSSecurityUtil.setNamespace(transformParam, WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX);
+
+        Element canonElem = doc.createElementNS(WSConstants.SIG_NS,
+                WSConstants.SIG_PREFIX + ":CanonicalizationMethod");
+
+        WSSecurityUtil.setNamespace(canonElem, WSConstants.SIG_NS,
+                WSConstants.SIG_PREFIX);
+
+        canonElem.setAttributeNS(null, "Algorithm",
+                Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+        transformParam.appendChild(canonElem);
+        return transformParam;
+    }
+    
+    
+    /**
+     * Prepends the Signature element to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>.
+     * This allows to insert the Signature element at any position in the
+     * Security header.
+     * 
+     * @param secHeader
+     *            The secHeader that holds the Signature element.
+     */
+    public void prependSigToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader.getSecurityHeader(), sig
+                .getElement(), false);
+    }
+    
+    public void appendSigToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.appendChildElement(document, secHeader.getSecurityHeader(), sig
+                .getElement());
+    }
+    
+    /**
+     * Returns the signature Element.
+     * The method can be called any time after <code>prepare()</code>.
+     * @return the signature element
+     */
+    public Element getSignatureElement() {
+        return this.sig.getElement();
+    }
+    /**
+     * Compute the Signature over the references.
+     * 
+     * After references are set this method computes the Signature for them.
+     * This method can be called any time after the references were set. See
+     * <code>addReferencesToSign()</code>.
+     * 
+     * @throws WSSecurityException
+     */
+    public void computeSignature() throws WSSecurityException {
+        WSDocInfoStore.store(wsDocInfo);
+        try {
+            sig.sign(sig.createSecretKey(derivedKeyBytes));
+            signatureValue = sig.getSignatureValue();
+        } catch (XMLSignatureException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } catch (Exception e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } finally {
+            WSDocInfoStore.delete(wsDocInfo);
+        }
+
+    }
+    
+    /**
+     * @see org.apache.ws.security.message.WSSecDerivedKeyBase#getDerivedKeyLength()
+     */
+    protected int getDerivedKeyLength() throws WSSecurityException {
+        return (this.derivedKeyLength > 0) ? this.derivedKeyLength : 
+            WSSecurityUtil.getKeyLength(this.sigAlgo);
+    }
+    
+    
+    public void setSignatureAlgorithm(String algo) {
+        this.sigAlgo = algo;
+    }
+
+    /**
+     * @return Returns the signatureValue.
+     */
+    public byte[] getSignatureValue() {
+        return signatureValue;
+    }
+    
+    /**
+     * Set the canonicalization method to use.
+     * 
+     * If the canonicalization method is not set then the recommended Exclusive
+     * XML Canonicalization is used by default Refer to WSConstants which
+     * algorithms are supported.
+     * 
+     * @param algo
+     *            Is the name of the signature algorithm
+     * @see WSConstants#C14N_OMIT_COMMENTS
+     * @see WSConstants#C14N_WITH_COMMENTS
+     * @see WSConstants#C14N_EXCL_OMIT_COMMENTS
+     * @see WSConstants#C14N_EXCL_WITH_COMMENTS
+     */
+    public void setSigCanonicalization(String algo) {
+        canonAlgo = algo;
+    }
+
+    /**
+     * Get the canonicalization method.
+     * 
+     * If the canonicalization method was not set then Exclusive XML
+     * Canonicalization is used by default.
+     * 
+     * @return The string describing the canonicalization algorithm.
+     */
+    public String getSigCanonicalization() {
+        return canonAlgo;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecDerivedKeyBase.java b/trunk/src/org/apache/ws/security/message/WSSecDerivedKeyBase.java
new file mode 100644
index 0000000..43b86c9
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecDerivedKeyBase.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.conversation.ConversationConstants;
+import org.apache.ws.security.conversation.ConversationException;
+import org.apache.ws.security.conversation.dkalgo.AlgoFactory;
+import org.apache.ws.security.conversation.dkalgo.DerivationAlgorithm;
+import org.apache.ws.security.message.token.DerivedKeyToken;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.utils.Base64;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Base class for DerivedKey encryption and signature
+ *
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ * @author Davanum Srinivas (dims@yahoo.com)
+ * @author Werner Dittmann (werner@apache.org)
+ */
+public abstract class WSSecDerivedKeyBase extends WSSecBase {
+    
+    protected Document document;
+    
+    /**
+     * Session key used as the secret in key derivation
+     */
+    protected byte[] ephemeralKey;
+     
+    /**
+     * DerivedKeyToken of this builder
+     */
+    protected DerivedKeyToken dkt = null;
+    
+    /**
+     * Raw bytes of the derived key
+     */
+    protected byte[] derivedKeyBytes = null; 
+    
+    /**
+     * wsu:Id of the wsc:DerivedKeyToken
+     */
+    protected String dktId = null;
+    
+
+    /**
+     * Client's label value
+     */
+    protected String clientLabel = ConversationConstants.DEFAULT_LABEL;
+    
+    /**
+     * Service's label value
+     */
+    protected String serviceLabel = ConversationConstants.DEFAULT_LABEL;
+    
+    /**
+     * soap:Envelope element
+     */
+    protected Element envelope = null;
+    
+    /**
+     * The Token identifier of the token that the <code>DerivedKeyToken</code> 
+     * is (or to be) derived from.
+     */
+    protected String tokenIdentifier = null;
+
+    /**
+     * The derived key will change depending on the sig/encr algorithm.
+     * Therefore the child classes are expected to provide this value.
+     * @return the derived key length
+     * @throws WSSecurityException
+     */
+    protected abstract int getDerivedKeyLength() throws WSSecurityException;
+   
+    /**
+     * The wsse:SecurityTokenReference element to be used
+     */
+    protected Element strElem;
+    
+    private int wscVersion = ConversationConstants.DEFAULT_VERSION;
+    
+    protected int derivedKeyLength = -1;
+    
+    private String customValueType;
+    
+    /**
+     * @param ephemeralKey The ephemeralKey to set.
+     */
+    public void setExternalKey(byte[] ephemeralKey, 
+                                String tokenIdentifier) {
+        this.ephemeralKey = ephemeralKey;
+        this.tokenIdentifier = tokenIdentifier;
+    }
+    
+    /**
+     * @param ephemeralKey The ephemeralKey to set.
+     */
+    public void setExternalKey(byte[] ephemeralKey, 
+                                Element strElem) {
+        this.ephemeralKey = ephemeralKey;
+        this.strElem = strElem;
+    }
+    
+    /**
+     * @return Returns the tokenIdentifier.
+     */
+    public String getTokenIdentifier() {
+        return tokenIdentifier;
+    }
+    
+    /**
+     * Get the id generated during <code>prepare()</code>.
+     * 
+     * Returns the the value of wsu:Id attribute of the DerivedKeyToken element.
+     * 
+     * @return Return the wsu:Id of this token or null if <code>prepare()</code>
+     *         was not called before.
+     */
+    public String getId() {
+        return dktId;
+    }
+    
+    /**
+     * Set the label value of the client.
+     * @param clientLabel
+     */    
+    public void setClientLabel(String clientLabel) {
+        this.clientLabel = clientLabel;
+    }
+
+    /**
+     * Set the label value of the service.
+     * @param serviceLabel
+     */
+    public void setServiceLabel(String serviceLabel) {
+        this.serviceLabel = serviceLabel;
+    }
+
+    /**
+     * Initialize a WSSec Derived key.
+     * 
+     * The method prepares and initializes a WSSec derived key structure after the
+     * relevant information was set. This method also creates and initializes the
+     * derived token using the ephemeral key. After preparation references
+     * can be added, encrypted and signed as required.
+     * 
+     * </p>
+     * 
+     * This method does not add any element to the security header. This must be
+     * done explicitly.
+     * 
+     * @param doc
+     *            The unsigned SOAP envelope as <code>Document</code>
+     * @throws WSSecurityException
+     */
+    public void prepare(Document doc)
+        throws WSSecurityException, ConversationException {
+        
+        document = doc;
+
+        //Create the derived keys
+        //At this point figure out the key length accordng to teh symencAlgo
+        int offset = 0;
+        int length = this.getDerivedKeyLength();
+        byte[] label;
+        try {
+            label = (clientLabel + serviceLabel).getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new WSSecurityException("UTF-8 encoding is not supported", e);
+        }
+        byte[] nonce = WSSecurityUtil.generateNonce(16);
+        
+        byte[] seed = new byte[label.length + nonce.length];
+        System.arraycopy(label, 0, seed, 0, label.length);
+        System.arraycopy(nonce, 0, seed, label.length, nonce.length);
+        
+        DerivationAlgorithm algo = AlgoFactory.getInstance(ConversationConstants.DerivationAlgorithm.P_SHA_1);
+        
+        this.derivedKeyBytes = algo.createKey(this.ephemeralKey, seed, offset, length);
+        
+        
+        //Add the DKTs
+        dkt = new DerivedKeyToken(this.wscVersion, document);
+        dktId = "derivedKeyId-" + dkt.hashCode();
+        
+        dkt.setOffset(offset);
+        dkt.setLength(length);
+        dkt.setNonce(Base64.encode(nonce));
+        
+        dkt.setID(dktId);
+        
+        if(this.strElem == null) {
+            //Create the SecurityTokenRef to the Encrypted Key
+            SecurityTokenReference strEncKey = new SecurityTokenReference(document);
+            Reference ref = new Reference(document);
+            ref.setURI("#" + this.tokenIdentifier);
+            if(this.customValueType != null && this.customValueType.trim().length() > 0) {
+                ref.setValueType(this.customValueType);
+            }
+            strEncKey.setReference(ref);
+            dkt.setSecurityTokenReference(strEncKey); 
+        } else {
+            dkt.setSecurityTokenReference(this.strElem);
+        }
+    }
+
+
+
+    /**
+     * Prepend the DerivedKey element to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>. This
+     * allows to insert the DereivedKey element at any position in the Security
+     * header.
+     * 
+     * @param secHeader
+     *            The security header that holds the Signature element.
+     */
+    public void prependDKElementToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader
+            .getSecurityHeader(), dkt.getElement(), false);
+    }
+    
+    public void appendDKElementToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.appendChildElement(document, secHeader
+            .getSecurityHeader(), dkt.getElement());
+    }
+
+    /**
+     * @param wscVersion The wscVersion to set.
+     */
+    public void setWscVersion(int wscVersion) {
+        this.wscVersion = wscVersion;
+    }
+    
+    public Element getdktElement() {
+        return this.dkt.getElement();
+    }
+
+    public void setDerivedKeyLength(int keyLength) {
+        this.derivedKeyLength = keyLength;
+    }
+
+    public void setCustomValueType(String customValueType) {
+        this.customValueType = customValueType;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java b/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java
new file mode 100644
index 0000000..d54805e
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecEncrypt.java
@@ -0,0 +1,776 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.util.Base64;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.EncryptedData;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.Vector;
+
+/**
+ * Encrypts a parts of a message according to WS Specification, X509 profile,
+ * and adds the encryption data.
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com).
+ * @author Werner Dittmann (Werner.Dittmann@apache.org).
+ */
+public class WSSecEncrypt extends WSSecEncryptedKey {
+    private static Log log = LogFactory.getLog(WSSecEncrypt.class.getName());
+
+    protected String symEncAlgo = WSConstants.AES_128;
+
+    protected String encCanonAlgo = null;
+
+    protected byte[] embeddedKey = null;
+
+    protected String embeddedKeyName = null;
+
+    protected boolean useKeyIdentifier;
+
+    /**
+     * Symmetric key used in the EncrytpedKey.
+     */
+    protected SecretKey symmetricKey = null;
+
+    /**
+     * SecurityTokenReference to be inserted into EncryptedData/keyInfo element.
+     */
+    protected SecurityTokenReference securityTokenReference = null;
+
+    /**
+     * Indicates whether to encrypt the symmetric key into an EncryptedKey 
+     * or not.
+     */
+    private boolean encryptSymmKey = true;
+    
+    /**
+     * Custom reference value
+     */
+    private String customReferenceValue;
+
+    /**
+     * Constructor.
+     */
+    public WSSecEncrypt() {
+    }
+
+    /**
+     * Sets the key to use during embedded encryption.
+     * 
+     * <p/>
+     * 
+     * @param key
+     *            to use during encryption. The key must fit the selected
+     *            symmetrical encryption algorithm
+     */
+    public void setKey(byte[] key) {
+        this.embeddedKey = key;
+    }
+
+    /**
+     * Sets the algorithm to encode the symmetric key.
+     * 
+     * Default is the <code>WSConstants.KEYTRANSPORT_RSA15</code> algorithm.
+     * 
+     * @param keyEnc
+     *            specifies the key encoding algorithm.
+     * @see WSConstants#KEYTRANSPORT_RSA15
+     * @see WSConstants#KEYTRANSPORT_RSAOEP
+     */
+    public void setKeyEnc(String keyEnc) {
+        keyEncAlgo = keyEnc;
+    }
+
+    /**
+     * Set the key name for EMBEDDED_KEYNAME
+     * 
+     * @param embeddedKeyName
+     */
+    public void setEmbeddedKeyName(String embeddedKeyName) {
+        this.embeddedKeyName = embeddedKeyName;
+    }
+    
+    /**
+     * Set this true if a key identifier must be used in the KeyInfo
+     * 
+     * @param useKeyIdentifier
+     */
+    public void setUseKeyIdentifier(boolean useKeyIdentifier) {
+        this.useKeyIdentifier = useKeyIdentifier;
+    }
+    
+    /**
+     * Set the name of the symmetric encryption algorithm to use.
+     * 
+     * This encryption algorithm is used to encrypt the data. If the algorithm
+     * is not set then AES128 is used. Refer to WSConstants which algorithms are
+     * supported.
+     * 
+     * @param algo
+     *            Is the name of the encryption algorithm
+     * @see WSConstants#TRIPLE_DES
+     * @see WSConstants#AES_128
+     * @see WSConstants#AES_192
+     * @see WSConstants#AES_256
+     */
+    public void setSymmetricEncAlgorithm(String algo) {
+        symEncAlgo = algo;
+    }
+
+    /**
+     * Set the name of an optional canonicalization algorithm to use before
+     * encryption.
+     * 
+     * This c14n algorithm is used to serialize the data before encryption. If
+     * the algorithm is not set then a standard serialization is used (provided
+     * by XMLCipher, usually a XMLSerializer according to DOM 3 specification).
+     * 
+     * @param algo
+     *            Is the name of the canonicalization algorithm
+     */
+    public void setEncCanonicalization(String algo) {
+        encCanonAlgo = algo;
+    }
+    
+    /**
+     * Get the name of symmetric encryption algorithm to use.
+     * 
+     * The name of the encryption algorithm to encrypt the data, i.e. the SOAP
+     * Body. Refer to WSConstants which algorithms are supported.
+     * 
+     * @return the name of the currently selected symmetric encryption algorithm
+     * @see WSConstants#TRIPLE_DES
+     * @see WSConstants#AES_128
+     * @see WSConstants#AES_192
+     * @see WSConstants#AES_256
+     */
+    public String getSymmetricEncAlgorithm() {
+        return symEncAlgo;
+    }
+    
+    /**
+     * Returns if Key Identifiers should be used in KeyInfo
+     * @return if Key Identifiers should be used in KeyInfo
+     */
+    public boolean getUseKeyIdentifier() {
+        return useKeyIdentifier;
+    }
+    
+    /**
+     * Initialize a WSSec Encrypt.
+     * 
+     * The method prepares and initializes a WSSec Encrypt structure after the
+     * relevant information was set. After preparation of the token references
+     * can be added and encrypted.
+     * 
+     * </p>
+     * 
+     * This method does not add any element to the security header. This must be
+     * done explicitly.
+     * 
+     * @param doc
+     *            The SOAP envelope as <code>Document</code>
+     * @param crypto
+     *            An instance of the Crypto API to handle keystore and
+     *            certificates
+     * @throws WSSecurityException
+     */
+    public void prepare(Document doc, Crypto crypto) throws WSSecurityException {
+
+        document = doc;
+
+        /*
+         * If no external key (symmetricalKey) was set generate an encryption
+         * key (session key) for this Encrypt element. This key will be
+         * encrypted using the public key of the receiver
+         */
+        
+        
+        if(this.ephemeralKey == null) {
+            if (symmetricKey == null) {
+                KeyGenerator keyGen = getKeyGenerator();
+                this.symmetricKey = keyGen.generateKey();
+            } 
+            this.ephemeralKey = this.symmetricKey.getEncoded();
+        }
+        
+        if (this.symmetricKey == null) {
+
+            this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
+                    this.ephemeralKey);
+        }
+        
+        /*
+         * Get the certificate that contains the public key for the public key
+         * algorithm that will encrypt the generated symmetric (session) key.
+         */
+        if(this.encryptSymmKey) {
+            X509Certificate remoteCert = null;
+            if (useThisCert != null) {
+                remoteCert = useThisCert;
+            } else {
+                X509Certificate[] certs = crypto.getCertificates(user);
+                if (certs == null || certs.length <= 0) {
+                    throw new WSSecurityException(
+                        WSSecurityException.FAILURE,
+                        "noUserCertsFound", 
+                        new Object[] { user, "encryption" }
+                    );
+                }
+                remoteCert = certs[0];
+            }
+            prepareInternal(this.ephemeralKey, remoteCert, crypto);
+        }
+    }
+
+    /**
+     * Builds the SOAP envelope with encrypted Body and adds encrypted key.
+     * 
+     * This is a convenience method and for backward compatibility. The method
+     * calls the single function methods in order to perform a <i>one shot
+     * encryption</i>. This method is compatible with the build method of the
+     * previous version with the exception of the additional WSSecHeader
+     * parameter.
+     * 
+     * @param doc
+     *            the SOAP envelope as <code>Document</code> with plain text
+     *            Body
+     * @param crypto
+     *            an instance of the Crypto API to handle keystore and
+     *            Certificates
+     * @param secHeader
+     *            the security header element to hold the encrypted key element.
+     * @return the SOAP envelope with encrypted Body as <code>Document
+     *         </code>
+     * @throws WSSecurityException
+     */
+    public Document build(Document doc, Crypto crypto, WSSecHeader secHeader)
+            throws WSSecurityException {
+        doDebug = log.isDebugEnabled();
+
+        if (keyIdentifierType == WSConstants.EMBEDDED_KEYNAME
+                || keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
+            return buildEmbedded(doc, secHeader);
+        }
+
+        if (doDebug) {
+            log.debug("Beginning Encryption...");
+        }
+
+        prepare(doc, crypto);
+        
+        if (envelope == null) {
+            envelope = document.getDocumentElement();
+        }
+
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+
+        Element refs = encryptForInternalRef(null, parts);
+        addInternalRefElement(refs);
+
+        prependToHeader(secHeader);
+
+        if (bstToken != null) {
+            prependBSTElementToHeader(secHeader);
+        }
+
+        log.debug("Encryption complete.");
+        return doc;
+    }
+
+    /**
+     * Encrypt one or more parts or elements of the message (internal).
+     * 
+     * This method takes a vector of <code>WSEncryptionPart</code> object that
+     * contain information about the elements to encrypt. The method call the
+     * encryption method, takes the reference information generated during
+     * encryption and add this to the <code>xenc:Reference</code> element.
+     * This method can be called after <code>prepare()</code> and can be
+     * called multiple times to encrypt a number of parts or elements.
+     * 
+     * </p>
+     * 
+     * The method generates a <code>xenc:Reference</code> element that <i>must</i>
+     * be added to this token. See <code>addInternalRefElement()</code>.
+     * 
+     * </p>
+     * 
+     * If the <code>dataRef</code> parameter is <code>null</code> the method
+     * creates and initializes a new Reference element.
+     * 
+     * @param dataRef
+     *            A <code>xenc:Reference</code> element or <code>null</code>
+     * @param references
+     *            A vector containing WSEncryptionPart objects
+     * @return Returns the updated <code>xenc:Reference</code> element
+     * @throws WSSecurityException
+     */
+    public Element encryptForInternalRef(Element dataRef, Vector references)
+            throws WSSecurityException {
+        Vector encDataRefs = doEncryption(document, this.symmetricKey,
+                references);
+        Element referenceList = dataRef;
+        if (referenceList == null) {
+            referenceList = document.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":ReferenceList");
+        }
+        createDataRefList(document, referenceList, encDataRefs);
+        return referenceList;
+    }
+
+    /**
+     * Encrypt one or more parts or elements of the message (external).
+     * 
+     * This method takes a vector of <code>WSEncryptionPart</code> object that
+     * contain information about the elements to encrypt. The method call the
+     * encryption method, takes the reference information generated during
+     * encryption and add this to the <code>xenc:Reference</code> element.
+     * This method can be called after <code>prepare()</code> and can be
+     * called multiple times to encrypt a number of parts or elements.
+     * 
+     * </p>
+     * 
+     * The method generates a <code>xenc:Reference</code> element that <i>must</i>
+     * be added to the SecurityHeader. See <code>addExternalRefElement()</code>.
+     * 
+     * </p>
+     * 
+     * If the <code>dataRef</code> parameter is <code>null</code> the method
+     * creates and initializes a new Reference element.
+     * 
+     * @param dataRef
+     *            A <code>xenc:Reference</code> element or <code>null</code>
+     * @param references
+     *            A vector containing WSEncryptionPart objects
+     * @return Returns the updated <code>xenc:Reference</code> element
+     * @throws WSSecurityException
+     */
+    public Element encryptForExternalRef(Element dataRef, Vector references)
+            throws WSSecurityException {
+
+        Vector encDataRefs = doEncryption(document, this.symmetricKey,
+                references);
+        Element referenceList = dataRef;
+        if (referenceList == null) {
+            referenceList = document.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":ReferenceList");
+        }
+        createDataRefList(document, referenceList, encDataRefs);
+        return referenceList;
+    }
+
+    /**
+     * Adds the internal Reference element to this Encrypt data.
+     * 
+     * The reference element <i>must</i> be created by the
+     * <code>encryptForInternalRef()</code> method. The reference element is
+     * added to the <code>EncryptedKey</code> element of this encrypt block.
+     * 
+     * @param dataRef
+     *            The internal <code>enc:Reference</code> element
+     */
+    public void addInternalRefElement(Element dataRef) {
+        WSSecurityUtil.appendChildElement(document, encryptedKeyElement, dataRef);
+    }
+
+    /**
+     * Adds (prepends) the external Reference element to the Security header.
+     * 
+     * The reference element <i>must</i> be created by the
+     * <code>encryptForExternalRef() </code> method. The method prepends the
+     * reference element in the SecurityHeader.
+     * 
+     * @param dataRef
+     *            The external <code>enc:Reference</code> element
+     * @param secHeader
+     *            The security header.
+     */
+    public void addExternalRefElement(Element dataRef, WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader
+                .getSecurityHeader(), dataRef, false);
+    }
+
+    private Vector doEncryption(Document doc, SecretKey secretKey,
+            Vector references) throws WSSecurityException {
+        
+        KeyInfo keyInfo = null;
+        
+        // Prepare KeyInfo if useKeyIdentifier is set
+        if (useKeyIdentifier &&
+            keyIdentifierType == WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER) {
+            keyInfo = new KeyInfo(document);
+            SecurityTokenReference secToken = new SecurityTokenReference(document);
+            if(this.customReferenceValue != null) {
+                secToken.setKeyIdentifierEncKeySHA1(this.customReferenceValue);
+            } else {
+                secToken.setKeyIdentifierEncKeySHA1(getSHA1(encryptedEphemeralKey));
+            }
+            
+            keyInfo.addUnknownElement(secToken.getElement());
+            Element keyInfoElement = keyInfo.getElement();
+            keyInfoElement.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                    + WSConstants.SIG_PREFIX, WSConstants.SIG_NS);
+        } 
+        
+        return doEncryption(doc, secretKey, keyInfo, references);
+    }
+
+    private Vector doEncryption(Document doc, SecretKey secretKey,
+            KeyInfo keyInfo, Vector references) throws WSSecurityException {
+
+        XMLCipher xmlCipher = null;
+        try {
+            xmlCipher = XMLCipher.getInstance(symEncAlgo);
+        } catch (XMLEncryptionException e3) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e3);
+        }
+
+        Vector encDataRef = new Vector();
+
+        boolean cloneKeyInfo = false;
+        for (int part = 0; part < references.size(); part++) {
+            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
+
+            String idToEnc = encPart.getId();
+
+            String elemName = encPart.getName();
+            String nmSpace = encPart.getNamespace();
+            String modifier = encPart.getEncModifier();
+            /*
+             * Third step: get the data to encrypt.
+             * 
+             */
+            Element body = null;
+            if (idToEnc != null) {
+                body = WSSecurityUtil.findElementById(document
+                        .getDocumentElement(), idToEnc, WSConstants.WSU_NS);
+                if (body == null) {
+                    body = WSSecurityUtil.findElementById(document
+                            .getDocumentElement(), idToEnc, null);
+                }
+            } else {
+                body = (Element) WSSecurityUtil.findElement(document, elemName,
+                        nmSpace);
+            }
+            if (body == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noEncElement", new Object[] { "{" + nmSpace + "}"
+                                + elemName });
+            }
+
+            boolean content = modifier.equals("Content") ? true : false;
+            String xencEncryptedDataId = "EncDataId-" + body.hashCode();
+            encPart.setEncId(xencEncryptedDataId);
+
+            cloneKeyInfo = true;
+            
+            if(keyInfo == null) {
+                keyInfo = new KeyInfo(document);
+                SecurityTokenReference secToken = new SecurityTokenReference(document);
+                Reference ref = new Reference(document);
+                ref.setURI("#" + encKeyId);
+                secToken.setReference(ref);
+                keyInfo.addUnknownElement(secToken.getElement());
+                Element keyInfoElement = keyInfo.getElement();
+                keyInfoElement.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                        + WSConstants.SIG_PREFIX, WSConstants.SIG_NS);
+            }
+            /*
+             * Forth step: encrypt data, and set necessary attributes in
+             * xenc:EncryptedData
+             */
+            try {
+                
+                if (modifier.equals("Header")) {
+                    
+                    Element elem = doc.createElementNS(WSConstants.WSSE11_NS,"wsse11:"+WSConstants.ENCRYPTED_HEADER);
+                    WSSecurityUtil.setNamespace(elem, WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
+                    String wsuPrefix = WSSecurityUtil.setNamespace(elem,
+                            WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+                    elem.setAttributeNS(WSConstants.WSU_NS, wsuPrefix + ":Id", "EncHeader-" + body.hashCode());
+                    
+                    
+                    NamedNodeMap map = body.getAttributes();
+                    
+                    for (int i = 0 ; i < map.getLength() ; i++) {
+                        Attr attr = (Attr)map.item(i);
+                        if (attr.getNamespaceURI().equals(WSConstants.URI_SOAP11_ENV)
+                                || attr.getNamespaceURI().equals(WSConstants.URI_SOAP12_ENV)) {                         
+                            String soapEnvPrefix = WSSecurityUtil.setNamespace(elem,
+                                    attr.getNamespaceURI(), "soapevn");
+                            elem.setAttributeNS(attr.getNamespaceURI(), soapEnvPrefix +":"+attr.getLocalName(), attr.getValue());
+                        }
+                    }
+                    
+                    xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
+                    EncryptedData encData = xmlCipher.getEncryptedData();
+                    encData.setId(xencEncryptedDataId);
+                    encData.setKeyInfo(keyInfo);
+                    xmlCipher.doFinal(doc, body, content);
+                    
+                    Element encDataElem = WSSecurityUtil.findElementById(document
+                            .getDocumentElement(), xencEncryptedDataId, null);
+                    Node clone = encDataElem.cloneNode(true);
+                    elem.appendChild(clone);
+                    encDataElem.getParentNode().appendChild(elem);
+                    encDataElem.getParentNode().removeChild(encDataElem); 
+                    
+                } else {
+                    xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
+                    EncryptedData encData = xmlCipher.getEncryptedData();
+                    encData.setId(xencEncryptedDataId);
+                    encData.setKeyInfo(keyInfo);
+                    xmlCipher.doFinal(doc, body, content);          
+                }
+                if(cloneKeyInfo) {
+                    keyInfo = new KeyInfo((Element) keyInfo.getElement()
+                            .cloneNode(true), null);
+                }
+            } catch (Exception e2) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_ENCRYPTION, null, null, e2);
+            }
+            encDataRef.add(new String("#" + xencEncryptedDataId));
+        }
+        return encDataRef;
+    }
+
+    private Document buildEmbedded(Document doc, WSSecHeader secHeader) 
+        throws WSSecurityException {
+        doDebug = log.isDebugEnabled();
+
+        if (doDebug) {
+            log.debug("Beginning Encryption embedded...");
+        }
+        envelope = doc.getDocumentElement();
+        envelope.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                + WSConstants.ENC_PREFIX, WSConstants.ENC_NS);
+
+        /*
+         * Second step: generate a symmetric key from the specified key
+         * (password) for this algorithm, and set the cipher into encryption
+         * mode.
+         */
+        if (this.symmetricKey == null) {
+            if (embeddedKey == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noKeySupplied");
+            }
+            this.symmetricKey = WSSecurityUtil.prepareSecretKey(symEncAlgo,
+                    embeddedKey);
+        }
+
+        KeyInfo keyInfo = null;
+        if (this.keyIdentifierType == WSConstants.EMBEDDED_KEYNAME) {
+            keyInfo = new KeyInfo(doc);
+            keyInfo
+                    .addKeyName(embeddedKeyName == null ? user
+                            : embeddedKeyName);
+        } else if (this.keyIdentifierType == WSConstants.EMBED_SECURITY_TOKEN_REF) {
+            /*
+             * This means that we want to embed a <wsse:SecurityTokenReference>
+             * into keyInfo element. If we need this functionality, this.secRef
+             * MUST be set before calling the build(doc, crypto) method. So if
+             * secRef is null then throw an exception.
+             */
+            if (this.securityTokenReference == null) {
+                throw new WSSecurityException(
+                        WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+                        "You must set keyInfo element, if the keyIdentifier "
+                                + "== EMBED_SECURITY_TOKEN_REF");
+            } else {
+                keyInfo = new KeyInfo(doc);
+                Element tmpE = securityTokenReference.getElement();
+                tmpE.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                        + tmpE.getPrefix(), tmpE.getNamespaceURI());
+                keyInfo.addUnknownElement(securityTokenReference.getElement());
+            }
+        }
+        Element keyInfoElement = keyInfo.getElement();
+        keyInfoElement.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                + WSConstants.SIG_PREFIX, WSConstants.SIG_NS);
+
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+        Vector encDataRefs = doEncryption(doc, this.symmetricKey, keyInfo,
+                parts);
+
+        /*
+         * At this point data is encrypted with the symmetric key and can be
+         * referenced via the above Id
+         */
+
+        /*
+         * Now we need to setup the wsse:Security header block 1) get (or
+         * create) the wsse:Security header block 2) The last step sets up the
+         * reference list that pints to the encrypted data
+         */
+        Element wsseSecurity = secHeader.getSecurityHeader();
+
+        Element referenceList = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":ReferenceList");
+        referenceList = createDataRefList(doc, referenceList, encDataRefs);
+        WSSecurityUtil.prependChildElement(doc, wsseSecurity, referenceList,
+                true);
+
+        return doc;
+    }
+
+    private KeyGenerator getKeyGenerator() throws WSSecurityException {
+        KeyGenerator keyGen = null;
+        try {
+            /*
+             * Assume AES as default, so initialize it
+             */
+            keyGen = KeyGenerator.getInstance("AES");
+            if (symEncAlgo.equalsIgnoreCase(WSConstants.TRIPLE_DES)) {
+                keyGen = KeyGenerator.getInstance("DESede");
+            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_128)) {
+                keyGen.init(128);
+            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_192)) {
+                keyGen.init(192);
+            } else if (symEncAlgo.equalsIgnoreCase(WSConstants.AES_256)) {
+                keyGen.init(256);
+            } else {
+                return null;
+            }
+        } catch (NoSuchAlgorithmException e) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
+        }
+        return keyGen;
+    }
+
+    /**
+     * Create DOM subtree for <code>xenc:EncryptedKey</code>
+     * 
+     * @param doc
+     *            the SOAP envelope parent document
+     * @param referenceList
+     * @param encDataRefs
+     * @return an <code>xenc:EncryptedKey</code> element
+     */
+
+    public static Element createDataRefList(Document doc,
+            Element referenceList, Vector encDataRefs) {
+        for (int i = 0; i < encDataRefs.size(); i++) {
+            String dataReferenceUri = (String) encDataRefs.get(i);
+            Element dataReference = doc.createElementNS(WSConstants.ENC_NS,
+                    WSConstants.ENC_PREFIX + ":DataReference");
+            dataReference.setAttributeNS(null, "URI", dataReferenceUri);
+            referenceList.appendChild(dataReference);
+        }
+        return referenceList;
+    }
+
+    /**
+     * @return The symmetric key
+     */
+    public SecretKey getSymmetricKey() {
+        return symmetricKey;
+    }
+
+    /**
+     * Set the symmetric key to be used for encryption
+     * 
+     * @param key
+     */
+    public void setSymmetricKey(SecretKey key) {
+        this.symmetricKey = key;
+    }
+
+    /**
+     * @return Return the SecurityTokenRefernce
+     */
+    public SecurityTokenReference getSecurityTokenReference() {
+        return securityTokenReference;
+    }
+
+    /**
+     * @param reference
+     */
+    public void setSecurityTokenReference(SecurityTokenReference reference) {
+        securityTokenReference = reference;
+    }
+
+    public boolean isEncryptSymmKey() {
+        return encryptSymmKey;
+    }
+
+    public void setEncryptSymmKey(boolean encryptSymmKey) {
+        this.encryptSymmKey = encryptSymmKey;
+    }
+
+    private String getSHA1(byte[] input) throws WSSecurityException {
+        try {
+            MessageDigest sha = null;
+            sha = MessageDigest.getInstance("SHA-1");
+            sha.reset();
+            sha.update(input);
+            byte[] data = sha.digest();
+            
+            return Base64.encode(data);
+        } catch (NoSuchAlgorithmException e) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
+        }
+    }
+
+    public void setCustomReferenceValue(String customReferenceValue) {
+        this.customReferenceValue = customReferenceValue;
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecEncryptedKey.java b/trunk/src/org/apache/ws/security/message/WSSecEncryptedKey.java
new file mode 100644
index 0000000..7c48f13
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecEncryptedKey.java
@@ -0,0 +1,547 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import java.security.InvalidKeyException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.util.UUIDGenerator;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+/**
+ * Builder class to build an EncryptedKey.
+ * 
+ * This is especially useful in the case where the same
+ * <code>EncryptedKey</code> has to be used to sign and encrypt the message In
+ * such a situation this builder will add the <code>EncryptedKey</code> to the
+ * security header and we can use the information form the builder to provide to
+ * other builders to reference to the token
+ */
+public class WSSecEncryptedKey extends WSSecBase {
+
+    private static Log log = LogFactory.getLog(WSSecEncryptedKey.class
+            .getName());
+
+    protected Document document;
+
+    /**
+     * soap:Envelope element
+     */
+    protected Element envelope = null;
+
+    /**
+     * Session key used as the secret in key derivation
+     */
+    protected byte[] ephemeralKey;
+
+    /**
+     * Encrypted bytes of the ephemeral key
+     */
+    protected byte[] encryptedEphemeralKey;
+    
+    /**
+     * Remote user's alias to obtain the cert to encrypt the ephemeral key
+     */
+    protected String encrUser = null;
+
+    /**
+     * Algorithm used to encrypt the ephemeral key
+     */
+    protected String keyEncAlgo = WSConstants.KEYTRANSPORT_RSA15;
+
+    /**
+     * xenc:EncryptedKey element
+     */
+    protected Element encryptedKeyElement = null;
+
+    /**
+     * The Token identifier of the token that the <code>DerivedKeyToken</code>
+     * is (or to be) derived from.
+     */
+    protected String encKeyId = null;
+
+    /**
+     * BinarySecurityToken to be included in the case where BST_DIRECT_REFERENCE
+     * is used to refer to the asymm encryption cert
+     */
+    protected BinarySecurity bstToken = null;
+    
+    protected X509Certificate useThisCert = null;
+    
+    /**
+     * Key size in bits
+     * Defaults to 128
+     */
+    protected int keySize = 128;
+
+    /**
+     * Set the user name to get the encryption certificate.
+     * 
+     * The public key of this certificate is used, thus no password necessary.
+     * The user name is a keystore alias usually.
+     * 
+     * @param user
+     */
+    public void setUserInfo(String user) {
+        this.user = user;
+    }
+
+    /**
+     * Get the id generated during <code>prepare()</code>.
+     * 
+     * Returns the the value of wsu:Id attribute of the EncryptedKey element.
+     * 
+     * @return Return the wsu:Id of this token or null if <code>prepare()</code>
+     *         was not called before.
+     */
+    public String getId() {
+        return encKeyId;
+    }
+
+    /**
+     * Prepare the ephemeralKey and the tokens required to be added to the
+     * security header
+     * 
+     * @param doc
+     *            The SOAP envelope as <code>Document</code>
+     * @param crypto
+     *            An instance of the Crypto API to handle keystore and
+     *            certificates
+     * @throws WSSecurityException
+     */
+    public void prepare(Document doc, Crypto crypto) throws WSSecurityException {
+
+        document = doc;
+
+        /*
+         * Set up the ephemeral key
+         */
+        if (this.ephemeralKey == null) {
+            this.ephemeralKey = generateEphemeralKey();
+        }
+
+        /*
+         * Get the certificate that contains the public key for the public key
+         * algorithm that will encrypt the generated symmetric (session) key.
+         */
+        X509Certificate remoteCert = null;
+        if (useThisCert != null) {
+            remoteCert = useThisCert;
+        } else {
+            X509Certificate[] certs = crypto.getCertificates(user);
+            if (certs == null || certs.length <= 0) {
+                throw new WSSecurityException(
+                    WSSecurityException.FAILURE,
+                    "noUserCertsFound", 
+                    new Object[] { user, "encryption" }
+                );
+            }
+            remoteCert = certs[0];
+        }
+        
+        prepareInternal(ephemeralKey, remoteCert, crypto);
+    }
+
+    /**
+     * Encrypt the symmetric key data and prepare the EncryptedKey element
+     * 
+     * This method does the most work for to prepare the EncryptedKey element.
+     * It is also used by the WSSecEncrypt sub-class.
+     * 
+     * @param keyBytes
+     *            The bytes that represent the symmetric key
+     * @param remoteCert
+     *            The certificate that contains the public key to encrypt the
+     *            symmetric key data
+     * @param crypto
+     *            An instance of the Crypto API to handle keystore and
+     *            certificates
+     * @throws WSSecurityException
+     */
+    protected void prepareInternal(byte[] keyBytes, X509Certificate remoteCert,
+            Crypto crypto) throws WSSecurityException {
+        String certUri = UUIDGenerator.getUUID();
+        Cipher cipher = WSSecurityUtil.getCipherInstance(keyEncAlgo);
+        try {
+            cipher.init(Cipher.ENCRYPT_MODE, remoteCert.getPublicKey());
+        } catch (InvalidKeyException e) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION,
+                    null, null, e);
+        }
+        if (doDebug) {
+            log.debug("cipher blksize: " + cipher.getBlockSize()
+                    + ", symm key length: " + keyBytes.length);
+        }
+        int blockSize = cipher.getBlockSize();
+        if (blockSize > 0 && blockSize < keyBytes.length) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unsupportedKeyTransp",
+                    new Object[] { "public key algorithm too weak to encrypt "
+                            + "symmetric key" });
+        }
+        
+        try {
+            this.encryptedEphemeralKey = cipher.doFinal(keyBytes);
+        } catch (IllegalStateException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION,
+                    null, null, e1);
+        } catch (IllegalBlockSizeException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION,
+                    null, null, e1);
+        } catch (BadPaddingException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_ENCRYPTION,
+                    null, null, e1);
+        }
+        Text keyText = WSSecurityUtil.createBase64EncodedTextNode(document,
+                this.encryptedEphemeralKey);
+
+        /*
+         * Now we need to setup the EncryptedKey header block 1) create a
+         * EncryptedKey element and set a wsu:Id for it 2) Generate ds:KeyInfo
+         * element, this wraps the wsse:SecurityTokenReference 3) Create and set
+         * up the SecurityTokenReference according to the keyIdentifier parameter
+         * 4) Create the CipherValue element structure and insert the encrypted
+         * session key
+         */
+        encryptedKeyElement = createEncryptedKey(document, keyEncAlgo);
+        if(this.encKeyId == null || "".equals(this.encKeyId)) {
+            this.encKeyId = "EncKeyId-" + UUIDGenerator.getUUID();
+        }
+        encryptedKeyElement.setAttributeNS(null, "Id", this.encKeyId);
+
+        KeyInfo keyInfo = new KeyInfo(document);
+
+        SecurityTokenReference secToken = new SecurityTokenReference(document);
+
+        switch (keyIdentifierType) {
+        case WSConstants.X509_KEY_IDENTIFIER:
+            secToken.setKeyIdentifier(remoteCert);
+            break;
+
+        case WSConstants.SKI_KEY_IDENTIFIER:
+            secToken.setKeyIdentifierSKI(remoteCert, crypto);
+            break;
+
+        case WSConstants.THUMBPRINT_IDENTIFIER:
+            secToken.setKeyIdentifierThumb(remoteCert);
+            break;
+            
+        case WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER:
+            //
+            // This identifier is not applicable for this case, so fall back to
+            // ThumbprintRSA.
+            //
+            secToken.setKeyIdentifierThumb(remoteCert);
+            break;
+
+        case WSConstants.ISSUER_SERIAL:
+            XMLX509IssuerSerial data = new XMLX509IssuerSerial(document,
+                    remoteCert);
+            X509Data x509Data = new X509Data(document);
+            x509Data.add(data);
+            secToken.setX509IssuerSerial(x509Data);
+            break;
+
+        case WSConstants.BST_DIRECT_REFERENCE:
+            Reference ref = new Reference(document);
+            ref.setURI("#" + certUri);
+            bstToken = new X509Security(document);
+            ((X509Security) bstToken).setX509Certificate(remoteCert);
+            bstToken.setID(certUri);
+            ref.setValueType(bstToken.getValueType());
+            secToken.setReference(ref);
+            break;
+
+        default:
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unsupportedKeyId");
+        }
+        keyInfo.addUnknownElement(secToken.getElement());
+        Element keyInfoElement = keyInfo.getElement();
+        keyInfoElement.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                + WSConstants.SIG_PREFIX, WSConstants.SIG_NS);
+        WSSecurityUtil.appendChildElement(document, encryptedKeyElement,
+                keyInfoElement);
+
+        Element xencCipherValue = createCipherValue(document,
+                encryptedKeyElement);
+        xencCipherValue.appendChild(keyText);
+
+        envelope = document.getDocumentElement();
+        envelope.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                + WSConstants.ENC_PREFIX, WSConstants.ENC_NS);
+    }
+
+    /**
+     * Create an ephemeral key
+     * 
+     * @return an ephemeral key
+     * @throws WSSecurityException
+     */
+    protected byte[] generateEphemeralKey() throws WSSecurityException {
+        try {     
+            final SecureRandom r = WSSecurityUtil.resolveSecureRandom();
+            if (r == null) {
+                throw new WSSecurityException("Random generator is not initialzed.");
+            }
+            byte[] temp = new byte[this.keySize / 8];
+            r.nextBytes(temp);
+            return temp;
+        } catch (Exception e) {
+            throw new WSSecurityException(
+                    "Error in creating the ephemeral key", e);
+        }
+    }
+
+    /**
+     * Create DOM subtree for <code>xenc:EncryptedKey</code>
+     * 
+     * @param doc
+     *            the SOAP envelope parent document
+     * @param keyTransportAlgo
+     *            specifies which algorithm to use to encrypt the symmetric key
+     * @return an <code>xenc:EncryptedKey</code> element
+     */
+
+    protected Element createEncryptedKey(Document doc, String keyTransportAlgo) {
+        Element encryptedKey = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":EncryptedKey");
+
+        WSSecurityUtil.setNamespace(encryptedKey, WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX);
+        Element encryptionMethod = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":EncryptionMethod");
+        encryptionMethod.setAttributeNS(null, "Algorithm", keyTransportAlgo);
+        WSSecurityUtil.appendChildElement(doc, encryptedKey, encryptionMethod);
+        return encryptedKey;
+    }
+    
+    /**
+     * Create DOM subtree for <code>xenc:EncryptedKey</code>
+     * 
+     * @param doc
+     *            the SOAP envelope parent document
+     * @param keyTransportAlgo
+     *            specifies which algorithm to use to encrypt the symmetric key
+     * @return an <code>xenc:EncryptedKey</code> element
+     * @deprecated use createEncryptedKey(Document doc, String keyTransportAlgo) instead
+     */
+    protected Element createEnrcyptedKey(Document doc, String keyTransportAlgo) {
+        return createEncryptedKey(doc, keyTransportAlgo);
+    }
+
+    protected Element createCipherValue(Document doc, Element encryptedKey) {
+        Element cipherData = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":CipherData");
+        Element cipherValue = doc.createElementNS(WSConstants.ENC_NS,
+                WSConstants.ENC_PREFIX + ":CipherValue");
+        cipherData.appendChild(cipherValue);
+        WSSecurityUtil.appendChildElement(doc, encryptedKey, cipherData);
+        return cipherValue;
+    }
+
+    /**
+     * Prepend the EncryptedKey element to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>. This
+     * allows to insert the EncryptedKey element at any position in the Security
+     * header.
+     * 
+     * @param secHeader
+     *            The security header that holds the Signature element.
+     */
+    public void prependToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader
+                .getSecurityHeader(), encryptedKeyElement, false);
+    }
+
+    /**
+     * Append the EncryptedKey element to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>. This
+     * allows to insert the EncryptedKey element at any position in the Security
+     * header.
+     * 
+     * @param secHeader
+     *            The security header that holds the Signature element.
+     */
+    public void appendToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.appendChildElement(document, secHeader
+                .getSecurityHeader(), encryptedKeyElement);
+    }
+    
+    /**
+     * Prepend the BinarySecurityToken to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>. This
+     * allows to insert the BST element at any position in the Security header.
+     * 
+     * @param secHeader
+     *            The security header that holds the BST element.
+     */
+    public void prependBSTElementToHeader(WSSecHeader secHeader) {
+        if (bstToken != null) {
+            WSSecurityUtil.prependChildElement(document, secHeader
+                    .getSecurityHeader(), bstToken.getElement(), false);
+        }
+        bstToken = null;
+    }
+
+    /**
+     * Append the BinarySecurityToken to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>. This
+     * allows to insert the BST element at any position in the Security header.
+     * 
+     * @param secHeader
+     *            The security header that holds the BST element.
+     */
+    public void appendBSTElementToHeader(WSSecHeader secHeader) {
+        if (bstToken != null) {
+            WSSecurityUtil.appendChildElement(document, secHeader
+                    .getSecurityHeader(), bstToken.getElement());
+        }
+        bstToken = null;
+    }
+    
+    /**
+     * @return Returns the ephemeralKey.
+     */
+    public byte[] getEphemeralKey() {
+        return ephemeralKey;
+    }
+    
+    /**
+     * Set the X509 Certificate to use for encryption.
+     * 
+     * If this is set <b>and</b> the key identifier is set to
+     * <code>DirectReference</code> then use this certificate to get the
+     * public key for encryption.
+     * 
+     * @param cert
+     *            is the X509 certificate to use for encryption
+     */
+    public void setUseThisCert(X509Certificate cert) {
+        useThisCert = cert;
+    }
+
+    /**
+     * @return Returns the encryptedKeyElement.
+     */
+    public Element getEncryptedKeyElement() {
+        return encryptedKeyElement;
+    }
+    
+    /**
+     * Set the encrypted key element when a pre prepared encrypted key is used
+     * @param encryptedKeyElement EncryptedKey element of the encrypted key used
+     */
+    public void setEncryptedKeyElement(Element encryptedKeyElement) {
+        this.encryptedKeyElement = encryptedKeyElement;
+    }
+    
+    /**
+     * @return Returns the BinarySecurityToken element.
+     */
+    public Element getBinarySecurityTokenElement() {
+        if(this.bstToken != null) {
+            return this.bstToken.getElement();
+        } else  {
+            return null;
+        }
+    }
+
+    public void setKeySize(int keySize) throws WSSecurityException {
+        if(keySize < 64) {
+            //Minimum size has to be 64 bits - E.g. A DES key
+            throw new WSSecurityException("invalidKeySize");
+        }
+        this.keySize = keySize;
+    }
+
+    public void setKeyEncAlgo(String keyEncAlgo) {
+        this.keyEncAlgo = keyEncAlgo;
+    }
+
+    /**
+     * @param ephemeralKey The ephemeralKey to set.
+     */
+    public void setEphemeralKey(byte[] ephemeralKey) {
+        this.ephemeralKey = ephemeralKey;
+    }
+    
+    /**
+     * Get the id of the BSt generated  during <code>prepare()</code>.
+     * 
+     * @return Returns the the value of wsu:Id attribute of the 
+     * BinaruSecurityToken element.
+     */
+    public String getBSTTokenId() {
+        if(this.bstToken == null) {
+            return null;
+        }
+        
+        return this.bstToken.getID();
+    }
+
+    /**
+     * @param document The document to set.
+     */
+    public void setDocument(Document document) {
+        this.document = document;
+    }
+
+    /**
+     * @param encKeyId The encKeyId to set.
+     */
+    public void setEncKeyId(String encKeyId) {
+        this.encKeyId = encKeyId;
+    }
+    
+    public boolean isCertSet() {
+        return (useThisCert == null ? true : false) ;
+    }
+
+    public byte[] getEncryptedEphemeralKey() {
+        return encryptedEphemeralKey;
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecHeader.java b/trunk/src/org/apache/ws/security/message/WSSecHeader.java
new file mode 100644
index 0000000..4662429
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecHeader.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * This class implements WS Security header.
+ * 
+ * Setup a Security header with a specified actor and mustunderstand flag.
+ * 
+ * <p/>
+ * 
+ * The defaults for actor and mustunderstand are: empty <code>actor</code> and
+ * <code>mustunderstand</code> is true.
+ * 
+ * @author Werner Dittmann (Werner.Dittmann@apache.org)
+ */
+public class WSSecHeader {
+    protected String actor = null;
+
+    protected boolean mustunderstand = true;
+
+    protected boolean doDebug = false;
+
+    private Element securityHeader = null;
+
+    /**
+     * Constructor.
+     */
+    public WSSecHeader() {
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param actor
+     *            The actor name of the <code>wsse:Security</code> header
+     */
+    public WSSecHeader(String actor) {
+        this(actor, true);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param act
+     *            The actor name of the <code>wsse:Security</code> header
+     * @param mu
+     *            Set <code>mustUnderstand</code> to true or false
+     */
+    public WSSecHeader(String act, boolean mu) {
+        actor = act;
+        mustunderstand = mu;
+    }
+
+    /**
+     * set actor name.
+     * 
+     * @param act
+     *            The actor name of the <code>wsse:Security</code> header
+     */
+    public void setActor(String act) {
+        actor = act;
+    }
+
+    /**
+     * Set the <code>mustUnderstand</code> flag for the
+     * <code>wsse:Security</code> header.
+     * 
+     * @param mu
+     *            Set <code>mustUnderstand</code> to true or false
+     */
+    public void setMustUnderstand(boolean mu) {
+        mustunderstand = mu;
+    }
+
+    /**
+     * Get the security header element of this instance.
+     * 
+     * @return The security header element.
+     */
+    public Element getSecurityHeader() {
+        return securityHeader;
+    }
+    
+    /**
+     * Returns whether the security header is empty
+     * 
+     * @return true if empty or if there is no security header
+     *         false if non empty security header
+     */
+    public boolean isEmpty(Document doc) {
+        
+        if (securityHeader == null) {            
+            securityHeader = WSSecurityUtil.findWsseSecurityHeaderBlock(doc, doc
+                    .getDocumentElement(), actor, false);
+            if ( securityHeader == null ) {
+                return true;
+            }
+        }
+        
+        if ( securityHeader.getChildNodes().getLength() == 0 ) {
+            return true;
+        } else {
+            return false;
+        }
+
+        
+    }
+
+    /**
+     * Creates a security header and inserts it as child into the SOAP Envelope.
+     * 
+     * <p/>
+     * 
+     * Check if a WS Security header block for an actor is already available in
+     * the document. If a header block is found return it, otherwise a new
+     * wsse:Security header block is created and the attributes set
+     * 
+     * @param doc
+     *            A SOAP envelope as <code>Document</code>
+     * @return A <code>wsse:Security</code> element
+     */
+    public Element insertSecurityHeader(Document doc) {
+
+        /*
+         * If there is already a security header in this instance just return it
+         */
+        if (securityHeader != null) {
+            return securityHeader;
+        }
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+
+        securityHeader = WSSecurityUtil.findWsseSecurityHeaderBlock(doc, doc
+                .getDocumentElement(), actor, true);
+
+        String soapPrefix = WSSecurityUtil.getPrefixNS(soapConstants
+                .getEnvelopeURI(), securityHeader);
+        if (actor != null && actor.length() > 0) {
+            securityHeader.setAttributeNS(soapConstants.getEnvelopeURI(),
+                    soapPrefix
+                            + ":"
+                            + soapConstants.getRoleAttributeQName()
+                                    .getLocalPart(), actor);
+        }
+        if (mustunderstand) {
+            securityHeader.setAttributeNS(soapConstants.getEnvelopeURI(),
+                    soapPrefix + ":" + WSConstants.ATTR_MUST_UNDERSTAND,
+                    soapConstants.getMustUnderstand());
+        }
+        return securityHeader;
+    }
+    
+    public void removeSecurityHeader(Document doc) {
+        
+        if (securityHeader == null) {            
+            securityHeader = WSSecurityUtil.findWsseSecurityHeaderBlock(doc, doc
+                    .getDocumentElement(), actor, false);
+            if ( securityHeader == null ) {
+                return;
+            }
+        }
+        
+        Node parent = securityHeader.getParentNode();
+        parent.removeChild(securityHeader);
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecSAMLToken.java b/trunk/src/org/apache/ws/security/message/WSSecSAMLToken.java
new file mode 100644
index 0000000..ee941e6
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecSAMLToken.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.opensaml.SAMLAssertion;
+import org.opensaml.SAMLException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Builds a WS SAML Assertion and inserts it into the SOAP Envelope. Refer to
+ * the WS specification, SAML Token profile
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class WSSecSAMLToken extends WSSecBase {
+
+    private static Log log = LogFactory.getLog(WSSecSAMLToken.class.getName());
+    
+    private Document document = null;
+    
+    private SAMLAssertion saml = null;
+
+    /**
+     * Constructor.
+     */
+    public WSSecSAMLToken() {
+    }
+
+    /**
+     * Creates a SAML token.
+     * 
+     * The method prepares and initializes a WSSec UsernameToken structure after
+     * the relevant information was set. A Before calling
+     * <code>prepare()</code> all parameters such as user, password,
+     * passwordType etc. must be set. A complete <code>UsernameToken</code> is
+     * constructed.
+     * 
+     * @param doc
+     *            The SOAP envelope as W3C document
+     */
+    public void prepare(Document doc, SAMLAssertion assertion) {
+        document = doc;
+        saml = assertion;
+    }
+
+    /**
+     * Prepends the SAML Assertion to the elements already in the
+     * Security header.
+     * 
+     * The method can be called any time after <code>prepare()</code>.
+     * This allows to insert the SAML assertion at any position in the
+     * Security header.
+     * 
+     * @param secHeader
+     *            The security header that holds the Signature element.
+     */
+    public void prependToHeader(WSSecHeader secHeader) {
+        Element element = null;        
+        try {
+            element = (Element) saml.toDOM(document);
+        } catch (SAMLException ex) {
+            throw new RuntimeException(ex.toString(), ex);
+        }
+        
+        WSSecurityUtil.prependChildElement(document, secHeader
+                .getSecurityHeader(), element, false);
+    }
+    
+    /**
+     * Get the id generated during <code>prepare()</code>.
+     * 
+     * Returns the the value of wsu:Id attribute of this Timestamp. 
+     * 
+     * @return Return the wsu:Id of this token or null if <code>prepareToken()</code>
+     * was not called before.
+     */
+    public String getId() {
+        if (saml == null) {
+            return null;
+        }
+        return saml.getId();
+    }
+    
+    /**
+     * Adds a new <code>SAMLAssertion</code> to a soap envelope.
+     * <p/>
+     * A complete <code>SAMLAssertion</code> is added to the
+     * <code>wsse:Security</code> header.
+     *
+     * @param doc      The SOAP envelope as W3C document
+     * @param assertion TODO
+     * @return Document with UsernameToken added
+     */
+    public Document build(Document doc, SAMLAssertion assertion, WSSecHeader secHeader) {
+        log.debug("Begin add SAMLAssertion token...");
+        
+        prepare(doc, assertion);
+        prependToHeader(secHeader);
+        
+        return doc;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecSecurityContextToken.java b/trunk/src/org/apache/ws/security/message/WSSecSecurityContextToken.java
new file mode 100644
index 0000000..0137681
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecSecurityContextToken.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.security.message;
+
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.conversation.ConversationConstants;
+import org.apache.ws.security.conversation.ConversationException;
+import org.apache.ws.security.message.token.SecurityContextToken;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+
+/**
+ * Builder class to add a <code>wsc:SecurityContextToken</code> into the
+ * <code>wsse:Security</code>
+ * 
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public class WSSecSecurityContextToken {
+
+    /**
+     * The <code>wsc:SecurityContextToken</code> to be added to the
+     * <code>wsse:SecurityHeader</code>
+     */
+    private SecurityContextToken sct;
+
+    /**
+     * The <code>wsu:Id</code> of the <code>wsc:SecurityContextToken</code> 
+     */
+    private String sctId;
+
+    /**
+     * The <code>wsc:Identifier</code> of the
+     * <code>wsc:SecurityContextToken</code>
+     */
+    private String identifier;
+
+    /**
+     * The symmetric secret associated with the SecurityContextToken
+     */
+    protected byte[] secret;
+    
+    private int wscVersion = ConversationConstants.DEFAULT_VERSION;
+
+    public void prepare(Document doc, Crypto crypto)
+            throws WSSecurityException, ConversationException  {
+
+        if (sct == null) {
+            if (this.identifier != null) {
+                this.sct = new SecurityContextToken(this.wscVersion, doc, this.identifier);
+            } else {
+                this.sct = new SecurityContextToken(this.wscVersion, doc);
+                this.identifier = this.sct.getIdentifier();
+            }
+        }
+
+        // The wsu:Id of the wsc:SecurityContextToken
+        if (this.sctId != null) {
+            this.sct.setID(this.sctId);
+        }
+    }
+
+    public void prependSCTElementToHeader(Document doc, WSSecHeader secHeader)
+            throws WSSecurityException {
+        WSSecurityUtil.prependChildElement(doc, secHeader.getSecurityHeader(),
+                sct.getElement(), false);
+    }
+
+    /**
+     * @return Returns the sct.
+     */
+    public SecurityContextToken getSct() {
+        return sct;
+    }
+
+    /**
+     * @param sct
+     *            The sct to set.
+     */
+    public void setSct(SecurityContextToken sct) {
+        this.sct = sct;
+    }
+
+    /**
+     * @return Returns the ephemeralKey.
+     */
+    public byte[] getSecret() {
+        return secret;
+    }
+
+    /**
+     * @param ephemeralKey
+     *            The ephemeralKey to set.
+     */
+    protected void setSecret(byte[] ephemeralKey) {
+        this.secret = ephemeralKey;
+    }
+
+    /**
+     * @return Returns the identifier.
+     */
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    /**
+     * @param identifier The identifier to set.
+     */
+    public void setIdentifier(String identifier) {
+        this.identifier = identifier;
+    }
+
+    /**
+     * @return Returns the sctId.
+     */
+    public String getSctId() {
+        if(this.sct != null) {
+            return this.sct.getID();
+        } else {
+            return this.sctId;
+        }
+    }
+
+    /**
+     * @param sctId The sctId to set.
+     */
+    public void setSctId(String sctId) {
+        this.sctId = sctId;
+    }
+
+    /**
+     * @param wscVersion The wscVersion to set.
+     */
+    public void setWscVersion(int wscVersion) {
+        this.wscVersion = wscVersion;
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecSignature.java b/trunk/src/org/apache/ws/security/message/WSSecSignature.java
new file mode 100644
index 0000000..598690a
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecSignature.java
@@ -0,0 +1,867 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSDocInfoStore;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.PKIPathSecurity;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.saml.SAMLUtil;
+import org.apache.ws.security.transform.STRTransform;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.algorithms.SignatureAlgorithm;
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.signature.XMLSignatureException;
+import org.apache.xml.security.transforms.TransformationException;
+import org.apache.xml.security.transforms.Transforms;
+import org.apache.xml.security.transforms.params.InclusiveNamespaces;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xml.security.utils.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import java.security.cert.X509Certificate;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ * Creates a Signature according to WS Specification, X509 profile.
+ * 
+ * This class is a re-factored implementation of the previous WSS4J class
+ * <code>WSSignEnvlope</code>. This new class allows better control of
+ * the process to create a Signature and to add it to the Security header.
+ * 
+ * <br/>
+ * 
+ * The flexibility and fine granular control is required to implement a handler
+ * that uses WSSecurityPolicy files to control the setup of a Security header.
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ * @author Werner Dittmann (werner@apache.org)
+ */
+public class WSSecSignature extends WSSecBase {
+
+    private static Log log = LogFactory.getLog(WSSecSignature.class.getName());
+
+    protected boolean useSingleCert = true;
+
+    protected String sigAlgo = null;
+
+    protected String canonAlgo = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
+
+    protected WSSecUsernameToken usernameToken = null;
+
+    protected byte[] signatureValue = null;
+
+    /*
+     * The following private variable are setup during prepare().
+     */
+    protected Document document = null;
+
+    private Crypto crypto = null;
+
+    protected WSDocInfo wsDocInfo = null;
+
+    protected String certUri = null;
+
+    protected XMLSignature sig = null;
+
+    protected KeyInfo keyInfo = null;
+
+    protected String keyInfoUri = null;
+
+    protected SecurityTokenReference secRef = null;
+
+    protected String strUri = null;
+
+    private byte[] secretKey = null;
+    
+    private String encrKeySha1value = null;
+
+    protected BinarySecurity bstToken = null;
+
+    private String customTokenValueType;
+
+    private String customTokenId;
+    
+    private String digestAlgo = "http://www.w3.org/2000/09/xmldsig#sha1";
+
+    /**
+     * Constructor.
+     */
+    public WSSecSignature() {
+    }
+
+    /**
+     * set the single cert flag.
+     * 
+     * @param useSingleCert
+     */
+    public void setUseSingleCertificate(boolean useSingleCert) {
+        this.useSingleCert = useSingleCert;
+    }
+
+    /**
+     * Get the single cert flag.
+     * 
+     * @return A boolean if single certificate is set.
+     */
+    public boolean isUseSingleCertificate() {
+        return this.useSingleCert;
+    }
+
+    /**
+     * Set the name of the signature encryption algorithm to use.
+     * 
+     * If the algorithm is not set then an automatic detection of the signature
+     * algorithm to use is performed during the <code>prepare()</code>
+     * method. Refer to WSConstants which algorithms are supported.
+     * 
+     * @param algo
+     *            Is the name of the signature algorithm
+     * @see WSConstants#RSA
+     * @see WSConstants#DSA
+     */
+    public void setSignatureAlgorithm(String algo) {
+        sigAlgo = algo;
+    }
+
+    /**
+     * Get the name of the signature algorithm that is being used.
+     * 
+     * Call this method after <code>prepare</code> to get the information
+     * which signature algorithm was automatically detected if no signature
+     * algorithm was preset.
+     * 
+     * @return the identifier URI of the signature algorithm
+     */
+    public String getSignatureAlgorithm() {
+        return sigAlgo;
+    }
+
+    /**
+     * Set the canonicalization method to use.
+     * 
+     * If the canonicalization method is not set then the recommended Exclusive
+     * XML Canonicalization is used by default Refer to WSConstants which
+     * algorithms are supported.
+     * 
+     * @param algo
+     *            Is the name of the signature algorithm
+     * @see WSConstants#C14N_OMIT_COMMENTS
+     * @see WSConstants#C14N_WITH_COMMENTS
+     * @see WSConstants#C14N_EXCL_OMIT_COMMENTS
+     * @see WSConstants#C14N_EXCL_WITH_COMMENTS
+     */
+    public void setSigCanonicalization(String algo) {
+        canonAlgo = algo;
+    }
+
+    /**
+     * Get the canonicalization method.
+     * 
+     * If the canonicalization method was not set then Exclusive XML
+     * Canonicalization is used by default.
+     * 
+     * @return The string describing the canonicalization algorithm.
+     */
+    public String getSigCanonicalization() {
+        return canonAlgo;
+    }
+
+    /**
+     * @return the digestAlgo
+     */
+    public String getDigestAlgo() {
+        return digestAlgo;
+    }
+
+    /**
+     * Set the string that defines which digest algorithm to use
+     * 
+     * @param digestAlgo the digestAlgo to set
+     */
+    public void setDigestAlgo(String digestAlgo) {
+        this.digestAlgo = digestAlgo;
+    }
+    
+    
+    /**
+     * @param usernameToken
+     *            The usernameToken to set.
+     */
+    public void setUsernameToken(WSSecUsernameToken usernameToken) {
+        this.usernameToken = usernameToken;
+    }
+
+    /**
+     * Returns the computed Signature value.
+     * 
+     * Call this method after <code>computeSignature()</code> or <code>build()</code>
+     * methods were called.
+     * 
+     * @return Returns the signatureValue.
+     */
+    public byte[] getSignatureValue() {
+        return signatureValue;
+    }
+
+    /**
+     * Get the id generated during <code>prepare()</code>.
+     * 
+     * Returns the the value of wsu:Id attribute of the Signature element.
+     * 
+     * @return Return the wsu:Id of this token or null if <code>prepare()</code>
+     *         was not called before.
+     */
+    public String getId() {
+        if (sig == null) {
+            return null;
+        }
+        return sig.getId();
+    }
+    
+    /**
+     * Get the id of the BSt generated  during <code>prepare()</code>.
+     * 
+     * @return Returns the the value of wsu:Id attribute of the 
+     * BinaruSecurityToken element.
+     */
+    public String getBSTTokenId() {
+        if(this.bstToken == null) {
+            return null;
+        }
+        
+        return this.bstToken.getID();
+    }
+
+    /**
+     * Initialize a WSSec Signature.
+     * 
+     * The method sets up and initializes a WSSec Signature structure after the
+     * relevant information was set. After setup of the references to elements
+     * to sign may be added. After all references are added they can be signed.
+     * 
+     * <p/>
+     * 
+     * This method does not add the Signature element to the security header.
+     * See <code>prependSignatureElementToHeader()</code> method.
+     * 
+     * @param doc
+     *            The SOAP envelope as <code>Document</code>
+     * @param cr
+     *            An instance of the Crypto API to handle keystore and
+     *            certificates
+     * @param secHeader
+     *            The security header that will hold the Signature. This is used
+     *            to construct namespace prefixes for Signature. This method
+     * @throws WSSecurityException
+     */
+    public void prepare(Document doc, Crypto cr, WSSecHeader secHeader)
+            throws WSSecurityException {
+        /*
+         * Gather some info about the document to process and store it for
+         * retrieval
+         */
+        crypto = cr;
+        document = doc;
+
+        wsDocInfo = new WSDocInfo(doc.hashCode());
+        wsDocInfo.setCrypto(cr);
+
+        /*
+         * At first get the security token (certificate) according to the
+         * parameters.
+         */
+        X509Certificate[] certs = null;
+        if (keyIdentifierType != WSConstants.UT_SIGNING
+                && keyIdentifierType != WSConstants.CUSTOM_SYMM_SIGNING
+                  && keyIdentifierType != WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER) {
+            certs = crypto.getCertificates(user);
+            if (certs == null || certs.length <= 0) {
+                throw new WSSecurityException(
+                    WSSecurityException.FAILURE,
+                    "noUserCertsFound", 
+                    new Object[] { user, "signature" }
+                );
+            }
+            certUri = "CertId-" + certs[0].hashCode();
+            /*
+             * If no signature algo was set try to detect it according to the
+             * data stored in the certificate.
+             */
+            if (sigAlgo == null) {
+                String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm();
+                log.debug("automatic sig algo detection: " + pubKeyAlgo);
+                if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
+                    sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+                } else if (pubKeyAlgo.equalsIgnoreCase("RSA")) {
+                    sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
+                } else {
+                    throw new WSSecurityException(
+                        WSSecurityException.FAILURE,
+                        "unknownSignatureAlgorithm",
+                        new Object[] {
+                            pubKeyAlgo
+                        }
+                    );
+                }
+            }
+        }
+
+        /*
+         * Get an initialized XMLSignature element.
+         */
+        if (canonAlgo.equals(WSConstants.C14N_EXCL_OMIT_COMMENTS)) {
+            Element canonElem = XMLUtils.createElementInSignatureSpace(doc,
+                    Constants._TAG_CANONICALIZATIONMETHOD);
+
+            canonElem.setAttributeNS(null, Constants._ATT_ALGORITHM, canonAlgo);
+
+            if (wssConfig.isWsiBSPCompliant()) {
+                Set prefixes = getInclusivePrefixes(secHeader.getSecurityHeader(), false);
+
+                InclusiveNamespaces inclusiveNamespaces = new InclusiveNamespaces(
+                        doc, prefixes);
+
+                canonElem.appendChild(inclusiveNamespaces.getElement());
+            }
+
+            try {
+                SignatureAlgorithm signatureAlgorithm = new SignatureAlgorithm(
+                        doc, sigAlgo);
+                sig = new XMLSignature(doc, null, signatureAlgorithm
+                        .getElement(), canonElem);
+            } catch (XMLSecurityException e) {
+                log.error("", e);
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e
+                );
+            }
+        } else {
+            try {
+                sig = new XMLSignature(doc, null, sigAlgo, canonAlgo);
+            } catch (XMLSecurityException e) {
+                log.error("", e);
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e
+                );
+            }
+        }
+
+        sig.addResourceResolver(EnvelopeIdResolver.getInstance());
+        String sigUri = "Signature-" + sig.hashCode();
+        sig.setId(sigUri);
+
+        keyInfo = sig.getKeyInfo();
+        keyInfoUri = "KeyId-" + keyInfo.hashCode();
+        keyInfo.setId(keyInfoUri);
+
+        secRef = new SecurityTokenReference(doc);
+        strUri = "STRId-" + secRef.hashCode();
+        secRef.setID(strUri);
+
+        /*
+         * Prepare and setup the token references for this Signature
+         */
+        switch (keyIdentifierType) {
+        case WSConstants.BST_DIRECT_REFERENCE:
+            Reference ref = new Reference(document);
+            ref.setURI("#" + certUri);
+            if (!useSingleCert) {
+                bstToken = new PKIPathSecurity(document);
+                ((PKIPathSecurity) bstToken).setX509Certificates(certs, false,
+                        crypto);
+            } else {
+                bstToken = new X509Security(document);
+                ((X509Security) bstToken).setX509Certificate(certs[0]);
+            }
+            ref.setValueType(bstToken.getValueType());
+            secRef.setReference(ref);
+            bstToken.setID(certUri);
+            wsDocInfo.setBst(bstToken.getElement());
+            break;
+
+        case WSConstants.ISSUER_SERIAL:
+            XMLX509IssuerSerial data = new XMLX509IssuerSerial(document,
+                    certs[0]);
+            X509Data x509Data = new X509Data(document);
+            x509Data.add(data);
+            secRef.setX509IssuerSerial(x509Data);
+            break;
+
+        case WSConstants.X509_KEY_IDENTIFIER:
+            secRef.setKeyIdentifier(certs[0]);
+            break;
+
+        case WSConstants.SKI_KEY_IDENTIFIER:
+            secRef.setKeyIdentifierSKI(certs[0], crypto);
+            break;
+
+        case WSConstants.UT_SIGNING:
+            Reference refUt = new Reference(document);
+            refUt.setValueType(WSConstants.USERNAMETOKEN_NS + "#UsernameToken");
+            String utId = usernameToken.getId();
+            refUt.setURI("#" + utId);
+            secRef.setReference(refUt);
+            secretKey = usernameToken.getSecretKey();
+            break;
+
+        case WSConstants.THUMBPRINT_IDENTIFIER:
+            secRef.setKeyIdentifierThumb(certs[0]);
+            break;
+            
+        case WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER:
+            secRef.setKeyIdentifierEncKeySHA1(this.encrKeySha1value);
+            break;
+
+        case WSConstants.CUSTOM_SYMM_SIGNING :
+            Reference refCust = new Reference(document);
+            refCust.setValueType(this.customTokenValueType);
+            refCust.setURI("#" + this.customTokenId);
+            secRef.setReference(refCust);
+            break;
+        default:
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unsupportedKeyId");
+        }
+        keyInfo.addUnknownElement(secRef.getElement());
+
+    }
+
+    /**
+     * This method adds references to the Signature.
+     * 
+     * The added references are signed when calling
+     * <code>computeSignature()</code>. This method can be called several
+     * times to add references as required. <code>addReferencesToSign()</code>
+     * can be called any time after <code>prepare</code>.
+     * 
+     * @param references
+     *            A vector containing <code>WSEncryptionPart</code> objects
+     *            that define the parts to sign.
+     * @param secHeader
+     *            Used to compute namespaces to be inserted by
+     *            InclusiveNamespaces to be WSI compliant.
+     * @throws WSSecurityException
+     */
+    public void addReferencesToSign(Vector references, WSSecHeader secHeader)
+            throws WSSecurityException {
+        Transforms transforms = null;
+
+        Element envelope = document.getDocumentElement();
+
+        for (int part = 0; part < references.size(); part++) {
+            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
+
+            String idToSign = encPart.getId();
+
+            String elemName = encPart.getName();
+            String nmSpace = encPart.getNamespace();
+
+            /*
+             * Set up the elements to sign. There are two reserved element
+             * names: "Token" and "STRTransform" "Token": Setup the Signature to
+             * either sign the information that points to the security token or
+             * the token itself. If its a direct reference sign the token,
+             * otherwise sign the KeyInfo Element. "STRTransform": Setup the
+             * ds:Reference to use STR Transform
+             * 
+             */
+            transforms = new Transforms(document);
+            try {
+                if (idToSign != null) {
+                    Element toSignById = WSSecurityUtil.findElementById(
+                            document.getDocumentElement(), idToSign,
+                            WSConstants.WSU_NS);
+                    if (toSignById == null) {
+                        toSignById = WSSecurityUtil.findElementById(document
+                                .getDocumentElement(), idToSign, null);
+                    }
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(document,
+                                        getInclusivePrefixes(toSignById))
+                                        .getElement());
+                    }
+                    sig.addDocument("#" + idToSign, transforms, digestAlgo);
+                } else if (elemName.equals("Token")) {
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (keyIdentifierType == WSConstants.BST_DIRECT_REFERENCE) {
+                        if (wssConfig.isWsiBSPCompliant()) {
+                            transforms
+                                    .item(0)
+                                    .getElement()
+                                    .appendChild(
+                                            new InclusiveNamespaces(
+                                                    document,
+                                                    getInclusivePrefixes(secHeader.getSecurityHeader()))
+                                                    .getElement());
+                        }
+                        sig.addDocument("#" + certUri, transforms, digestAlgo);
+                    } else {
+                        if (wssConfig.isWsiBSPCompliant()) {
+                            transforms.item(0).getElement().appendChild(
+                                    new InclusiveNamespaces(document,
+                                            getInclusivePrefixes(keyInfo
+                                                    .getElement()))
+                                            .getElement());
+                        }
+                        sig.addDocument("#" + keyInfoUri, transforms, digestAlgo);
+                    }
+                } else if (elemName.equals("STRTransform")) { // STRTransform
+                    Element ctx = createSTRParameter(document);
+                    transforms.addTransform(
+                            STRTransform.implementedTransformURI, ctx);
+                    sig.addDocument("#" + strUri, transforms, digestAlgo);
+                } else if (elemName.equals("Assertion")) { // Assertion
+
+                    String id = null;
+                    id = SAMLUtil.getAssertionId(envelope, elemName, nmSpace);
+
+                    Element body = (Element) WSSecurityUtil.findElement(
+                            envelope, elemName, nmSpace);
+                    if (body == null) {
+                        throw new WSSecurityException(
+                                WSSecurityException.FAILURE, "noEncElement",
+                                new Object[] { nmSpace + ", " + elemName });
+                    }
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(document,
+                                        getInclusivePrefixes(body))
+                                        .getElement());
+                    }
+                    String prefix = WSSecurityUtil.setNamespace(body,
+                            WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+                    body.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+                    sig.addDocument("#" + id, transforms, digestAlgo);
+
+                } else {
+                    Element body = (Element) WSSecurityUtil.findElement(
+                            envelope, elemName, nmSpace);
+                    if (body == null) {
+                        throw new WSSecurityException(
+                                WSSecurityException.FAILURE, "noEncElement",
+                                new Object[] { nmSpace + ", " + elemName });
+                    }
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(document,
+                                        getInclusivePrefixes(body))
+                                        .getElement());
+                    }
+                    sig.addDocument("#" + setWsuId(body), transforms, digestAlgo);
+                }
+            } catch (TransformationException e1) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null,
+                        e1);
+            } catch (XMLSignatureException e1) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null,
+                        e1);
+            }
+        }
+    }
+
+    /**
+     * Prepends the Signature element to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>.
+     * This allows to insert the Signature element at any position in the
+     * Security header.
+     * 
+     * @param secHeader
+     *            The secHeader that holds the Signature element.
+     */
+    public void prependToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader.getSecurityHeader(), sig
+                .getElement(), false);
+    }
+    
+    /**
+     * Appends the Signature element to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>.
+     * This allows to insert the Signature element at any position in the
+     * Security header.
+     * 
+     * @param secHeader
+     *            The secHeader that holds the Signature element.
+     */
+    public void appendToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.appendChildElement(document, secHeader.getSecurityHeader(), sig
+                .getElement());
+    }
+    
+    /**
+     * Prepend the BinarySecurityToken to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>.
+     * This allows to insert the BST element at any position in the Security
+     * header.
+     * 
+     * @param secHeader
+     *            The security header that holds the BST element.
+     */
+    public void prependBSTElementToHeader(WSSecHeader secHeader) {
+        if (bstToken != null) {
+            WSSecurityUtil.prependChildElement(document, secHeader.getSecurityHeader(),
+                    bstToken.getElement(), false);
+        }
+        bstToken = null;
+    }
+
+    /**
+     * Returns the SignatureElement.
+     * The method can be called any time after <code>prepare()</code>.
+     * @return The DOM Element of the signature.
+     */
+    public Element getSignatureElement() {
+        return this.sig.getElement();
+    }
+    
+    /**
+     * Returns the BST Token element.
+     * The method can be called any time after <code>prepare()</code>.
+     * @return the BST Token element
+     */
+    public Element getBinarySecurityTokenElement() {
+        if(this.bstToken != null) {
+            return this.bstToken.getElement();
+        } else  {
+            return null;
+        }
+    }
+    
+    public void appendBSTElementToHeader(WSSecHeader secHeader) {
+        if (bstToken != null) {
+            WSSecurityUtil.appendChildElement(document, secHeader.getSecurityHeader(),
+                    bstToken.getElement());
+        }
+        bstToken = null;
+    }
+    
+    /**
+     * Compute the Signature over the references.
+     * 
+     * After references are set this method computes the Signature for them.
+     * This method can be called any time after the references were set. See
+     * <code>addReferencesToSign()</code>.
+     * 
+     * @throws WSSecurityException
+     */
+    public void computeSignature() throws WSSecurityException {
+        WSDocInfoStore.store(wsDocInfo);
+        try {
+            if (keyIdentifierType == WSConstants.UT_SIGNING ||
+                    keyIdentifierType == WSConstants.CUSTOM_SYMM_SIGNING ||
+                      keyIdentifierType == WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER) {
+                sig.sign(sig.createSecretKey(secretKey));
+            } else {
+                sig.sign(crypto.getPrivateKey(user, password));
+            }
+            signatureValue = sig.getSignatureValue();
+        } catch (XMLSignatureException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } catch (Exception e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } finally {
+            WSDocInfoStore.delete(wsDocInfo);
+        }
+
+    }
+
+    /**
+     * Builds a signed soap envelope.
+     * 
+     * This is a convenience method and for backward compatibility. The method
+     * creates a Signature and puts it into the Security header. It does so by
+     * calling the single functions in order to perform a <i>one shot signature</i>.
+     * This method is compatible with the build method of the previous version
+     * with the exception of the additional WSSecHeader parameter.
+     * 
+     * @param doc
+     *            The unsigned SOAP envelope as <code>Document</code>
+     * @param cr
+     *            An instance of the Crypto API to handle keystore and
+     *            certificates
+     * @param secHeader
+     *            the security header element to hold the encrypted key element.
+     * @return A signed SOAP envelope as <code>Document</code>
+     * @throws WSSecurityException
+     */
+    public Document build(Document doc, Crypto cr, WSSecHeader secHeader)
+            throws WSSecurityException {
+        doDebug = log.isDebugEnabled();
+
+        if (doDebug) {
+            log.debug("Beginning signing...");
+        }
+
+        prepare(doc, cr, secHeader);
+
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+
+        addReferencesToSign(parts, secHeader);
+
+        prependToHeader(secHeader);
+
+        /*
+         * if we have a BST prepend it in front of the Signature according to
+         * strict layout rules.
+         */
+        if (bstToken != null) {
+            prependBSTElementToHeader(secHeader);
+        }
+
+        computeSignature();
+
+        return (doc);
+    }
+
+    protected Element createSTRParameter(Document doc) {
+        Element transformParam = doc.createElementNS(WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX + ":TransformationParameters");
+
+        WSSecurityUtil.setNamespace(transformParam, WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX);
+
+        Element canonElem = doc.createElementNS(WSConstants.SIG_NS,
+                WSConstants.SIG_PREFIX + ":CanonicalizationMethod");
+
+        WSSecurityUtil.setNamespace(canonElem, WSConstants.SIG_NS,
+                WSConstants.SIG_PREFIX);
+
+        canonElem.setAttributeNS(null, "Algorithm",
+                Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+        transformParam.appendChild(canonElem);
+        return transformParam;
+    }
+
+    protected Set getInclusivePrefixes(Element target) {
+        return getInclusivePrefixes(target, true);
+    }
+
+    protected Set getInclusivePrefixes(Element target, boolean excludeVisible) {
+        Set result = new HashSet();
+        Node parent = target;
+        NamedNodeMap attributes;
+        Node attribute;
+        while (!(parent.getParentNode() instanceof Document)) {
+            parent = parent.getParentNode();
+            attributes = parent.getAttributes();
+            for (int i = 0; i < attributes.getLength(); i++) {
+                attribute = attributes.item(i);
+                if (attribute.getNamespaceURI() != null
+                        && attribute.getNamespaceURI().equals(
+                                org.apache.ws.security.WSConstants.XMLNS_NS)) {
+                    if (attribute.getNodeName().equals("xmlns")) {
+                        result.add("#default");
+                    } else {
+                        result.add(attribute.getLocalName());
+                    }
+                }
+            }
+        }
+
+        if (excludeVisible == true) {
+            attributes = target.getAttributes();
+            for (int i = 0; i < attributes.getLength(); i++) {
+                attribute = attributes.item(i);
+                if (attribute.getNamespaceURI() != null
+                        && attribute.getNamespaceURI().equals(
+                                org.apache.ws.security.WSConstants.XMLNS_NS)) {
+                    if (attribute.getNodeName().equals("xmlns")) {
+                        result.remove("#default");
+                    } else {
+                        result.remove(attribute.getLocalName());
+                    }
+                }
+                if (attribute.getPrefix() != null) {
+                    result.remove(attribute.getPrefix());
+                }
+            }
+
+            if (target.getPrefix() == null) {
+                result.remove("#default");
+            } else {
+                result.remove(target.getPrefix());
+            }
+        }
+
+        return result;
+    }
+
+    public void setSecretKey(byte[] secretKey) {
+        this.secretKey = secretKey;
+    }
+
+    public void setCustomTokenValueType(String customTokenValueType) {
+        this.customTokenValueType = customTokenValueType;
+    }
+
+    public void setCustomTokenId(String customTokenId) {
+        this.customTokenId = customTokenId;
+    }
+
+    public void setEncrKeySha1value(String encrKeySha1value) {
+        this.encrKeySha1value = encrKeySha1value;
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecSignatureConfirmation.java b/trunk/src/org/apache/ws/security/message/WSSecSignatureConfirmation.java
new file mode 100644
index 0000000..89a8e67
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecSignatureConfirmation.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.message.token.SignatureConfirmation;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Builds a WS SignatureConfirmation and inserts it into the SOAP Envelope.
+ * 
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de).
+ */
+
+public class WSSecSignatureConfirmation extends WSSecBase {
+    private static Log log = LogFactory.getLog(WSSecSignatureConfirmation.class
+            .getName());
+
+    private SignatureConfirmation sc = null;
+
+    private Document document = null;
+    
+    byte[] signatureValue = null;
+
+    /**
+     * Constructor.
+     */
+    public WSSecSignatureConfirmation() {
+    }
+
+    /**
+     * Set the Signature value to store in this SignatureConfirmation.
+     * 
+     * @param signatureValue
+     *            The Signature value to store in the SignatureConfirmation
+     *            element
+     */
+    public void setSignatureValue(byte[] signatureValue) {
+        this.signatureValue = signatureValue;
+    }
+
+
+    /**
+     * Creates a SignatureConfimation element.
+     * 
+     * The method prepares and initializes a WSSec SignatureConfirmation structure after
+     * the relevant information was set. Before calling <code>prepare()</code> the
+     * filed <code>signatureValue</code> must be set
+     * 
+     * @param doc
+     *            The SOAP envelope as W3C document
+     */
+    public void prepare(Document doc) {
+        document = doc;
+        sc = new SignatureConfirmation(doc, signatureValue);
+        String scId = "SigConf-" + sc.hashCode();
+        sc.setID(scId);
+    }
+    
+    /**
+     * Prepends the SignatureConfirmation element to the elements already in the
+     * Security header.
+     * 
+     * The method can be called any time after <code>prepare()</code>.
+     * This allows to insert the SignatureConfirmation element at any position in the
+     * Security header.
+     * 
+     * @param secHeader
+     *            The security header that holds the Signature element.
+     */
+    public void prependToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader
+                .getSecurityHeader(), sc.getElement(), false);
+    }
+    
+    /**
+     * Adds a new <code>SignatureConfirmation</code> to a soap envelope.
+     * 
+     * A complete <code>SignatureConfirmation</code> is constructed and added
+     * to the <code>wsse:Security</code> header.
+     * 
+     * @param doc
+     *            The SOAP envelope as W3C document
+     * @param sigVal
+     *            the Signature value. This will be the content of the "Value"
+     *            attribute.
+     * @param secHeader
+     *            The security header that holds the Signature element.
+    * @return Document with SignatureConfirmation added
+     */
+    public Document build(Document doc, byte[] sigVal, WSSecHeader secHeader) {
+        log.debug("Begin add signature confirmation...");
+        
+        signatureValue = sigVal;
+        prepare(doc);
+        prependToHeader(secHeader);
+        
+        return doc;
+    }
+
+    /**
+     * Get the id generated during <code>prepare()</code>.
+     * 
+     * Returns the the value of wsu:Id attribute of this SignatureConfirmation. 
+     * 
+     * @return Return the wsu:Id of this token or null if <code>prepareToken()</code>
+     * was not called before.
+     */
+    public String getId() {
+        if (sc == null) {
+            return null;
+        }
+        return sc.getID();
+    }
+    
+    /**
+     * Get the SignatureConfirmation element generated during 
+     * <code>prepare()</code>.
+     * 
+     * @return Return the SignatureConfirmation element or null if <code>prepare()</code>
+     * was not called before.
+     */
+    public Element getSignatureConfirmationElement() {
+        return (this.sc != null) ? this.sc.getElement() : null;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecTimestamp.java b/trunk/src/org/apache/ws/security/message/WSSecTimestamp.java
new file mode 100644
index 0000000..485aaad
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecTimestamp.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.message.token.Timestamp;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Builds a WS Timestamp and inserts it into the SOAP Envelope. Refer to the WS
+ * specification 1.0. chapter 10 / appendix A.2
+ * 
+ * @author Christof Soehngen (Christof.Soehngen@syracom.de).
+ * @author Werner Dittmann (werner@apache.org).
+ */
+
+public class WSSecTimestamp extends WSSecBase {
+    private static Log log = LogFactory.getLog(WSSecTimestamp.class.getName());
+
+    private Timestamp ts = null;
+
+    private Document document = null;
+
+    private int timeToLive = 300; // time between Created and Expires
+
+    /**
+     * Constructor.
+     */
+    public WSSecTimestamp() {
+    }
+
+    /**
+     * Set the time to live. This is the time difference in seconds between the
+     * <code>Created</code> and the <code>Expires</code> in
+     * <code>Timestamp</code>. <p/>
+     * 
+     * @param ttl
+     *            The time to live in second
+     */
+    public void setTimeToLive(int ttl) {
+        timeToLive = ttl;
+    }
+
+    /**
+     * Creates a Timestamp element.
+     * 
+     * The method prepares and initializes a WSSec Timestamp structure after the
+     * relevant information was set. Before calling <code>prepare()</code> the
+     * parameter such as <code>timeToLive</code> can be set if the deafult
+     * value is not suitable.
+     * 
+     * @param doc
+     *            The SOAP enevlope as W3C document
+     */
+    public void prepare(Document doc) {
+        document = doc;
+        ts = new Timestamp(wssConfig.isPrecisionInMilliSeconds(), doc,
+                timeToLive);
+        String tsId = "Timestamp-" + ts.hashCode();
+        ts.setID(tsId);
+    }
+
+    /**
+     * Prepends the Timestamp element to the elements already in the Security
+     * header.
+     * 
+     * The method can be called any time after <code>prepare()</code>. This
+     * allows to insert the Timestamp element at any position in the Security
+     * header.
+     * 
+     * @param secHeader
+     *            The security header that holds the Signature element.
+     */
+    public void prependToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader
+                .getSecurityHeader(), ts.getElement(), false);
+    }
+
+    /**
+     * Adds a new <code>Timestamp</code> to a soap envelope.
+     * 
+     * A complete <code>Timestamp</code> is constructed and added to the
+     * <code>wsse:Security</code> header.
+     * 
+     * @param doc
+     *            The SOAP envelope as W3C document
+     * @param secHeader
+     *            The security header that hold this Timestamp
+     * @return Document with Timestamp added
+     * @throws Exception
+     */
+    public Document build(Document doc, WSSecHeader secHeader) {
+        log.debug("Begin add timestamp...");
+
+        prepare(doc);
+        prependToHeader(secHeader);
+
+        return doc;
+    }
+
+    /**
+     * Get the id generated during <code>prepare()</code>.
+     * 
+     * Returns the the value of wsu:Id attribute of this Timestamp.
+     * 
+     * @return Return the wsu:Id of this token or null if
+     *         <code>prepareToken()</code> was not called before.
+     */
+    public String getId() {
+        if (ts == null) {
+            return null;
+        }
+        return ts.getID();
+    }
+    
+    /**
+     * Get the timestamp element generated during <code>prepare()</code>.
+     */
+    public Element getElement() {
+        if (ts == null) {
+            return null;
+        }
+        return ts.getElement();
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSecUsernameToken.java b/trunk/src/org/apache/ws/security/message/WSSecUsernameToken.java
new file mode 100644
index 0000000..f4621d7
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSecUsernameToken.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Builds a WS UsernameToken.
+ * 
+ * Refer to the WS specification, UsernameToken profile
+ * 
+ * @author Werner Dittmann (werner@apache.org).
+ */
+
+public class WSSecUsernameToken extends WSSecBase {
+    private static Log log = LogFactory.getLog(WSSecUsernameToken.class
+            .getName());
+
+    private String passwordType = WSConstants.PASSWORD_DIGEST;
+
+    private UsernameToken ut = null;
+
+    private boolean nonce = false;
+
+    private boolean created = false;
+    
+    private boolean useDerivedKey = false;
+    
+    private boolean useMac = false;
+    
+    private byte[] saltValue;
+    
+    private int iteration = UsernameToken.DEFAULT_ITERATION;
+
+    private Document document = null;
+
+    /**
+     * Constructor.
+     */
+    public WSSecUsernameToken() {
+    }
+
+    /**
+     * Defines how to construct the password element of the
+     * <code>UsernameToken</code>.
+     * 
+     * @param pwType
+     *            contains the password type. Only allowed values are
+     *            {@link WSConstants#PASSWORD_DIGEST} and
+     *            {@link WSConstants#PASSWORD_TEXT}.
+     *            or null when no password is needed.
+     */
+    public void setPasswordType(String pwType) {
+        this.passwordType = pwType;
+    }
+
+    /**
+     * Add a Nonce element to the UsernameToken.
+     */
+    public void addNonce() {
+        nonce = true;
+    }
+
+    /**
+     * Add a Created element to the UsernameToken.
+     */
+    public void addCreated() {
+        created = true;
+    }
+    
+    /**
+     * Add a derived key to the UsernameToken
+     * @param useMac whether the derived key is to be used for a MAC or not
+     * @param saltValue The saltvalue to use
+     * @param iteration The number of iterations to use in deriving a key
+     */
+    public void addDerivedKey(boolean useMac, byte[] saltValue, int iteration) {
+        passwordType = null;
+        useDerivedKey = true;
+        this.useMac = useMac;
+        this.saltValue = saltValue;
+        if (iteration > 0) {
+            this.iteration = iteration;
+        }
+    }
+
+    
+    /**
+     * Get the derived secret key.
+     * 
+     * After the <code>prepare()</code> method was called use this method
+     * to compute a derived secret key. The generation of this secret key is according
+     * to WS-Trust specification.
+     * 
+     * @return Return the derived secret key of this token or null if <code>prepare()</code>
+     * was not called before.
+     */
+    public byte[] getSecretKey() {
+        if (ut == null) {
+            return null;
+        }
+        return ut.getSecretKey();
+    }
+    
+    /**
+     * Get the derived key.
+     * 
+     * After the <code>prepare()</code> method was called use this method
+     * to compute a derived key. The generation of this secret key is according
+     * to the UsernameTokenProfile 1.1 specification (section 4 - Key Derivation).
+     * 
+     * @return Return the derived key of this token or null if <code>prepare()</code>
+     * was not called before.
+     */
+    public byte[] getDerivedKey() throws WSSecurityException {
+        if (ut == null || !useDerivedKey) {
+            return null;
+        }
+        return UsernameToken.generateDerivedKey(password, saltValue, iteration);
+    }
+
+    /**
+     * Get the id generated during <code>prepare()</code>.
+     * 
+     * Returns the the value of wsu:Id attribute of this UsernameToken. 
+     * 
+     * @return Return the wsu:Id of this token or null if <code>prepare()</code>
+     * was not called before.
+     */
+    public String getId() {
+        if (ut == null) {
+            return null;
+        }
+        return ut.getID();
+    }
+
+    /**
+     * Creates a Username token.
+     * 
+     * The method prepares and initializes a WSSec UsernameToken structure after
+     * the relevant information was set. A Before calling
+     * <code>prepare()</code> all parameters such as user, password,
+     * passwordType etc. must be set. A complete <code>UsernameToken</code> is
+     * constructed.
+     * 
+     * @param doc
+     *            The SOAP envelope as W3C document
+     */
+    public void prepare(Document doc) {
+        document = doc;
+        ut = new UsernameToken(wssConfig.isPrecisionInMilliSeconds(), doc,
+                passwordType);
+        ut.setName(user);
+        if (useDerivedKey) {
+            saltValue = ut.addSalt(doc, saltValue, useMac);
+            ut.addIteration(doc, iteration);
+        } else {
+            ut.setPassword(password);
+        }
+        if (nonce) {
+            ut.addNonce(doc);
+        }
+        if (created) {
+            ut.addCreated(wssConfig.isPrecisionInMilliSeconds(), doc);
+        }
+        String utId = "UsernameToken-" + ut.hashCode();
+        ut.setID(utId);
+    }
+
+    /**
+     * Prepends the UsernameToken element to the elements already in the
+     * Security header.
+     * 
+     * The method can be called any time after <code>prepare()</code>.
+     * This allows to insert the UsernameToken element at any position in the
+     * Security header.
+     * 
+     * @param secHeader
+     *            The security header that holds the Signature element.
+     */
+    public void prependToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.prependChildElement(document, secHeader
+                .getSecurityHeader(), ut.getElement(), false);
+    }
+
+    /**
+     * Appends the UsernameToken element to the elements already in the
+     * Security header.
+     * 
+     * The method can be called any time after <code>prepare()</code>.
+     * This allows to insert the UsernameToken element at any position in the
+     * Security header.
+     * 
+     * @param secHeader
+     *            The security header that holds the Signature element.
+     */
+    public void appendToHeader(WSSecHeader secHeader) {
+        WSSecurityUtil.appendChildElement(document, secHeader
+                .getSecurityHeader(), ut.getElement());
+    }
+    /**
+     * Adds a new <code>UsernameToken</code> to a soap envelope.
+     * 
+     * Before calling <code>build()</code> all parameters such as user,
+     * password, passwordType etc. must be set. A complete
+     * <code>UsernameToken</code> is constructed and added to the
+     * <code>wsse:Security</code> header.
+     * 
+     * @param doc
+     *            The SOAP envelope as W3C document
+     * @param secHeader
+     *            The security header inside the SOAP envelope
+     * @return Document with UsernameToken added
+     */
+    public Document build(Document doc, WSSecHeader secHeader) {
+        log.debug("Begin add username token...");
+
+        prepare(doc);
+        prependToHeader(secHeader);
+
+        return doc;
+    }
+
+    /**
+     * Returns the <code>UsernameToken</code> element.
+     * 
+     * The method can be called any time after <code>prepare()</code>.
+     * This allows to insert the UsernameToken element at any position in the
+     * Security header.
+     * 
+     * @return the Username Token element
+     */
+    public Element getUsernameTokenElement() {
+       return this.ut.getElement(); 
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java b/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java
new file mode 100644
index 0000000..c0d8332
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/WSSignEnvelope.java
@@ -0,0 +1,648 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSDocInfoStore;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.PKIPathSecurity;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.saml.SAMLUtil;
+import org.apache.ws.security.transform.STRTransform;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.algorithms.SignatureAlgorithm;
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.signature.XMLSignatureException;
+import org.apache.xml.security.transforms.TransformationException;
+import org.apache.xml.security.transforms.Transforms;
+import org.apache.xml.security.transforms.params.InclusiveNamespaces;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xml.security.utils.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import java.security.cert.X509Certificate;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ * Signs a SOAP envelope according to WS Specification, X509 profile, and adds
+ * the signature data.
+ *
+ * @author Davanum Srinivas (dims@yahoo.com)
+ * @author Werner Dittmann (Werner.Dittman@siemens.com)
+ */
+public class WSSignEnvelope extends WSBaseMessage {
+
+    private static Log log = LogFactory.getLog(WSSignEnvelope.class.getName());
+
+    private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
+
+    protected boolean useSingleCert = true;
+
+    protected String sigAlgo = null;
+
+    protected String canonAlgo = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
+
+    protected WSSAddUsernameToken usernameToken = null;
+
+    protected byte[] signatureValue = null;
+
+    /**
+     * Constructor.
+     * @deprecated replaced by {@link WSSecSignature#WSSecSignature()}
+     */
+    public WSSignEnvelope() {
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param actor The actor name of the <code>wsse:Security</code> header
+     * 
+     * @deprecated replaced by {@link WSSecSignature#WSSecSignature()}
+     *             and {@link WSSecHeader} for actor specification.
+     */
+    public WSSignEnvelope(String actor) {
+        super(actor);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param actor The actor name of the <code>wsse:Security</code> header
+     * @param mu    Set <code>mustUnderstand</code> to true or false
+     * 
+     * @deprecated replaced by {@link WSSecSignature#WSSecSignature()}
+     *             and {@link WSSecHeader} for actor and mustunderstand
+     *             specification.
+     */
+    public WSSignEnvelope(String actor, boolean mu) {
+        super(actor, mu);
+    }
+
+    /**
+     * set the single cert flag.
+     *
+     * @param useSingleCert
+     * @deprecated replaced by {@link WSSecSignature#setUseSingleCertificate(boolean)}
+     */
+    public void setUseSingleCertificate(boolean useSingleCert) {
+        this.useSingleCert = useSingleCert;
+    }
+
+    /**
+     * Get the single cert flag.
+     *
+     * @return If to use a single cert
+     * @deprecated replaced by {@link WSSecSignature#isUseSingleCertificate()}
+     */
+    public boolean isUseSingleCertificate() {
+        return this.useSingleCert;
+    }
+
+    /**
+     * Set the name of the signature encryption algorithm to use.
+     *
+     * If the algorithm is not set then Triple RSA is used. Refer to WSConstants
+     * which algorithms are supported.
+     *
+     * @param algo
+     *            Is the name of the signature algorithm
+     * @see WSConstants#RSA
+     * @see WSConstants#DSA
+     * @deprecated replaced by {@link WSSecSignature#setSignatureAlgorithm(String)}
+     */
+    public void setSignatureAlgorithm(String algo) {
+        sigAlgo = algo;
+    }
+
+    /**
+     * Get the name of the signature algorithm that is being used.
+     *
+     * If the algorithm is not set then RSA is default.
+     *
+     * @return the identifier URI of the signature algorithm
+     * @deprecated replaced by {@link WSSecSignature#getSignatureAlgorithm()}
+     */
+    public String getSignatureAlgorithm() {
+        return sigAlgo;
+    }
+
+    /**
+     * Set the canonicalization method to use.
+     *
+     * If the canonicalization method is not set then the recommended Exclusive
+     * XML Canonicalization is used by default Refer to WSConstants which
+     * algorithms are supported.
+     *
+     * @param algo
+     *            Is the name of the signature algorithm
+     * @see WSConstants#C14N_OMIT_COMMENTS
+     * @see WSConstants#C14N_WITH_COMMENTS
+     * @see WSConstants#C14N_EXCL_OMIT_COMMENTS
+     * @see WSConstants#C14N_EXCL_WITH_COMMENTS
+     * @deprecated replaced by {@link WSSecSignature#setSigCanonicalization(String)}
+     */
+    public void setSigCanonicalization(String algo) {
+        canonAlgo = algo;
+    }
+
+    /**
+     * Get the canonicalization method.
+     *
+     * If the canonicalization method was not set then Exclusive XML
+     * Canonicalization is used by default.
+     *
+     * @return TODO
+     * @deprecated replaced by {@link WSSecSignature#getSigCanonicalization()}
+     */
+    public String getSigCanonicalization() {
+        return canonAlgo;
+    }
+
+    /**
+     * @param usernameToken The usernameToken to set.
+     * @deprecated replaced by {@link WSSecSignature#setUsernameToken(WSSecUsernameToken)}
+     */
+    public void setUsernameToken(WSSAddUsernameToken usernameToken) {
+        this.usernameToken = usernameToken;
+    }
+
+    /**
+     * @return Returns the signatureValue.
+     * @deprecated replaced by {@link WSSecSignature#getSignatureValue()}
+     */
+    public byte[] getSignatureValue() {
+        return signatureValue;
+    }
+
+    /**
+     * Builds a signed soap envelope.
+     *
+     * The method first gets an appropriate
+     * security header. According to the defined parameters for certificate
+     * handling the signature elements are constructed and inserted into the
+     * <code>wsse:Signature</code>
+     *
+     * @param doc    The unsigned SOAP envelope as <code>Document</code>
+     * @param crypto An instance of the Crypto API to handle keystore and
+     *               certificates
+     * @return A signed SOAP envelope as <code>Document</code>
+     * @throws WSSecurityException
+     * @deprecated replaced by {@link WSSecSignature#build(Document, Crypto, WSSecHeader)}
+     */
+    public Document build(Document doc, Crypto crypto)
+            throws WSSecurityException {
+        doDebug = log.isDebugEnabled();
+
+        long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
+        if (tlog.isDebugEnabled()) {
+            t0 = System.currentTimeMillis();
+        }
+        if (doDebug) {
+            log.debug("Beginning signing...");
+        }
+
+        /*
+         * Gather some info about the document to process and store it for
+         * retrieval
+         */
+        WSDocInfo wsDocInfo = new WSDocInfo(doc.hashCode());
+        wsDocInfo.setCrypto(crypto);
+
+        Element envelope = doc.getDocumentElement();
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+
+        Element securityHeader = insertSecurityHeader(doc);
+
+        // Set the id of the elements to be used as digest source
+        // String id = setBodyID(doc);
+        String certUri = null;
+        X509Certificate[] certs = null;
+        if (keyIdentifierType != WSConstants.UT_SIGNING) {
+            certs = crypto.getCertificates(user);
+            if (certs == null || certs.length <= 0) {
+                throw new WSSecurityException(
+                    WSSecurityException.FAILURE,
+                    "noUserCertsFound", 
+                    new Object[] { user, "signature" }
+                );
+            }
+            certUri = "CertId-" + certs[0].hashCode();
+            if (sigAlgo == null) {
+                String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm();
+                log.debug("automatic sig algo detection: " + pubKeyAlgo);
+                if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
+                    sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+                } else if (pubKeyAlgo.equalsIgnoreCase("RSA")) {
+                    sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
+                } else {
+                    throw new WSSecurityException(
+                        WSSecurityException.FAILURE,
+                        "unknownSignatureAlgorithm",
+                        new Object[] {
+                            pubKeyAlgo
+                        }
+                    );
+                }
+            }
+        }
+        XMLSignature sig = null;
+
+        if (canonAlgo.equals(WSConstants.C14N_EXCL_OMIT_COMMENTS)) {
+            Element canonElem = XMLUtils.createElementInSignatureSpace(doc,
+                    Constants._TAG_CANONICALIZATIONMETHOD);
+
+            canonElem.setAttributeNS(null, Constants._ATT_ALGORITHM, canonAlgo);
+
+            if (wssConfig.isWsiBSPCompliant()) {
+                Set prefixes = getInclusivePrefixes(securityHeader, false);
+
+                InclusiveNamespaces inclusiveNamespaces = new InclusiveNamespaces(
+                        doc, prefixes);
+
+                canonElem.appendChild(inclusiveNamespaces.getElement());
+            }
+
+            try {
+                SignatureAlgorithm signatureAlgorithm = new SignatureAlgorithm(
+                        doc, sigAlgo);
+                sig = new XMLSignature(doc, null, signatureAlgorithm
+                        .getElement(), canonElem);
+            } catch (XMLSecurityException e) {
+                log.error("", e);
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e
+                );
+            }
+        } else {
+            try {
+                sig = new XMLSignature(doc, null, sigAlgo, canonAlgo);
+            } catch (XMLSecurityException e) {
+                log.error("", e);
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e
+                );
+            }
+        }
+        /*
+         * If we don't generate a new Transforms for each addDocument here, then
+         * only the last Transforms is put into the according ds:Reference
+         * element, i.e. the first ds:Reference does not contain a Transforms
+         * element. Thus the verification fails (somehow)
+         */
+
+        KeyInfo info = sig.getKeyInfo();
+        String keyInfoUri = "KeyId-" + info.hashCode();
+        info.setId(keyInfoUri);
+
+        SecurityTokenReference secRef = new SecurityTokenReference(doc);
+        String strUri = "STRId-" + secRef.hashCode();
+        secRef.setID(strUri);
+
+        if (tlog.isDebugEnabled()) {
+            t1 = System.currentTimeMillis();
+        }
+
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+
+        Transforms transforms = null;
+
+        for (int part = 0; part < parts.size(); part++) {
+            WSEncryptionPart encPart = (WSEncryptionPart) parts.get(part);
+
+            String idToSign = encPart.getId();
+
+            String elemName = encPart.getName();
+            String nmSpace = encPart.getNamespace();
+
+            /*
+             * Set up the elements to sign. There are two reserved element
+             * names: "Token" and "STRTransform" "Token": Setup the Signature to
+             * either sign the information that points to the security token or
+             * the token itself. If its a direct reference sign the token,
+             * otherwise sign the KeyInfo Element. "STRTransform": Setup the
+             * ds:Reference to use STR Transform
+             *
+             */
+            try {
+                if (idToSign != null) {
+                    Element toSignById = WSSecurityUtil
+                            .findElementById(doc.getDocumentElement(),
+                                    idToSign, WSConstants.WSU_NS);
+                    if (toSignById == null) {
+                        toSignById = WSSecurityUtil.findElementById(doc
+                                .getDocumentElement(), idToSign, null);
+                    }
+                    transforms = new Transforms(doc);
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(doc,
+                                        getInclusivePrefixes(toSignById))
+                                        .getElement());
+                    }
+                    sig.addDocument("#" + idToSign, transforms);
+                }
+                else if (elemName.equals("Token")) {
+                    transforms = new Transforms(doc);
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (keyIdentifierType == WSConstants.BST_DIRECT_REFERENCE) {
+                        if (wssConfig.isWsiBSPCompliant()) {
+                            transforms
+                                    .item(0)
+                                    .getElement()
+                                    .appendChild(
+                                            new InclusiveNamespaces(
+                                                    doc,
+                                                    getInclusivePrefixes(securityHeader))
+                                                    .getElement());
+                        }
+                        sig.addDocument("#" + certUri, transforms);
+                    } else {
+                        if (wssConfig.isWsiBSPCompliant()) {
+                            transforms.item(0).getElement().appendChild(
+                                    new InclusiveNamespaces(doc,
+                                            getInclusivePrefixes(info
+                                                    .getElement()))
+                                            .getElement());
+                        }
+                        sig.addDocument("#" + keyInfoUri, transforms);
+                    }
+                } else if (elemName.equals("STRTransform")) { // STRTransform
+                    Element ctx = createSTRParameter(doc);
+                    transforms = new Transforms(doc);
+                    transforms.addTransform(
+                            STRTransform.implementedTransformURI, ctx);
+                    sig.addDocument("#" + strUri, transforms);
+                } else if (elemName.equals("Assertion")) { // Assertion
+
+                    String id = null;
+                    id = SAMLUtil.getAssertionId(envelope, elemName, nmSpace);
+
+                    Element body = (Element) WSSecurityUtil.findElement(
+                            envelope, elemName, nmSpace);
+                    if (body == null) {
+                        throw new WSSecurityException(
+                                WSSecurityException.FAILURE, "noEncElement",
+                                new Object[] { nmSpace + ", " + elemName });
+                    }
+                    transforms = new Transforms(doc);
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(doc,
+                                        getInclusivePrefixes(body))
+                                        .getElement());
+                    }
+                    String prefix = WSSecurityUtil.setNamespace(body,
+                            WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+                    body.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id",
+                            id);
+                    sig.addDocument("#" + id, transforms);
+
+                } else {
+                    Element body = (Element) WSSecurityUtil.findElement(
+                            envelope, elemName, nmSpace);
+                    if (body == null) {
+                        throw new WSSecurityException(
+                                WSSecurityException.FAILURE, "noEncElement",
+                                new Object[] { nmSpace + ", " + elemName });
+                    }
+                    transforms = new Transforms(doc);
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(doc,
+                                        getInclusivePrefixes(body))
+                                        .getElement());
+                    }
+                    sig.addDocument("#" + setWsuId(body), transforms);
+                }
+            } catch (TransformationException e1) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null,
+                        e1);
+            } catch (XMLSignatureException e1) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null,
+                        e1);
+            }
+        }
+
+        sig.addResourceResolver(EnvelopeIdResolver.getInstance());
+
+        WSSecurityUtil.prependChildElement(doc, securityHeader, sig
+                .getElement(), false);
+        if (tlog.isDebugEnabled()) {
+            t2 = System.currentTimeMillis();
+        }
+
+        byte[] secretKey = null;
+        switch (keyIdentifierType) {
+        case WSConstants.BST_DIRECT_REFERENCE:
+            Reference ref = new Reference(doc);
+            ref.setURI("#" + certUri);
+            BinarySecurity bstToken = null;
+            if (!useSingleCert) {
+                bstToken = new PKIPathSecurity(doc);
+                ((PKIPathSecurity) bstToken).setX509Certificates(certs, false,
+                        crypto);
+            } else {
+                bstToken = new X509Security(doc);
+                ((X509Security) bstToken).setX509Certificate(certs[0]);
+            }
+            ref.setValueType(bstToken.getValueType());
+            secRef.setReference(ref);
+            bstToken.setID(certUri);
+            WSSecurityUtil.prependChildElement(doc, securityHeader, bstToken
+                    .getElement(), false);
+            wsDocInfo.setBst(bstToken.getElement());
+            break;
+
+        case WSConstants.ISSUER_SERIAL:
+            XMLX509IssuerSerial data = new XMLX509IssuerSerial(doc, certs[0]);
+            X509Data x509Data = new X509Data(doc);
+            x509Data.add(data);
+            secRef.setX509IssuerSerial(x509Data);
+            break;
+
+        case WSConstants.X509_KEY_IDENTIFIER:
+            secRef.setKeyIdentifier(certs[0]);
+            break;
+
+        case WSConstants.SKI_KEY_IDENTIFIER:
+            secRef.setKeyIdentifierSKI(certs[0], crypto);
+            break;
+
+        case WSConstants.UT_SIGNING:
+            Reference refUt = new Reference(doc);
+            refUt.setValueType(WSConstants.USERNAMETOKEN_NS + "#UsernameToken");
+            String utId = usernameToken.getId();
+            if (utId == null) {
+                utId = "usernameTokenId-" + usernameToken.hashCode();
+                usernameToken.setId(utId);
+            }
+            refUt.setURI("#" + utId);
+            secRef.setReference(refUt);
+            secretKey = usernameToken.getSecretKey();
+            break;
+
+        case WSConstants.THUMBPRINT_IDENTIFIER:
+            secRef.setKeyIdentifierThumb(certs[0]);
+            break;
+
+        default:
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unsupportedKeyId");
+        }
+        if (tlog.isDebugEnabled()) {
+            t3 = System.currentTimeMillis();
+        }
+        info.addUnknownElement(secRef.getElement());
+
+        WSDocInfoStore.store(wsDocInfo);
+        try {
+            if (keyIdentifierType == WSConstants.UT_SIGNING) {
+                sig.sign(sig.createSecretKey(secretKey));
+            } else {
+                sig.sign(crypto.getPrivateKey(user, password));
+            }
+            signatureValue = sig.getSignatureValue();
+        } catch (XMLSignatureException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } catch (Exception e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } finally {
+            WSDocInfoStore.delete(wsDocInfo);
+        }
+        if (tlog.isDebugEnabled()) {
+            t4 = System.currentTimeMillis();
+            tlog.debug("SignEnvelope: cre-Sig= " + (t1 - t0)
+                    + " set transform= " + (t2 - t1) + " sec-ref= " + (t3 - t2)
+                    + " signature= " + (t4 - t3));
+        }
+        if (doDebug) {
+            log.debug("Signing complete.");
+        }
+        return (doc);
+    }
+
+    protected Element createSTRParameter(Document doc) {
+        Element transformParam = doc.createElementNS(WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX + ":TransformationParameters");
+
+        WSSecurityUtil.setNamespace(transformParam, WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX);
+
+        Element canonElem = doc.createElementNS(WSConstants.SIG_NS,
+                WSConstants.SIG_PREFIX + ":CanonicalizationMethod");
+
+        WSSecurityUtil.setNamespace(canonElem, WSConstants.SIG_NS,
+                WSConstants.SIG_PREFIX);
+
+        canonElem.setAttributeNS(null, "Algorithm",
+                Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+        transformParam.appendChild(canonElem);
+        return transformParam;
+    }
+
+    protected Set getInclusivePrefixes(Element target) {
+        return getInclusivePrefixes(target, true);
+    }
+
+    protected Set getInclusivePrefixes(Element target, boolean excludeVisible) {
+        Set result = new HashSet();
+        Node parent = target;
+        NamedNodeMap attributes;
+        Node attribute;
+        while (!(parent.getParentNode() instanceof Document)) {
+            parent = parent.getParentNode();
+            attributes = parent.getAttributes();
+            for (int i = 0; i < attributes.getLength(); i++) {
+                attribute = attributes.item(i);
+                if (attribute.getNamespaceURI() != null
+                        && attribute.getNamespaceURI().equals(
+                                org.apache.ws.security.WSConstants.XMLNS_NS)) {
+                    if (attribute.getNodeName().equals("xmlns")) {
+                        result.add("#default");
+                    } else {
+                        result.add(attribute.getLocalName());
+                    }
+                }
+            }
+        }
+
+        if (excludeVisible == true) {
+            attributes = target.getAttributes();
+            for (int i = 0; i < attributes.getLength(); i++) {
+                attribute = attributes.item(i);
+                if (attribute.getNamespaceURI() != null
+                        && attribute.getNamespaceURI().equals(
+                                org.apache.ws.security.WSConstants.XMLNS_NS)) {
+                    if (attribute.getNodeName().equals("xmlns")) {
+                        result.remove("#default");
+                    } else {
+                        result.remove(attribute.getLocalName());
+                    }
+                }
+                if (attribute.getPrefix() != null) {
+                    result.remove(attribute.getPrefix());
+                }
+            }
+
+            if (target.getPrefix() == null) {
+                result.remove("#default");
+            } else {
+                result.remove(target.getPrefix());
+            }
+        }
+
+        return result;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/package.html b/trunk/src/org/apache/ws/security/message/package.html
new file mode 100644
index 0000000..a5ab68a
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/package.html
@@ -0,0 +1,149 @@
+<!-- <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+  -->

+<html>

+<head>

+  <title>Web Service Security classes for message creation</title>

+<!--

+

+  @(#)Web Service Security classes for message creation 

+

+/*

+ * Copyright  2003-2004 The Apache Software Foundation.

+ *

+ *  Licensed 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.

+ *

+ */

+-->

+</head>

+<body bgcolor="white">

+

+The package provides classes to create messages that are compliant to the

+OASIS Web Service Security specifications.

+<p/>

+The OASIS WSS specifications define a number of features and it is possible 

+to combine them in several ways. The WSS4J classes already support 

+a large number of WSS features and their combinations. 

+<a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss">

+Here</a> are the WSS specifications.

+<p/>

+Currently this package contains two sets of classes that provide the same 

+or similar functionality. 

+<ul>

+  <li>The old classes, named WSAdd*, WSEncryptBody, WSSignEnvelope, WSBaseMessage.

+  The usage of these classes is depreciated.</li>

+  <li>The new, refactored classes. Their names start with the prefix <e>WSSec</e>.

+</ul>

+

+<h3>How to use the WSSec* classes</h3>

+The new refactored classes follow the same usage pattern. 

+<ol type="1">

+  <li>Create an object for the required security element, for example a 

+  <code>WSSecSignature</code>.

+  </li>

+  <li>Set the required fields using setter methods, for example user name, signature

+  algorithm, etc.

+  </li>

+  <li>After the fields are set call <code>prepare(...)</code>. This initializes the internal

+  structures, gets the required data like X509 tokens, etc.

+  </li>

+  <li>After preparation you may do security element specific functions, for example add

+  data refernces that should be included in the signature. You can also add the element to

+  the <code>WSSecHeader</code> at this time (adding to the security header can be done at any

+  time after <code>prepare(...)</code>). See the documentation of the various classes what is

+  available.

+  </li>

+</ol>

+In contrast to the old classes the handling of the security header is not longer

+implicitly performed. To provide better flexibilty the class <code>WSSecHeader</code>

+deals with the security header.

+<p/>

+The new structure of the classes provide a much more flxible handling of the actions

+performed by the classes. This enhanced flexibility enables a precise control of

+the placement of security elements in the security header and a much better control

+which elements to sign or to encrypt.

+<p/>

+This code snippet shows how to setup a Signature element:

+<pre>

+        /*

+         * Explicit security header handling. The WSSecHeader object

+         * remains the same for all elements that shall go into this

+         * security header. Thus you usually need to created one

+         * WSSecHeader object only.

+         */

+        WSSecHeader secHeader = new WSSecHeader();

+        secHeader.insertSecurityHeader(doc);

+

+

+        WSSecSignature builder = new WSSecSignature();

+

+        builder.setUserInfo("username", "password");

+        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);

+

+        Document doc = getSOAPEnvelope();

+

+		builder.prepare(doc, crypto, secHeader);

+

+		/*

+		 * Set parts to sign

+		 */

+		Vector parts = new Vector();

+		WSEncryptionPart encP = new WSEncryptionPart(localName, namespace, "Content");

+		parts.add(encP);

+

+		/*

+		 * Add the references to include into Signature. This can be done multiple

+		 * times.

+		 */

+		builder.addReferencesToSign(parts, secHeader);

+

+		/*

+		 * Add the Signature now to the security header

+		 */

+		builder.prependToHeader(secHeader);

+

+		/*

+		 * There maybe a BST to prepend it in front of the Signature according to

+		 * strict layout rules.

+		 */

+		builder.prependBSTElementToHeader(secHeader);

+

+		/*

+		 * Before calling computeSignature make sure all elements to sign are

+		 * available in the document (SOAP Envelope)

+		 */

+		builder.computeSignature();

+

+</pre>

+Each new class also contains a <code>build()</code> method that is similar to the

+<code>build()</code> method in the old classes. Thus, if the flexibilty is not

+required you may use this method for convenience.

+

+<h3>Each top level security element has wsu:Id or plain Id attribute</h3>

+The <code>prepare()</code> method autmatically generates an Id string for each new

+element and sets the wsu:Id or plain Id attribute. Which type 

+of Id to use is determined by the security element. The <e>EncryptedKey</e> and <e>Signature</e> 

+elements have a plain Id according to the W3C specifications, elements defined by 

+the OASIS WS Security specifications contain a wsu:Id. 

+<p/>

+Each <code>WSSec*</code> class has a <code>getId()</code> that returns the id strig

+regardless if its qualified or not.

+<p/>

+The security processing uses these Id to identify each top level security element to

+provide additional further processing of an element, for example to encrypt a Signature or

+any other top level element. Also a Signature may include each top level element. Which

+parts of a message to sign and/or encrypt is controlled by the Security Policy

+

+@since WSS4J 2.0

+</body>

+</html>

diff --git a/trunk/src/org/apache/ws/security/message/token/BinarySecurity.java b/trunk/src/org/apache/ws/security/message/token/BinarySecurity.java
new file mode 100644
index 0000000..5477ae6
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/BinarySecurity.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message.token;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.util.DOM2Writer;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.Base64;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Binary Security Token.
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com).
+ * @author Werner Dittmann (Werner.Dittmann@t-onile.de).
+ */
+public class BinarySecurity {
+    public static final QName TOKEN_BST = new QName(WSConstants.WSSE_NS, "BinarySecurityToken");
+    public static final QName TOKEN_KI = new QName(WSConstants.WSSE_NS, "KeyIdentifier");
+    public static final String BASE64_ENCODING = WSConstants.SOAPMESSAGE_NS + "#Base64Binary";
+    protected Element element = null;
+
+    /**
+     * Constructor.
+     * <p/>
+     * 
+     * @param elem 
+     * @throws WSSecurityException 
+     */
+    public BinarySecurity(Element elem) throws WSSecurityException {
+        this.element = elem;
+        QName el = new QName(this.element.getNamespaceURI(), this.element
+                .getLocalName());
+        if (!el.equals(TOKEN_BST) && !el.equals(TOKEN_KI)) {
+            throw new WSSecurityException(
+                    WSSecurityException.INVALID_SECURITY_TOKEN, "badTokenType",
+                    new Object[] { el });
+        }
+        String encoding = getEncodingType();
+        /*
+         * if the Element is a BinarySecurityToken then
+         *     encoding may be null -> default is Base64
+         *     if encoding is not null and not empty it must be Base64
+         * else
+         *     this is a keyidentifier element
+         *     must contain an encoding attribute which must be Base64
+         *     in this case
+         */
+        if (el.equals(TOKEN_BST)) {
+            if (encoding != null && encoding.length() > 0
+                    && !encoding.equals(BASE64_ENCODING)) {
+                throw new WSSecurityException(
+                        WSSecurityException.INVALID_SECURITY_TOKEN,
+                        "badEncoding", new Object[] { encoding });
+            }
+        } else if (el.equals(TOKEN_KI)) {
+            if (encoding == null || !encoding.equals(BASE64_ENCODING)) {
+                throw new WSSecurityException(
+                        WSSecurityException.INVALID_SECURITY_TOKEN,
+                        "badEncoding", new Object[] { encoding });
+            }
+        }
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param doc 
+     */
+    public BinarySecurity(Document doc) {
+        this.element = doc.createElementNS(WSConstants.WSSE_NS, "wsse:BinarySecurityToken");
+        WSSecurityUtil.setNamespace(this.element, WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);
+        setEncodingType(BASE64_ENCODING);
+        this.element.appendChild(doc.createTextNode(""));
+    }
+
+    /**
+     * get the value type.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public String getValueType() {
+        return this.element.getAttribute("ValueType");
+    }
+
+    /**
+     * set the value type.
+     * <p/>
+     * 
+     * @param type 
+     */
+    protected void setValueType(String type) {
+        this.element.setAttributeNS(null, "ValueType", type);
+    }
+
+    /**
+     * get the encoding type.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public String getEncodingType() {
+        return this.element.getAttribute("EncodingType");
+    }
+
+    /**
+     * set the encoding type.
+     * <p/>
+     * 
+     * @param encoding 
+     */
+    protected void setEncodingType(String encoding) {
+        this.element.setAttributeNS(null, "EncodingType", encoding);
+    }
+
+    /**
+     * get the byte array containing token information.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public byte[] getToken() {
+        Text node = getFirstNode();
+        if (node == null) {
+            return null;
+        }
+        try {
+            return Base64.decode(node.getData());
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    /**
+     * set the token information.
+     * <p/>
+     * 
+     * @param data 
+     */
+    protected void setToken(byte[] data) {
+        if (data == null) {
+            throw new IllegalArgumentException("data == null");
+        }
+        Text node = getFirstNode();
+        node.setData(Base64.encode(data));
+    }
+
+    /**
+     * return the first text node.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    protected Text getFirstNode() {
+        Node node = this.element.getFirstChild();
+        return ((node != null) && node instanceof Text) ? (Text) node : null;
+    }
+
+    /**
+     * return the dom element.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public Element getElement() {
+        return this.element;
+    }
+
+    /**
+     * get the id.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public String getID() {
+        return this.element.getAttributeNS(WSConstants.WSU_NS, "Id");
+    }
+
+    /**
+     * set the id.
+     * <p/>
+     * 
+     * @param id 
+     */
+    public void setID(String id) {
+        String prefix = WSSecurityUtil.setNamespace(this.element, WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+        this.element.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+    }
+
+    /**
+     * return the string representation of the token.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public String toString() {
+        return DOM2Writer.nodeToString((Node) this.element);
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/token/DerivedKeyToken.java b/trunk/src/org/apache/ws/security/message/token/DerivedKeyToken.java
new file mode 100755
index 0000000..67506e5
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/DerivedKeyToken.java
@@ -0,0 +1,503 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message.token;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.xml.namespace.QName;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.conversation.ConversationConstants;
+import org.apache.ws.security.conversation.ConversationException;
+import org.apache.ws.security.util.DOM2Writer;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+/**
+ <DerivedKeyToken wsu:Id="..." wsc:Algorithm="...">
+ <SecurityTokenReference>...</SecurityTokenReference>
+ <Properties>...</Properties>
+ <Generation>...</Generation>
+ <Offset>...</Offset>
+ <Length>...</Length>
+ <Label>...</Label>
+ <Nonce>...</Nonce>
+ </DerivedKeyToken>
+ */
+
+/**
+ * @author Ruchith Fernando
+ * @version 1.0
+ */
+public class DerivedKeyToken {
+
+    private Log log = LogFactory.getLog(DerivedKeyToken.class.getName());
+
+
+    //These are the elements that are used to create the SecurityContextToken
+    protected Element element = null;
+    protected Element elementSecurityTokenReference = null;
+    protected Element elementProperties = null;
+    protected Element elementGeneration = null;
+    protected Element elementOffset = null;
+    protected Element elementLength = null;
+    protected Element elementLabel = null;
+    protected Element elementNonce = null;
+    
+    private String ns;
+    
+    /**
+     * This will create an empty DerivedKeyToken
+     *
+     * @param doc THe DOM document
+     */
+    public DerivedKeyToken(Document doc) throws ConversationException {
+        this(ConversationConstants.DEFAULT_VERSION, doc);
+    }
+
+    /**
+     * This will create an empty DerivedKeyToken
+     *
+     * @param doc THe DOM document
+     */
+    public DerivedKeyToken(int version, Document doc) throws ConversationException {
+        
+        log.debug("DerivedKeyToken: created");
+        
+        this.ns = ConversationConstants.getWSCNs(version);
+        
+        this.element = doc.createElementNS(ns,
+                "wsc:" +
+                ConversationConstants.
+                DERIVED_KEY_TOKEN_LN);
+        WSSecurityUtil.setNamespace(this.element, ns,
+                ConversationConstants.WSC_PREFIX);
+    }
+
+    /**
+     * This will create a DerivedKeyToken object with the given DErivedKeyToken element
+     *
+     * @param elem The DErivedKeyToken DOM element
+     * @throws WSSecurityException If the element is not a derived key token
+     */
+    public DerivedKeyToken(Element elem) throws WSSecurityException {
+        log.debug("DerivedKeyToken: created : element constructor");
+        this.element = elem;
+        QName el = new QName(this.element.getNamespaceURI(),
+                this.element.getLocalName());
+        if (!el.equals(new QName(ConversationConstants.WSC_NS_05_02, ConversationConstants.DERIVED_KEY_TOKEN_LN)) &&
+                !el.equals(new QName(ConversationConstants.WSC_NS_05_12, ConversationConstants.DERIVED_KEY_TOKEN_LN))) {
+            throw new WSSecurityException(WSSecurityException.INVALID_SECURITY_TOKEN,
+                    "badTokenType00", new Object[]{el});
+        }
+        this.elementSecurityTokenReference = (Element) WSSecurityUtil.
+                getDirectChild(this.element,
+                        ConversationConstants.SECURITY_TOKEN_REFERENCE_LN,
+                        WSConstants.WSSE_NS);
+        
+        this.ns = el.getNamespaceURI();
+        
+        this.elementProperties = (Element) WSSecurityUtil.getDirectChild(this.
+                element, ConversationConstants.PROPERTIES_LN, this.ns);
+        this.elementGeneration = (Element) WSSecurityUtil.getDirectChild(this.
+                element, ConversationConstants.GENERATION_LN, this.ns);
+        this.elementOffset = (Element) WSSecurityUtil.getDirectChild(this.element,
+                ConversationConstants.OFFSET_LN, this.ns);
+        this.elementLength = (Element) WSSecurityUtil.getDirectChild(this.element,
+                ConversationConstants.LENGTH_LN, this.ns);
+        this.elementLabel = (Element) WSSecurityUtil.getDirectChild(this.element,
+                ConversationConstants.LABEL_LN, this.ns);
+        this.elementNonce = (Element) WSSecurityUtil.getDirectChild(this.element,
+                ConversationConstants.NONCE_LN, this.ns);
+    }
+
+    /**
+     * Sets the security token reference of the derived key token
+     * This is the reference to the shared secret used in the conversation/context
+     *
+     * @param ref Security token reference
+     */
+    public void setSecurityTokenReference(SecurityTokenReference ref) {
+        this.elementSecurityTokenReference = ref.getElement();
+        //WSSecurityUtil.appendChildElement(doc, this.element, ref.getElement());
+        WSSecurityUtil.prependChildElement(this.element.getOwnerDocument(), this.element, ref.getElement(), false);
+    }
+    
+    /**
+     * Sets the security token reference of the derived key token
+     * This is the reference to the shared secret used in the conversation/context
+     *
+     * @param ref Security token reference
+     * @deprecated use setSecurityTokenReference(SecurityTokenReference ref) instead
+     */
+    public void setSecuityTokenReference(SecurityTokenReference ref) {
+        setSecurityTokenReference(ref);
+    }
+    
+    public void setSecurityTokenReference(Element elem) {
+        this.elementSecurityTokenReference = elem;
+        WSSecurityUtil.prependChildElement(elem.getOwnerDocument(), this.element, elem, false);
+    }
+    
+    /**
+     * @deprecated use setSecurityTokenReference(Element elem) instead
+     */
+    public void setSecuityTokenReference(Element elem) {
+        setSecurityTokenReference(elem);
+    }
+
+    /**
+     * Returns the SecurityTokenReference of the derived key token
+     *
+     * @return the Security Token Reference of the derived key token
+     * @throws WSSecurityException
+     */
+    public SecurityTokenReference getSecurityTokenReference() throws
+            WSSecurityException {
+        if (this.elementSecurityTokenReference != null) {
+            return new SecurityTokenReference(this.elementSecurityTokenReference);
+        }
+        return null;
+    }
+    
+    /**
+     * Returns the SecurityTokenReference of the derived key token
+     *
+     * @return the Security Token Reference of the derived key token
+     * @throws WSSecurityException
+     * @deprecated use getSecurityTokenReference() instead
+     */
+    public SecurityTokenReference getSecuityTokenReference() throws
+            WSSecurityException {
+        return getSecurityTokenReference();
+    }
+
+    //Write the getter for security token reference
+
+    /**
+     * This adds a property into
+     * /DerivedKeyToken/Properties
+     *
+     * @param propName  Name of the property
+     * @param propValue Value of the property
+     */
+    private void addProperty(String propName, String propValue) {
+        if (this.elementProperties == null) { //Create the properties element if it is not there
+            this.elementProperties = this.element.getOwnerDocument().createElementNS(this.ns,
+                    "wsc:" +
+                    ConversationConstants.PROPERTIES_LN);
+            WSSecurityUtil.setNamespace(this.elementProperties,
+                    this.ns,
+                    WSConstants.WSSE_PREFIX);
+            this.element.appendChild(this.elementProperties);
+        }
+        Element tempElement = this.element.getOwnerDocument().createElementNS(this.ns,
+                "wsc:" + propName);
+        tempElement.appendChild(this.element.getOwnerDocument().createTextNode(propValue));
+
+        this.elementProperties.appendChild(tempElement);
+    }
+
+    /**
+     * This is used to set the Name, Label and Nonce element values in the properties element
+     * <b>At this point I'm not sure if these are the only properties that will appear in the
+     * <code>Properties</code> element. There fore this method is provided
+     * If this is not required feel free to remove this :D
+     * </b>
+     *
+     * @param name  Value of the Properties/Name element
+     * @param label Value of the Properties/Label element
+     * @param nonce Value of the Properties/Nonce element
+     */
+    public void setProperties(String name, String label,
+                              String nonce) {
+        Hashtable table = new Hashtable(3);
+        table.put("Name", name);
+        table.put("Label", label);
+        table.put("Nonce", nonce);
+        this.setProperties(table);
+    }
+
+    /**
+     * If there are other types of properties other than Name, Label and Nonce
+     * This is provided for extensibility purposes
+     *
+     * @param properties The properties and values in a hashtable
+     */
+    public void setProperties(Hashtable properties) {
+        Enumeration keys = properties.keys();
+        while (keys.hasMoreElements()) {
+            String propertyName = (String) keys.nextElement(); //Get the property name
+            //Check whether this property is already there
+            //If so change the value
+            Node node = WSSecurityUtil.findElement(this.elementProperties,
+                    propertyName,
+                    this.ns);
+            if (node != null && node instanceof Element) { //If the node is not null
+                Text node1 = getFirstNode((Element) node);
+                node1.setData((String) properties.get(propertyName));
+            } else {
+                this.addProperty(propertyName,
+                        (String) properties.get(propertyName));
+            }
+        }
+    }
+
+    public Hashtable getProperties() {
+        if (this.elementProperties != null) {
+            Hashtable table = new Hashtable();
+            NodeList nodes = this.elementProperties.getChildNodes();
+            for (int i = 0; i < nodes.getLength(); i++) {
+                Node tempNode = nodes.item(i);
+                if (tempNode instanceof Element) {
+                    Text text = this.getFirstNode((Element) tempNode);
+                    table.put(tempNode.getNodeName(), text.getData());
+                }
+            }
+
+        }
+        return null;
+    }
+
+    /**
+     * Sets the length of the derived key
+     *
+     * @param length The length of the derived key as a long
+     */
+    public void setLength(int length) {
+        this.elementLength = this.element.getOwnerDocument().createElementNS(this.ns,
+                "wsc:" +
+                ConversationConstants.LENGTH_LN);
+        WSSecurityUtil.setNamespace(this.elementLength,
+                this.ns,
+                ConversationConstants.WSC_PREFIX);
+        this.elementLength.appendChild(this.element.getOwnerDocument().createTextNode(Long.toString(length)));
+        this.element.appendChild(this.elementLength);
+    }
+
+    public int getLength() {
+        if (this.elementLength != null) {
+            return Integer.parseInt(getFirstNode(this.elementLength).getData());
+        }
+        return -1;
+    }
+
+    /**
+     * Sets the offset
+     *
+     * @param offset The offset value as an integer
+     */
+    public void setOffset(int offset) throws ConversationException {
+        //This element MUST NOT be used if the <Generation> element is specified
+        if (this.elementGeneration == null) {
+            this.elementOffset = this.element.getOwnerDocument().createElementNS(this.ns,
+                    "wsc:" +
+                    ConversationConstants.OFFSET_LN);
+            WSSecurityUtil.setNamespace(this.elementOffset,
+                    this.ns,
+                    ConversationConstants.WSC_PREFIX);
+            this.elementOffset.appendChild(this.element.getOwnerDocument().createTextNode(Integer.toString(offset)));
+            this.element.appendChild(this.elementOffset);
+        } else {
+            throw new ConversationException("Offset cannot be set along with generation - generation is already set");
+        }
+
+    }
+
+    public int getOffset() {
+        if (this.elementOffset != null) {
+            return Integer.parseInt(getFirstNode(this.elementOffset).getData());
+        }
+        return -1;
+    }
+
+    /**
+     * Sets the generation of the derived key
+     *
+     * @param generation generation value as an integer
+     */
+    public void setGeneration(int generation) throws
+            ConversationException {
+        //This element MUST NOT be used if the <Offset> element is specified
+        if (this.elementOffset == null) {
+            this.elementGeneration = this.element.getOwnerDocument().createElementNS(this.ns,
+                    "wsc:" + ConversationConstants.GENERATION_LN);
+            WSSecurityUtil.setNamespace(this.elementGeneration,
+                    this.ns,
+                    ConversationConstants.WSC_PREFIX);
+            this.elementGeneration.appendChild(this.element.getOwnerDocument().createTextNode(Integer.toString(generation)));
+            this.element.appendChild(this.elementGeneration);
+        } else {
+            throw new ConversationException("Generation cannot be set along with offset - Offset is already set");
+        }
+    }
+
+    public int getGeneration() {
+        if (this.elementGeneration != null) {
+            return Integer.parseInt(getFirstNode(this.elementGeneration).getData());
+        }
+        return -1;
+    }
+
+    /**
+     * Sets the label of the derived key
+     *
+     * @param label Label value as a string
+     */
+    public void setLabel(String label) {
+        this.elementLabel = this.element.getOwnerDocument().createElementNS(this.ns,
+                "wsc:" +
+                ConversationConstants.LABEL_LN);
+        WSSecurityUtil.setNamespace(this.elementLabel, this.ns,
+                ConversationConstants.WSC_PREFIX);
+        this.elementLabel.appendChild(this.element.getOwnerDocument().createTextNode(label));
+        this.element.appendChild(this.elementLabel);
+    }
+
+    /**
+     * Sets the nonce value of the derived key
+     *
+     * @param nonce Nonce value as a string
+     */
+    public void setNonce(String nonce) {
+        this.elementNonce = this.element.getOwnerDocument().createElementNS(this.ns,
+                "wsc:" +
+                ConversationConstants.NONCE_LN);
+        WSSecurityUtil.setNamespace(this.elementNonce, this.ns,
+                ConversationConstants.WSC_PREFIX);
+        this.elementNonce.appendChild(this.element.getOwnerDocument().createTextNode(nonce));
+        this.element.appendChild(this.elementNonce);
+
+    }
+
+    /**
+     * Returns the label of the derived key token
+     *
+     * @return Label of the derived key token
+     */
+    public String getLabel() {
+        if (this.elementLabel != null) {
+            return getFirstNode(this.elementLabel).getData();
+        }
+        return null;
+    }
+
+    /**
+     * Return the nonce of the derived key token
+     *
+     * @return Nonce of the derived key token
+     */
+    public String getNonce() {
+        if (this.elementNonce != null) {
+            return getFirstNode(this.elementNonce).getData();
+        }
+        return null;
+    }
+
+    /**
+     * Returns the first text node of an element.
+     *
+     * @param e the element to get the node from
+     * @return the first text node or <code>null</code> if node
+     *         is null or is not a text node
+     */
+    private Text getFirstNode(Element e) {
+        Node node = e.getFirstChild();
+        return ((node != null) && node instanceof Text) ? (Text) node : null;
+    }
+
+    /**
+     * Returns the dom element of this <code>SecurityContextToken</code> object.
+     *
+     * @return the DerivedKeyToken element
+     */
+    public Element getElement() {
+        return this.element;
+    }
+
+    /**
+     * Returns the string representation of the token.
+     *
+     * @return a XML string representation
+     */
+    public String toString() {
+        return DOM2Writer.nodeToString((Node) this.element);
+    }
+
+    /**
+     * Gets the id.
+     *
+     * @return the value of the <code>wsu:Id</code> attribute of this
+     *         DerivedKeyToken
+     */
+    public String getID() {
+        return this.element.getAttributeNS(WSConstants.WSU_NS, "Id");
+    }
+
+    /**
+     * Set the id of this derived key token.
+     *
+     * @param id the value for the <code>wsu:Id</code> attribute of this
+     *           DerivgedKeyToken
+     */
+    public void setID(String id) {
+        String prefix = WSSecurityUtil.setNamespace(this.element,
+                WSConstants.WSU_NS,
+                WSConstants.WSU_PREFIX);
+        this.element.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+    }
+
+    /**
+     * Gets the derivation algorithm
+     *
+     * @return the value of the <code>wsc:Algorithm</code> attribute of this
+     *         DerivedKeyToken
+     */
+    public String getAlgorithm() {
+        String algo = this.element.getAttributeNS(this.ns,
+                "Algorithm");
+        if (algo == null || algo.equals("")) {
+            return ConversationConstants.DerivationAlgorithm.P_SHA_1;
+        } else {
+            return algo;
+        }
+    }
+
+    /**
+     * Set the derivation algorithm of this derived key token.
+     *
+     * @param algo the value for the <code>wsu:Algorithm</code> attribute of this
+     *                    DerivedKeyToken
+     */
+    public void setAlgorithm(String algo) {
+        String prefix = WSSecurityUtil.setNamespace(this.element,
+                this.ns,
+                ConversationConstants.
+                WSC_PREFIX);
+        this.element.setAttributeNS(this.ns,
+                prefix + ":Algorithm", algo);
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/message/token/PKIPathSecurity.java b/trunk/src/org/apache/ws/security/message/token/PKIPathSecurity.java
new file mode 100644
index 0000000..c101b54
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/PKIPathSecurity.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message.token;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * PKIPath Security Token.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class PKIPathSecurity extends BinarySecurity {
+    private static final String type = WSConstants.X509TOKEN_NS + "#X509PKIPathv1";
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @throws WSSecurityException
+     */
+    public PKIPathSecurity(Element elem)
+        throws WSSecurityException {
+        super(elem);
+        if (!getValueType().equals(getType())) {
+            throw new WSSecurityException(
+                WSSecurityException.INVALID_SECURITY_TOKEN,
+                "invalidValueType",
+                new Object[]{type, getValueType()});
+        }
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     */
+    public PKIPathSecurity(Document doc) {
+        super(doc);
+        setValueType(getType());
+    }
+
+    /**
+     * get the X509Certificate array.
+     * <p/>
+     *
+     * @param reverse
+     * @param crypto
+     * @return array of certificates 
+     * @throws WSSecurityException
+     */
+    public X509Certificate[] getX509Certificates(boolean reverse, Crypto crypto)
+        throws WSSecurityException {
+        byte[] data = getToken();
+        if (data == null) {
+            return null;
+        }
+        X509Certificate[] certs = null;
+        certs = crypto.getX509Certificates(data, reverse);
+        return certs;
+    }
+
+    /**
+     * set the X509Certificate array.
+     * <p/>
+     *
+     * @param certs
+     * @param reverse
+     * @param crypto
+     * @throws WSSecurityException
+     */
+    public void setX509Certificates(X509Certificate[] certs,
+                                    boolean reverse,
+                                    Crypto crypto)
+        throws WSSecurityException {
+        if (certs == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noCert");
+        }
+        byte[] data = crypto.getCertificateData(reverse, certs);
+        setToken(data);
+    }
+
+    public static String getType() {
+        return type;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/token/Reference.java b/trunk/src/org/apache/ws/security/message/token/Reference.java
new file mode 100644
index 0000000..f118787
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/Reference.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message.token;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.util.DOM2Writer;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Reference.
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class Reference {
+    public static final QName TOKEN =
+        new QName(WSConstants.WSSE_NS, "Reference");
+    protected Element element = null;
+
+    /**
+     * Constructor.
+     * <p/>
+     * 
+     * @param elem 
+     * @throws WSSecurityException 
+     */
+    public Reference(Element elem) throws WSSecurityException {
+        if (elem == null) {
+            throw new WSSecurityException(
+                WSSecurityException.INVALID_SECURITY,
+                "noReference");
+        }
+        this.element = elem;
+        QName el =
+            new QName(
+                this.element.getNamespaceURI(),
+                this.element.getLocalName());
+        if (!el.equals(TOKEN)) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILURE,
+                "badElement",
+                new Object[] { TOKEN, el });
+        }
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     * 
+     * @param doc 
+     */
+    public Reference(Document doc) {
+        this.element =
+            doc.createElementNS(WSConstants.WSSE_NS, "wsse:Reference");
+        WSSecurityUtil.setNamespace(this.element, WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);
+    }
+
+    /**
+     * get the dom element.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public Element getElement() {
+        return this.element;
+    }
+
+    /**
+     * get the URI.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public String getValueType() {
+        return this.element.getAttributeNS(null, "ValueType");
+    }
+
+    /**
+     * get the URI.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public String getURI() {
+        return this.element.getAttributeNS(null, "URI");
+    }
+
+    /**
+     * set the Value type.
+     * <p/>
+     * 
+     * @param valueType
+     */
+    public void setValueType(String valueType) {
+        this.element.setAttributeNS(null, "ValueType", valueType);
+    }
+
+    /**
+     * set the URI.
+     * <p/>
+     * 
+     * @param uri 
+     */
+    public void setURI(String uri) {
+        this.element.setAttributeNS(null, "URI", uri);
+    }
+
+    /**
+     * return the string representation.
+     * <p/>
+     * 
+     * @return TODO
+     */
+    public String toString() {
+        return DOM2Writer.nodeToString((Node) this.element);
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/token/SecurityContextToken.java b/trunk/src/org/apache/ws/security/message/token/SecurityContextToken.java
new file mode 100644
index 0000000..4feacb8
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/SecurityContextToken.java
@@ -0,0 +1,200 @@
+package org.apache.ws.security.message.token;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.conversation.ConversationConstants;
+import org.apache.ws.security.conversation.ConversationException;
+import org.apache.ws.security.util.DOM2Writer;
+import org.apache.ws.security.util.UUIDGenerator;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+import javax.xml.namespace.QName;
+
+/**
+ * @author Ruchith Fernando
+ * @version 1.0
+ */
+public class SecurityContextToken {
+
+    /**
+     * Security context token element
+     */
+    protected Element element = null;
+
+    /**
+     * Identifier element
+     */
+    protected Element elementIdentifier = null;
+    
+    /**
+     * Constructor to create the SCT
+     *
+     * @param doc
+     */
+    public SecurityContextToken(Document doc) throws ConversationException {
+        this(ConversationConstants.DEFAULT_VERSION, doc);
+    }
+
+    /**
+     * Constructor to create the SCT with a given uuid
+     *
+     * @param doc
+     */
+    public SecurityContextToken(Document doc, String uuid) throws ConversationException {
+        this(ConversationConstants.DEFAULT_VERSION, doc, uuid);
+    }
+
+    /**
+     * Constructor to create the SCT
+     *
+     * @param doc
+     */
+    public SecurityContextToken(int version, Document doc) throws ConversationException {
+
+        String ns = ConversationConstants.getWSCNs(version);
+        
+        this.element = doc.createElementNS(ns,
+                "wsc:" + ConversationConstants.SECURITY_CONTEXT_TOKEN_LN);
+
+        WSSecurityUtil.setNamespace(this.element,ns,
+                ConversationConstants.WSC_PREFIX);
+
+        this.elementIdentifier = doc.createElementNS(ns,
+                "wsc:" + ConversationConstants.IDENTIFIER_LN);
+
+        this.element.appendChild(this.elementIdentifier);
+
+        String uuid = UUIDGenerator.getUUID();
+        
+        this.elementIdentifier.appendChild(doc.createTextNode(uuid));
+        
+        this.setID("sctId-" + this.element.hashCode());
+    }
+
+    /**
+     * Constructor to create the SCT with a given uuid
+     *
+     * @param doc
+     */
+    public SecurityContextToken(int version, Document doc, String uuid) throws ConversationException {
+
+        String ns = ConversationConstants.getWSCNs(version);
+        
+        this.element = doc.createElementNS(ns,
+                "wsc:" + ConversationConstants.SECURITY_CONTEXT_TOKEN_LN);
+
+        WSSecurityUtil.setNamespace(this.element, ns,
+                ConversationConstants.WSC_PREFIX);
+
+        this.elementIdentifier = doc.createElementNS(ns,
+                "wsc:" + ConversationConstants.IDENTIFIER_LN);
+
+        this.element.appendChild(this.elementIdentifier);
+
+        this.elementIdentifier.appendChild(doc.createTextNode(uuid));
+    }
+
+    /**
+     * This is used to create a SecurityContestToken using a DOM Element
+     *
+     * @param elem The DOM element: The security context token
+     * @throws WSSecurityException If the element passed in in not a security context token
+     */
+    public SecurityContextToken(Element elem) throws WSSecurityException {
+        this.element = elem;
+        QName el = new QName(this.element.getNamespaceURI(),
+                this.element.getLocalName());
+
+        if (!el.equals(new QName(ConversationConstants.WSC_NS_05_02, ConversationConstants.SECURITY_CONTEXT_TOKEN_LN)) &&
+                !el.equals(new QName(ConversationConstants.WSC_NS_05_12, ConversationConstants.SECURITY_CONTEXT_TOKEN_LN))) {    // If the element is not a security context token
+            throw new WSSecurityException(WSSecurityException.INVALID_SECURITY_TOKEN, "badTokenType00",
+                    new Object[]{el});
+        }
+
+        this.elementIdentifier = (Element) WSSecurityUtil.getDirectChild(
+                element, ConversationConstants.IDENTIFIER_LN, el
+                        .getNamespaceURI());
+    }
+
+    /**
+     * Set the identifier.
+     */
+    public void setIdentifier(Document doc, String uuid) {
+        Text node = getFirstNode(this.elementIdentifier);
+        node.setData(uuid);
+    }
+
+    /**
+     * Get the identifier.
+     *
+     * @return the data from the identifier element.
+     */
+    public String getIdentifier() {
+        if (this.elementIdentifier != null) {
+            return getFirstNode(this.elementIdentifier).getData();
+        }
+        return null;
+    }
+
+    public void setElement(Element elem) {
+        this.element.appendChild(elem);
+    }
+
+    /**
+     * Returns the first text node of an element.
+     *
+     * @param e the element to get the node from
+     * @return the first text node or <code>null</code> if node
+     *         is null or is not a text node
+     */
+    private Text getFirstNode(Element e) {
+        Node node = e.getFirstChild();
+        return ((node != null) && node instanceof Text) ? (Text) node : null;
+    }
+
+    /**
+     * Returns the dom element of this <code>SecurityContextToken</code> object.
+     *
+     * @return the <code>wsse:UsernameToken</code> element
+     */
+    public Element getElement() {
+        return this.element;
+    }
+
+    /**
+     * Returns the string representation of the token.
+     *
+     * @return a XML string representation
+     */
+    public String toString() {
+        return DOM2Writer.nodeToString((Node) this.element);
+    }
+
+    /**
+     * Gets the id.
+     *
+     * @return the value of the <code>wsu:Id</code> attribute of this
+     *         SecurityContextToken
+     */
+    public String getID() {
+        return this.element.getAttributeNS(WSConstants.WSU_NS, "Id");
+    }
+
+    /**
+     * Set the id of this security context token.
+     *
+     * @param id the value for the <code>wsu:Id</code> attribute of this
+     *           SecurityContextToken
+     */
+    public void setID(String id) {
+        String prefix = WSSecurityUtil.setNamespace(this.element,
+                WSConstants.WSU_NS,
+                WSConstants.WSU_PREFIX);
+        this.element.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java b/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java
new file mode 100644
index 0000000..8eb137f
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java
@@ -0,0 +1,696 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message.token;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.util.DOM2Writer;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial;
+import org.apache.xml.security.keys.content.X509Data;
+import org.apache.ws.security.util.Base64;
+import org.apache.xml.security.utils.Constants;
+import org.w3c.dom.*;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+
+/**
+ * Security Token Reference.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class SecurityTokenReference {
+    private static Log log =
+            LogFactory.getLog(SecurityTokenReference.class.getName());
+    public static final String SECURITY_TOKEN_REFERENCE = "SecurityTokenReference";
+    public static final String KEY_NAME = "KeyName";
+    public static final String SKI_URI = WSConstants.X509TOKEN_NS + "#X509SubjectKeyIdentifier";
+    public static final String THUMB_URI = WSConstants.SOAPMESSAGE_NS11 + "#" + WSConstants.THUMBPRINT;
+    public static final String SAML_ID_URI = WSConstants.SAMLTOKEN_NS + "#" + WSConstants.SAML_ASSERTION_ID;
+    public static final String ENC_KEY_SHA1_URI = WSConstants.SOAPMESSAGE_NS11 + "#" + WSConstants.ENC_KEY_SHA1_URI;
+    protected Element element = null;
+    private XMLX509IssuerSerial issuerSerial = null;
+    private byte[] skiBytes = null;
+    
+    private static boolean doDebug = false;
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param elem TODO
+     * @throws WSSecurityException
+     */
+    public SecurityTokenReference(Element elem) throws WSSecurityException {
+        doDebug = log.isDebugEnabled();
+        this.element = elem;
+        boolean goodElement = false;
+        if (SECURITY_TOKEN_REFERENCE.equals(element.getLocalName())) {
+            goodElement = WSConstants.WSSE_NS.equals(element.getNamespaceURI());
+//        } else if (KEY_NAME.equals(element.getLocalName())) {
+//            goodElement = WSConstants.SIG_NS.equals(element.getNamespaceURI());
+        }
+        if (!goodElement) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "badElement",
+                    null);
+        }
+    }
+
+    /**
+     * Constructor.
+     * <p/>
+     *
+     * @param doc TODO
+     */
+    public SecurityTokenReference(Document doc) {
+        doDebug = log.isDebugEnabled();
+        this.element =
+                doc.createElementNS(WSConstants.WSSE_NS,
+                        "wsse:SecurityTokenReference");
+        WSSecurityUtil.setNamespace(this.element, WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);        
+    }
+
+    /*
+     * Here the methods that handle the direct reference inside
+     * a SecurityTokenReference
+     */
+
+    /**
+     * set the reference.
+     * <p/>
+     *
+     * @param ref
+     */
+    public void setReference(Reference ref) {
+        Element elem = getFirstElement();
+        if (elem != null) {
+            this.element.replaceChild(ref.getElement(), elem);
+        } else {
+            this.element.appendChild(ref.getElement());
+        }
+    }
+
+    /**
+     * Gets the Reference.
+     *
+     * @return the <code>Reference</code> element contained in this
+     *         SecurityTokeneReference
+     * @throws WSSecurityException
+     */
+    public Reference getReference() throws WSSecurityException {
+        Element elem = getFirstElement();
+        return new Reference(elem);
+    }
+
+    /**
+     * Gets the signing token element, which maybe a <code>BinarySecurityToken
+     * </code> or a SAML token.
+     * 
+     * The method gets the URI attribute of the {@link Reference} contained in
+     * the {@link SecurityTokenReference} and tries to find the referenced
+     * Element in the document.
+     *
+     * @param doc the document that contains the binary security token
+     *            element. This could be different from the document
+     *            that contains the SecurityTokenReference (STR). See
+     *            STRTransform.derefenceBST() method
+     * @return Element     containing the signing token, must be a BinarySecurityToken
+     * @throws WSSecurityException When either no <code>Reference</code> element, or the found
+     *                   reference contains no URI, or the referenced signing not found.
+     */
+    public Element getTokenElement(Document doc, WSDocInfo docInfo, CallbackHandler cb)
+            throws WSSecurityException {
+        Reference ref = getReference();
+        String uri = ref.getURI();
+        if (doDebug) {
+            log.debug("Token reference uri: " + uri);
+        }
+        if (uri == null) {
+            throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+                    "badReferenceURI");
+        }
+        Element tokElement = null;
+        String tmpS = WSConstants.WSS_SAML_NS + WSConstants.WSS_SAML_ASSERTION;
+        String saml10 = WSConstants.WSS_SAML_NS + WSConstants.SAML_ASSERTION_ID;
+        
+        if (tmpS.equals(ref.getValueType())
+                || saml10.equals(ref.getValueType())
+                || WSConstants.WSC_SCT.equals(ref.getValueType())) {
+            Element sa = docInfo.getAssertion();
+            String saID = null;
+            if (sa != null) {
+                saID = sa.getAttribute("AssertionID");
+            }
+            if (doDebug) {
+                log.debug("SAML token ID: " + saID);
+            }
+            String id = uri.substring(1);
+            if (saID == null || !saID.equals(id)) {
+                
+                if(cb != null) {
+                    //try to find a custom token
+                    WSPasswordCallback pwcb = new WSPasswordCallback(id,
+                            WSPasswordCallback.CUSTOM_TOKEN);
+                    try {
+                        cb.handle(new Callback[]{pwcb});
+                    } catch (Exception e) {
+                        throw new WSSecurityException(WSSecurityException.FAILURE,
+                                "noPassword", new Object[] { id }, e);
+                    }
+                    
+                    Element assertionElem = pwcb.getCustomToken();
+                    if(assertionElem != null) {
+                        sa = (Element)doc.importNode(assertionElem, true);
+                    }
+                    else {
+                        throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+                            "badReferenceURI",
+                            new Object[]{"uri:" + uri + ", saID: " + saID});
+                    }
+                } else {
+                    throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+                            "badReferenceURI",
+                            new Object[]{"uri:" + uri + ", saID: " + saID});
+                }
+            }
+            tokElement = sa;
+        } else {
+
+            tokElement = WSSecurityUtil.getElementByWsuId(doc, uri);
+            
+            // In some scenarios id is used rather than wsu:Id
+            if (tokElement == null) {
+                tokElement = WSSecurityUtil.getElementByGenId(doc, uri);
+            }
+
+        }
+        if (tokElement == null) {
+            throw new WSSecurityException(WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+                    "noToken",
+                    new Object[]{uri});
+        }
+        return tokElement;
+    }
+
+    /*
+     * Here the methods that handle the various key identifier types
+     * such as KeyIdentifier, SubjectKeyIdentifier (SKI)
+     */
+
+    /**
+     * Sets the KeyIdentifier Element as a X509 certificate.
+     * Takes a X509 certificate, converts its data into base 64 and inserts
+     * it into a <code>wsse:KeyIdentifier</code> element, which is placed
+     * in the <code>wsse:SecurityTokenReference</code> element.
+     *
+     * @param cert is the X509 certificate to be inserted as key identifier
+     */
+    public void setKeyIdentifier(X509Certificate cert)
+            throws WSSecurityException {
+        Document doc = this.element.getOwnerDocument();
+        byte data[] = null;
+        try {
+            data = cert.getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError", null, e);
+        }
+        Text text = doc.createTextNode(Base64.encode(data));
+        
+        if (cert.getVersion() == 1) {
+            createKeyIdentifier(doc, X509Security.X509_V1_TYPE, text);
+        } else {
+            createKeyIdentifier(doc, X509Security.X509_V3_TYPE, text);
+        }
+    }
+
+    /**
+     * Sets the KeyIdentifier Element as a X509 Subject-Key-Identifier (SKI).
+     * Takes a X509 certificate, gets it SKI data, converts into base 64 and
+     * inserts it into a <code>wsse:KeyIdentifier</code> element, which is placed
+     * in the <code>wsse:SecurityTokenReference</code> element.
+     *
+     * @param cert   is the X509 certificate to get the SKI
+     * @param crypto is the Crypto implementation. Used to read SKI info bytes from certificate
+     */
+    public void setKeyIdentifierSKI(X509Certificate cert, Crypto crypto)
+            throws WSSecurityException {
+        //
+        // As per the 1.1 specification, SKI can only be used for a V3 certificate
+        //
+        if (cert.getVersion() != 3) {
+            throw new WSSecurityException(
+                WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+                "invalidCertForSKI",
+                new Object[]{new Integer(cert.getVersion())}
+            );
+        }
+        
+        Document doc = this.element.getOwnerDocument();
+        byte data[] = crypto.getSKIBytesFromCert(cert);
+        
+        org.w3c.dom.Text text = doc.createTextNode(Base64.encode(data));
+        createKeyIdentifier(doc, SKI_URI, text);        
+    }
+
+    /**
+     * Sets the KeyIdentifier Element as a Thumbprint.
+     * 
+     * Takes a X509 certificate, computes its thumbprint using SHA-1, converts
+     * into base 64 and inserts it into a <code>wsse:KeyIdentifier</code>
+     * element, which is placed in the <code>wsse:SecurityTokenReference</code>
+     * element.
+     * 
+     * @param cert
+     *            is the X509 certificate to get the thumbprint
+     */
+    public void setKeyIdentifierThumb(X509Certificate cert)
+            throws WSSecurityException {
+        Document doc = this.element.getOwnerDocument();
+        MessageDigest sha = null;
+        try {
+            sha = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException e1) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILURE, "noSHA1availabe", null, e1
+            );
+        }
+        sha.reset();
+        try {
+            sha.update(cert.getEncoded());
+        } catch (CertificateEncodingException e1) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError", null, e1
+            );
+        }
+        byte[] data = sha.digest();
+
+        org.w3c.dom.Text text = doc.createTextNode(Base64.encode(data));
+        createKeyIdentifier(doc, THUMB_URI, text);
+    }
+    
+
+    public void setKeyIdentifierEncKeySHA1(String value) 
+               throws WSSecurityException {
+        Document doc = this.element.getOwnerDocument();
+        org.w3c.dom.Text text = doc.createTextNode(value);
+        createKeyIdentifier(doc, ENC_KEY_SHA1_URI, text);
+        
+    }
+    
+    public void setSAMLKeyIdentifier(String keyIdVal)
+            throws WSSecurityException {
+        Document doc = this.element.getOwnerDocument();
+        createKeyIdentifier(doc, SAML_ID_URI, doc.createTextNode(keyIdVal));
+    }
+
+    private void createKeyIdentifier(Document doc, String uri, Node node) {
+        
+        Element keyId = doc.createElementNS(WSConstants.WSSE_NS,
+                "wsse:KeyIdentifier");
+        keyId.setAttributeNS(null, "ValueType", uri);
+        keyId.setAttributeNS(null, "EncodingType",
+                BinarySecurity.BASE64_ENCODING);
+
+        keyId.appendChild(node);
+        Element elem = getFirstElement();
+        if (elem != null) {
+            this.element.replaceChild(keyId, elem);
+        } else {
+            this.element.appendChild(keyId);
+        }
+    }
+
+    /*
+     * Several helper and utility methods.
+     */
+    
+    /**
+     * get the first child element.
+     *
+     * @return the first <code>Element</code> child node
+     */
+    public Element getFirstElement() {
+        for (Node currentChild = this.element.getFirstChild();
+             currentChild != null;
+             currentChild = currentChild.getNextSibling()) {
+            if (currentChild instanceof Element) {
+                return (Element) currentChild;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets the KeyIdentifier.
+     *
+     * @return the the X509 certificate or zero if a unknown key identifier
+     *         type was detected.
+     */
+    public X509Certificate[] getKeyIdentifier(Crypto crypto)
+            throws WSSecurityException {
+        X509Security token = null;
+        Element elem = getFirstElement();
+        String value = elem.getAttribute("ValueType");
+        String alias = null;
+
+        if (X509Security.X509_V3_TYPE.equals(value) 
+                || X509Security.X509_V1_TYPE.equals(value)) {
+            token = new X509Security(elem);
+            if (token != null) {
+                X509Certificate cert = token.getX509Certificate(crypto);
+                X509Certificate[] certs = new X509Certificate[1];
+                certs[0] = cert;
+                return certs;
+            }
+        } else if (SKI_URI.equals(value)) {
+            alias = getX509SKIAlias(crypto);
+        } else if (THUMB_URI.equals(value)) {
+            Node node = getFirstElement().getFirstChild();
+            if (node == null) {
+                return null;
+            }
+            if (node.getNodeType() == Node.TEXT_NODE) {
+                byte[] thumb = Base64.decode(((Text) node).getData());
+                alias = crypto.getAliasForX509CertThumb(thumb);
+            }
+        }
+        
+        if (alias != null) {
+            return crypto.getCertificates(alias);
+        }
+        return null;
+    }
+    
+    public String getKeyIdentifierValue() {
+        if(containsKeyIdentifier()) {
+            Node node = getFirstElement().getFirstChild();
+            if (node == null) {
+                return null;
+            }
+            if (node.getNodeType() == Node.TEXT_NODE) {
+                return ((Text) node).getData();
+            }
+        } 
+        return null;
+    }
+    
+    public String getKeyIdentifierValueType() {
+        if(containsKeyIdentifier()) {
+            Element elem = getFirstElement();
+            return elem.getAttribute("ValueType");
+            
+        } 
+        return null;
+    }
+    
+        
+
+    public String getX509SKIAlias(Crypto crypto) throws WSSecurityException {
+        if (skiBytes == null) {
+            skiBytes = getSKIBytes();
+            if (skiBytes == null) {
+                return null;
+            }
+        }
+        String alias = crypto.getAliasForX509Cert(skiBytes);
+        if (doDebug) {
+            log.info("X509 SKI alias: " + alias);
+        }
+        return alias;
+    }
+
+    public byte[] getSKIBytes() {
+        if (skiBytes != null) {
+            return skiBytes;
+        }
+        Node node = getFirstElement().getFirstChild();
+        if (node == null) {
+            return null;
+        }
+        if (node.getNodeType() == Node.TEXT_NODE) {
+            try {
+                skiBytes = Base64.decode(((Text) node).getData());
+            } catch (WSSecurityException e) {
+                return null;
+            }
+        }
+        return skiBytes;
+    }
+
+    /*
+     * Here the methods that handle the IssuerSerial key identification
+     */
+
+    /**
+     * Sets the X509 IssuerSerial data.
+     *
+     * @param ref the {@link XMLX509IssuerSerial} to put into this
+     *            SecurityTokenReference
+     */
+    public void setX509IssuerSerial(X509Data ref) {
+        Element elem = getFirstElement();
+        if (elem != null) {
+            this.element.replaceChild(ref.getElement(), elem);
+        } else {
+            this.element.appendChild(ref.getElement());
+        }
+    }
+
+    /**
+     * Gets the certificate identified with X509 issuerSerial data.
+     * This method first tries to get the embedded certificate.
+     * If this fails it checks if the certificate is  in the
+     * keystore.
+     *
+     * @return a certificate array or null if nothing found
+     */
+    public X509Certificate[] getX509IssuerSerial(Crypto crypto)
+            throws WSSecurityException {
+        String alias = getX509IssuerSerialAlias(crypto);
+        if (alias != null) {
+            return crypto.getCertificates(alias);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the alias name of the certificate identified with X509 issuerSerial data.
+     * The keystore identifies the certificate and the key with this alias name.
+     *
+     * @return the alias name for the certificate or null if nothing found
+     */
+    public String getX509IssuerSerialAlias(Crypto crypto)
+            throws WSSecurityException {
+        if (issuerSerial == null) {
+            issuerSerial = getIssuerSerial();
+            if (issuerSerial == null) {
+                return null;
+            }
+        }
+
+        String alias = crypto.getAliasForX509Cert(issuerSerial.getIssuerName(),
+                issuerSerial.getSerialNumber());
+
+        if (doDebug) {
+            log.info("X509IssuerSerial alias: " + alias);
+        }
+        return alias;
+    }
+
+    private XMLX509IssuerSerial getIssuerSerial() throws WSSecurityException {
+        if (issuerSerial != null) {
+            return issuerSerial;
+        }
+        Element elem = getFirstElement();
+        if (elem == null) {
+            return null;
+        }
+        try {
+            if (Constants._TAG_X509DATA.equals(elem.getLocalName())) {
+                elem = (Element)WSSecurityUtil.findElement(elem, Constants._TAG_X509ISSUERSERIAL, Constants.SignatureSpecNS);
+            }
+            issuerSerial = new XMLX509IssuerSerial(elem, "");
+        } catch (XMLSecurityException e) {
+            throw new WSSecurityException(WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+                    "noToken",
+                    new Object[]{"Issuer/Serial data element missing"},
+                    e);
+        }
+        return issuerSerial;
+    }
+
+    /*
+     * Several helper and utility methods.
+     */
+
+    /**
+     * Method containsReference
+     *
+     * @return true if the <code>SecurtityTokenReference</code> contains
+     *         a <code>wsse:Reference</code> element
+     */
+    public boolean containsReference() {
+        return this.lengthReference() > 0;
+    }
+
+    /**
+     * Method lengthReference.
+     *
+     * @return number of <code>wsse:Reference</code> elements in
+     *         the <code>SecurtityTokenReference</code>
+     */
+    public int lengthReference() {
+        return this.length(WSConstants.WSSE_NS, "Reference");
+    }
+
+    /**
+     * Method containsX509IssuerSerial
+     *
+     * @return true if the <code>SecurtityTokenReference</code> contains
+     *         a <code>ds:IssuerSerial</code> element
+     */
+    public boolean containsX509IssuerSerial() {
+        return this.lengthX509IssuerSerial() > 0;
+    }
+
+    /**
+     * Method containsX509Data
+     *
+     * @return true if the <code>SecurtityTokenReference</code> contains
+     *         a <code>ds:X509Data</code> element
+     */
+    public boolean containsX509Data() {
+        return this.lengthX509Data() > 0;
+    }
+    /**
+     * Method lengthX509IssuerSerial.
+     *
+     * @return number of <code>ds:IssuerSerial</code> elements in
+     *         the <code>SecurtityTokenReference</code>
+     */
+    public int lengthX509IssuerSerial() {
+        return this.length(WSConstants.SIG_NS, Constants._TAG_X509ISSUERSERIAL);
+    }
+
+    /**
+     * Method lengthX509Data.
+     *
+     * @return number of <code>ds:IssuerSerial</code> elements in
+     *         the <code>SecurtityTokenReference</code>
+     */
+    public int lengthX509Data() {
+        return this.length(WSConstants.SIG_NS, Constants._TAG_X509DATA);
+    }
+    /**
+     * Method containsKeyIdentifier.
+     *
+     * @return true if the <code>SecurtityTokenReference</code> contains
+     *         a <code>wsse:KeyIdentifier</code> element
+     */
+    public boolean containsKeyIdentifier() {
+        return this.lengthKeyIdentifier() > 0;
+    }
+
+    /**
+     * Method lengthKeyIdentifier.
+     *
+     * @return number of <code>wsse:KeyIdentifier</code> elements in
+     *         the <code>SecurtityTokenReference</code>
+     */
+    public int lengthKeyIdentifier() {
+        return this.length(WSConstants.WSSE_NS, "KeyIdentifier");
+    }
+
+    /**
+     * Method length.
+     *
+     * @param namespace
+     * @param localname
+     * @return number of elements with matching localname and namespace
+     */
+    public int length(String namespace, String localname) {
+        NodeList childNodes = this.element.getChildNodes();
+        int maxLength = childNodes.getLength();
+        int result = 0;
+        for (int i = 0; i < maxLength; i++) {
+            Node n = childNodes.item(i);
+            if (n.getNodeType() == Node.ELEMENT_NODE) {
+                String ns = n.getNamespaceURI();
+                String name = n.getLocalName();
+                if (((namespace != null)
+                        && (ns != null)
+                        && namespace.equals(ns))
+                        || ((namespace == null) && (ns == null))) {
+                    if (localname.equals(name)) {
+                        result++;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * get the dom element.
+     * <p/>
+     *
+     * @return TODO
+     */
+    public Element getElement() {
+        return this.element;
+    }
+
+    /**
+     * set the id.
+     * <p/>
+     *
+     * @param id
+     */
+    public void setID(String id) {
+        String prefix =
+                WSSecurityUtil.setNamespace(this.element,
+                        WSConstants.WSU_NS,
+                        WSConstants.WSU_PREFIX);
+        this.element.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+    }
+
+    /**
+     * return the string representation.
+     * <p/>
+     *
+     * @return TODO
+     */
+    public String toString() {
+        return DOM2Writer.nodeToString((Node) this.element);
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/token/SignatureConfirmation.java b/trunk/src/org/apache/ws/security/message/token/SignatureConfirmation.java
new file mode 100644
index 0000000..035e556
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/SignatureConfirmation.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message.token;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.util.DOM2Writer;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.Base64;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+
+/**
+ * Signature Confirmation element.
+ *
+ *
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de)
+ */
+public class SignatureConfirmation {
+
+    private static final String VALUE = "Value"; 
+    protected Element element = null;
+    private byte[] signatureValue = null;
+    /**
+     * Constructs a <code>SignatureConfirmation</code> object and parses the
+     * <code>wsse11:SignatureCOnfirmation</code> element to initialize it.
+     *
+     * @param elem the <code>wsse11:SignatureCOnfirmation</code> element that
+     *             contains the confirmation data
+     */
+    public SignatureConfirmation(Element elem) throws WSSecurityException {
+
+        element = elem;
+        String sv = element.getAttributeNS(null, VALUE);
+        if (sv != null) {
+            signatureValue = Base64.decode(sv);
+        }
+    }
+
+    /**
+     * Constructs a <code>SignatureConfirmation</code> object according
+     * to the defined parameters.
+     * <p/>
+     *
+     * @param doc the SOAP envelope as <code>Document</code>
+     * @param signVal the Signature value as byte[] of <code>null</code> 
+     *   if no value available.
+     */
+    public SignatureConfirmation(Document doc, byte[] signVal) {
+
+        element =
+                doc.createElementNS(WSConstants.WSSE11_NS,
+                        WSConstants.WSSE11_PREFIX
+                + ":"
+                + WSConstants.SIGNATURE_CONFIRMATION_LN);
+        WSSecurityUtil.setNamespace(element,
+                WSConstants.WSSE11_NS,
+                WSConstants.WSSE11_PREFIX);
+        if (signVal != null) {
+            String sv = Base64.encode(signVal);
+            element.setAttribute(VALUE, sv);
+        }
+
+    }
+
+    /**
+     * Returns the dom element of this <code>Timestamp</code> object.
+     *
+     * @return the <code>wsse:UsernameToken</code> element
+     */
+    public Element getElement() {
+        return this.element;
+    }
+
+    /**
+     * Returns the string representation of the token.
+     *
+     * @return a XML string representation
+     */
+    public String toString() {
+        return DOM2Writer.nodeToString((Node) this.element);
+    }
+    
+    /**
+     * Set wsu:Id attribute of this SignatureConfirmation element.
+     * @param id
+     */
+    public void setID(String id) {
+        String prefix = WSSecurityUtil.setNamespace(this.element,
+                WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+        this.element.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+    }
+    
+    /**
+     * Returns the value of the wsu:Id attribute
+     * @return TODO
+     */
+    public String getID() {
+        return this.element.getAttributeNS(WSConstants.WSU_NS, "Id");
+    }
+
+    /**
+     * @return Returns the signatureValue.
+     */
+    public byte[] getSignatureValue() {
+        return signatureValue;
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/message/token/Timestamp.java b/trunk/src/org/apache/ws/security/message/token/Timestamp.java
new file mode 100644
index 0000000..5b7af8a
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/Timestamp.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message.token;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.util.DOM2Writer;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.XmlSchemaDateFormat;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.TimeZone;
+import java.util.Vector;
+
+/**
+ * Timestamp according to SOAP Message Security 1.0,
+ * chapter 10 / appendix A.2
+ * <p/>
+ *
+ * @author Christof Soehngen (christof.soehngen@syracom.de)
+ */
+public class Timestamp {
+
+    protected Element element = null;
+    protected Vector customElements = null;
+
+    protected Calendar created;
+    protected Calendar expires;
+    
+    /**
+     * Constructs a <code>Timestamp</code> object and parses the
+     * <code>wsu:Timestamp</code> element to initialize it.
+     *
+     * @param element the <code>wsu:Timestamp</code> element that
+     *             contains the timestamp data
+     */
+    public Timestamp(Element element) throws WSSecurityException {
+
+        this.element = element;
+        
+        customElements = new Vector();
+
+        String strCreated = null;
+        String strExpires = null;
+
+        for (Node currentChild = element.getFirstChild();
+             currentChild != null;
+             currentChild = currentChild.getNextSibling()) {
+            if (currentChild instanceof Element) {
+                if (WSConstants.CREATED_LN.equals(currentChild.getLocalName()) &&
+                        WSConstants.WSU_NS.equals(currentChild.getNamespaceURI())) {
+                    if (strCreated == null) {
+                        strCreated = ((Text) ((Element) currentChild).getFirstChild()).getData();
+                    }
+                    else {
+                        throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+                                "invalidTimestamp");
+                    }
+                } else if (WSConstants.EXPIRES_LN.equals(currentChild.getLocalName()) &&
+                        WSConstants.WSU_NS.equals(currentChild.getNamespaceURI())) {
+                    if (strExpires == null) {
+                        strExpires = ((Text) ((Element) currentChild).getFirstChild()).getData();
+                    }
+                    else {
+                        throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+                        "invalidTimestamp");                        
+                    }
+                } else {
+                    customElements.add((Element) currentChild);
+                }
+            }
+        }
+
+        DateFormat zulu = new XmlSchemaDateFormat();
+        
+        try {
+            if (strCreated != null) {
+                created = Calendar.getInstance();
+                created.setTime(zulu.parse(strCreated));
+            }
+            if (strExpires != null) {
+                expires = Calendar.getInstance();
+                expires.setTime(zulu.parse(strExpires));
+            }
+        } catch (ParseException e) {
+            throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+                    "invalidTimestamp",
+                    null, e);
+        }
+    }
+
+
+    /**
+     * Constructs a <code>Timestamp</code> object according
+     * to the defined parameters.
+     * <p/>
+     *
+     * @param doc the SOAP envelope as <code>Document</code>
+     * @param ttl the time to live (validity of the security semantics) in seconds
+     */
+    public Timestamp(boolean milliseconds, Document doc, int ttl) {
+
+        customElements = new Vector();
+
+        element = 
+            doc.createElementNS(
+                WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
+            );
+        WSSecurityUtil.setNamespace(element, WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+
+        DateFormat zulu = null;
+        if (milliseconds) {
+            zulu = new XmlSchemaDateFormat();
+        }
+        else {
+            zulu = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+            zulu.setTimeZone(TimeZone.getTimeZone("UTC"));
+        }
+        created = getCurrentTime();
+
+        Element elementCreated =
+                doc.createElementNS(WSConstants.WSU_NS,
+                        WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN);
+        WSSecurityUtil.setNamespace(elementCreated,
+                WSConstants.WSU_NS,
+                WSConstants.WSU_PREFIX);
+        elementCreated.appendChild(doc.createTextNode(zulu.format(created.getTime())));
+        element.appendChild(elementCreated);
+        if (ttl != 0) {
+            long currentTime = created.getTimeInMillis();
+            currentTime += ttl * 1000;
+            expires = getCurrentTime();
+            expires.setTimeInMillis(currentTime);
+
+            Element elementExpires =
+                    doc.createElementNS(WSConstants.WSU_NS,
+                            WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN);
+            WSSecurityUtil.setNamespace(elementExpires,
+                    WSConstants.WSU_NS,
+                    WSConstants.WSU_PREFIX);
+            elementExpires.appendChild(doc.createTextNode(zulu.format(expires.getTime())));
+            element.appendChild(elementExpires);
+        }
+    }
+
+    /**
+     * Get the current time
+     * 
+     * @return calendar the current time
+     */
+    protected Calendar getCurrentTime() {
+        return Calendar.getInstance();
+    }
+    
+    /**
+     * Returns the dom element of this <code>Timestamp</code> object.
+     *
+     * @return the <code>wsse:UsernameToken</code> element
+     */
+    public Element getElement() {
+        return this.element;
+    }
+
+    /**
+     * Returns the string representation of the token.
+     *
+     * @return a XML string representation
+     */
+    public String toString() {
+        return DOM2Writer.nodeToString((Node) this.element);
+    }
+
+    /**
+     * Get the time of creation.
+     * <p/>
+     *
+     * @return the "created" time
+     */
+    public Calendar getCreated() {
+        return created;
+    }
+
+    /**
+     * Get the time of expiration.
+     * <p/>
+     *
+     * @return the "expires" time
+     */
+    public Calendar getExpires() {
+        return expires;
+    }
+
+    /**
+     * Creates and adds a custom element to this Timestamp
+     */
+    public void addCustomElement(Document doc, Element customElement) {
+        customElements.add(customElement);
+        element.appendChild(customElement);
+    }
+
+    /**
+     * Get the the custom elements from this Timestamp
+     *
+     * @return the vector containing the custom elements.
+     */
+    public Vector getCustomElements() {
+        return this.customElements;
+    }
+    
+    /**
+     * Set wsu:Id attribute of this timestamp
+     * @param id
+     */
+    public void setID(String id) {
+        String prefix = WSSecurityUtil.setNamespace(this.element,
+                WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+        this.element.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+    }
+    
+    /**
+     * Returns the value of the wsu:Id attribute
+     * @return TODO
+     */
+    public String getID() {
+        return this.element.getAttributeNS(WSConstants.WSU_NS, "Id");
+    }
+    
+}
diff --git a/trunk/src/org/apache/ws/security/message/token/UsernameToken.java b/trunk/src/org/apache/ws/security/message/token/UsernameToken.java
new file mode 100644
index 0000000..1d88f65
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/UsernameToken.java
@@ -0,0 +1,743 @@
+/*
+ * Copyright  2003-2007 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message.token;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.util.DOM2Writer;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.util.XmlSchemaDateFormat;
+import org.apache.ws.security.util.Base64;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.namespace.QName;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.text.SimpleDateFormat;
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * UsernameToken according to WS Security specifications, UsernameToken profile.
+ * 
+ * Enhanced to support digest password type for username token signature
+ * Enhanced to support passwordless usernametokens as allowed by spec.
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de)
+ */
+public class UsernameToken {
+    private static final Log log = LogFactory.getLog(UsernameToken.class.getName());
+    
+    private static final boolean doDebug = log.isDebugEnabled();
+
+    public static final String PASSWORD_TYPE = "passwordType";
+    
+    private String raw_password;        // enhancment by Alberto Coletti
+
+    protected Element element = null;
+
+    protected Element elementUsername = null;
+
+    protected Element elementPassword = null;
+
+    protected Element elementNonce = null;
+
+    protected Element elementCreated = null;
+
+    protected Element elementSalt = null;
+
+    protected Element elementIteration = null;
+
+    protected String passwordType = null;
+
+    protected boolean hashed = true;
+
+    private static SecureRandom random = null;
+
+    public static final int DEFAULT_ITERATION = 1000;
+
+    public static final QName TOKEN = new QName(WSConstants.WSSE_NS,
+            WSConstants.USERNAME_TOKEN_LN);
+
+    static {
+        try {
+            random = SecureRandom.getInstance("SHA1PRNG");
+        } catch (NoSuchAlgorithmException e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * Constructs a <code>UsernameToken</code> object and parses the
+     * <code>wsse:UsernameToken</code> element to initialize it.
+     * 
+     * @param elem
+     *            the <code>wsse:UsernameToken</code> element that contains
+     *            the UsernameToken data
+     * @throws WSSecurityException
+     */
+    public UsernameToken(Element elem) throws WSSecurityException {
+        this.element = elem;
+        QName el = new QName(this.element.getNamespaceURI(), this.element
+                .getLocalName());
+        if (!el.equals(TOKEN)) {
+            throw new WSSecurityException(
+                    WSSecurityException.INVALID_SECURITY_TOKEN,
+                    "badTokenType00", new Object[] { el });
+        }
+        elementUsername = (Element) WSSecurityUtil.getDirectChild(element,
+                WSConstants.USERNAME_LN, WSConstants.WSSE_NS);
+        elementPassword = (Element) WSSecurityUtil.getDirectChild(element,
+                WSConstants.PASSWORD_LN, WSConstants.WSSE_NS);
+        elementNonce = (Element) WSSecurityUtil.getDirectChild(element,
+                WSConstants.NONCE_LN, WSConstants.WSSE_NS);
+        elementCreated = (Element) WSSecurityUtil.getDirectChild(element,
+                WSConstants.CREATED_LN, WSConstants.WSU_NS);
+        elementSalt = (Element) WSSecurityUtil.getDirectChild(element,
+                WSConstants.SALT_LN, WSConstants.WSSE11_NS);
+        elementIteration = (Element) WSSecurityUtil.getDirectChild(element,
+                WSConstants.ITERATION_LN, WSConstants.WSSE11_NS);
+        if (elementUsername == null) {
+            throw new WSSecurityException(
+                    WSSecurityException.INVALID_SECURITY_TOKEN,
+                    "badTokenType01", new Object[] { el });
+        }
+        hashed = false;
+        if (elementSalt != null) {
+            //
+            // If the UsernameToken is to be used for key derivation, the (1.1)
+            // spec says that it cannot contain a password, and it must contain
+            // an Iteration element
+            //
+            if (elementPassword != null || elementIteration == null) {
+                throw new WSSecurityException(
+                        WSSecurityException.INVALID_SECURITY_TOKEN,
+                        "badTokenType01", new Object[] { el });
+            }
+            return;
+        }
+        if (elementPassword != null) {
+            passwordType = elementPassword.getAttribute("Type");
+        }
+        if (passwordType != null
+                && passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
+            hashed = true;
+            if (elementNonce == null || elementCreated == null) {
+                throw new WSSecurityException(
+                        WSSecurityException.INVALID_SECURITY_TOKEN,
+                        "badTokenType01", new Object[] { el });
+            }
+        }
+    }
+
+    /**
+     * Constructs a <code>UsernameToken</code> object according to the defined
+     * parameters. <p/> This constructs set the password encoding to
+     * {@link WSConstants#PASSWORD_DIGEST}
+     * 
+     * @param doc
+     *            the SOAP envelope as <code>Document</code>
+     */
+    public UsernameToken(boolean milliseconds, Document doc) {
+        this(milliseconds, doc, WSConstants.PASSWORD_DIGEST);
+    }
+
+    /**
+     * Constructs a <code>UsernameToken</code> object according to the defined
+     * parameters. <p/>
+     * 
+     * @param doc
+     *            the SOAP envelope as <code>Document</code>
+     * @param pwType
+     *            the required password encoding, either
+     *            {@link WSConstants#PASSWORD_DIGEST} or
+     *            {@link WSConstants#PASSWORD_TEXT} or 
+     *            {@link WSConstants#PW_NONE} <code>null</code> if no
+     *            password required
+     */
+    public UsernameToken(boolean milliseconds, Document doc, String pwType) {
+        this.element = doc.createElementNS(WSConstants.WSSE_NS, "wsse:"
+                + WSConstants.USERNAME_TOKEN_LN);
+        WSSecurityUtil.setNamespace(this.element, WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX);
+
+        this.elementUsername = doc.createElementNS(WSConstants.WSSE_NS, "wsse:"
+                + WSConstants.USERNAME_LN);
+        WSSecurityUtil.setNamespace(this.elementUsername, WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX);
+        this.elementUsername.appendChild(doc.createTextNode(""));
+        element.appendChild(elementUsername);
+
+        if (pwType != null) {
+            this.elementPassword = doc.createElementNS(WSConstants.WSSE_NS,
+                    "wsse:" + WSConstants.PASSWORD_LN);
+            WSSecurityUtil.setNamespace(this.elementPassword,
+                    WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);
+            this.elementPassword.appendChild(doc.createTextNode(""));
+            element.appendChild(elementPassword);
+
+            hashed = false;
+            passwordType = pwType;
+            if (passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
+                hashed = true;
+                addNonce(doc);
+                addCreated(milliseconds, doc);
+            }
+        }
+    }
+
+    /**
+     * Creates and adds a Nonce element to this UsernameToken
+     */
+    public void addNonce(Document doc) {
+        if (elementNonce != null) {
+            return;
+        }
+        byte[] nonceValue = new byte[16];
+        random.nextBytes(nonceValue);
+        this.elementNonce = doc.createElementNS(WSConstants.WSSE_NS, "wsse:"
+                + WSConstants.NONCE_LN);
+        WSSecurityUtil.setNamespace(this.elementNonce, WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX);
+        this.elementNonce.appendChild(doc.createTextNode(Base64
+                .encode(nonceValue)));
+        element.appendChild(elementNonce);
+    }
+
+    /**
+     * Creates and adds a Created element to this UsernameToken
+     */
+    public void addCreated(boolean milliseconds, Document doc) {
+        if (elementCreated != null) {
+            return;
+        }
+        DateFormat zulu = null;
+        if (milliseconds) {
+            zulu = new XmlSchemaDateFormat();
+        } else {
+            zulu = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+            zulu.setTimeZone(TimeZone.getTimeZone("UTC"));
+        }
+        Calendar rightNow = Calendar.getInstance();
+        this.elementCreated = doc.createElementNS(WSConstants.WSU_NS,
+                WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN);
+        WSSecurityUtil.setNamespace(this.elementCreated, WSConstants.WSU_NS,
+                WSConstants.WSU_PREFIX);
+        this.elementCreated.appendChild(doc.createTextNode(zulu.format(rightNow
+                .getTime())));
+        element.appendChild(elementCreated);
+    }
+
+    /**
+     * Adds and optionally creates a Salt element to this UsernameToken.
+     * 
+     * If the <code>saltValue</code> is <code>null</code> the the method
+     * generates a new salt. Otherwise it uses the the given value.
+     * 
+     * @param doc
+     *            The Document for the UsernameToken
+     * @param saltValue
+     *            The salt to add, if null generate a new salt value
+     * @param mac
+     *            If <code>true</code> then an optionally generated value is
+     *            usable for a MAC
+     * @return Returns the added salt
+     */
+    public byte[] addSalt(Document doc, byte[] saltValue, boolean mac) {
+
+        if (saltValue == null) {
+            saltValue = generateSalt(mac);
+        }
+        this.elementSalt = doc.createElementNS(WSConstants.WSSE11_NS,
+                WSConstants.WSSE11_PREFIX + ":" + WSConstants.SALT_LN);
+        WSSecurityUtil.setNamespace(this.elementSalt, WSConstants.WSSE11_NS,
+                WSConstants.WSSE11_PREFIX);
+        this.elementSalt.appendChild(doc.createTextNode(Base64
+                .encode(saltValue)));
+        element.appendChild(elementSalt);
+        return saltValue;
+    }
+
+    /**
+     * Creates and adds a Iteration element to this UsernameToken
+     */
+    public void addIteration(Document doc, int iteration) {
+        String text = "" + iteration;
+        this.elementIteration = doc.createElementNS(WSConstants.WSSE11_NS,
+                WSConstants.WSSE11_PREFIX + ":" + WSConstants.ITERATION_LN);
+        WSSecurityUtil.setNamespace(this.elementIteration,
+                WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
+        this.elementIteration.appendChild(doc.createTextNode(text));
+        element.appendChild(elementIteration);
+    }
+
+    /**
+     * Get the user name.
+     * 
+     * @return the data from the user name element.
+     */
+    public String getName() {
+        return nodeString(this.elementUsername);
+    }
+
+    /**
+     * Set the user name.
+     * 
+     * @param name
+     *            sets a text node containing the use name into the user name
+     *            element.
+     */
+    public void setName(String name) {
+        Text node = getFirstNode(this.elementUsername);
+        node.setData(name);
+    }
+
+    /**
+     * Get the nonce.
+     * 
+     * @return the data from the nonce element.
+     */
+    public String getNonce() {
+        return nodeString(this.elementNonce);
+    }
+
+    /**
+     * Get the created timestamp.
+     * 
+     * @return the data from the created time element.
+     */
+    public String getCreated() {
+        return nodeString(this.elementCreated);
+    }
+
+    /**
+     * Gets the password string. This is the password as it is in the password
+     * element of a username token. Thus it can be either plain text or the
+     * password digest value.
+     * 
+     * @return the password string or <code>null</code> if no such node
+     *         exists.
+     */
+    public String getPassword() {
+        return nodeString(this.elementPassword);
+    }
+
+    /**
+     * Get the Salt value of this UsernameToken.
+     * 
+     * @return Returns the binary Salt value or <code>null</code> if no Salt
+     *         value is available in the username token.
+     * @throws WSSecurityException
+     */
+    public byte[] getSalt() throws WSSecurityException {
+        String salt = nodeString(this.elementSalt);
+        if (salt != null) {
+            return Base64.decode(nodeString(this.elementSalt));
+        }
+        return null;
+    }
+
+    /**
+     * Get the Iteration value of this UsernameToken.
+     * 
+     * @return Returns the Iteration value. If no Iteration was specified in the
+     *         username token the default value according to the specification
+     *         is returned.
+     */
+    public int getIteration() {
+        String iter = nodeString(this.elementIteration);
+        if (iter != null) {
+            return Integer.parseInt(iter);
+        }
+        return DEFAULT_ITERATION;
+    }
+
+    /**
+     * Get the hashed indicator. If the indicator is
+     * <code>true> the password of the
+     * <code>UsernameToken</code> was encoded using
+     * {@link WSConstants#PASSWORD_DIGEST}
+     *
+     * @return the hashed indicator.
+     */
+    public boolean isHashed() {
+        return hashed;
+    }
+
+    /**
+     * @return Returns the passwordType.
+     */
+    public String getPasswordType() {
+        return passwordType;
+    }
+
+    /**
+     * Sets the password string. This function sets the password in the
+     * <code>UsernameToken</code> either as plain text or encodes the password
+     * according to the WS Security specifications, UsernameToken profile, into
+     * a password digest.
+     * 
+     * @param pwd
+     *            the password to use
+     */
+    public void setPassword(String pwd) {
+        if (pwd == null) {
+            if(this.passwordType != null) {
+                throw new IllegalArgumentException("pwd == null but a password is needed");
+            } else {
+                // Ignore setting the password.
+                return;
+            }
+        }
+        
+        raw_password = pwd;             // enhancement by Alberto coletti
+        Text node = getFirstNode(this.elementPassword);
+        try {
+            if (!hashed) {
+                node.setData(pwd);
+                this.elementPassword.setAttribute("Type",
+                        WSConstants.PASSWORD_TEXT);
+            } else {
+                node.setData(doPasswordDigest(getNonce(), getCreated(), pwd));
+                this.elementPassword.setAttribute("Type",
+                        WSConstants.PASSWORD_DIGEST);
+            }
+        } catch (Exception e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * Set the raw (plain text) password used to compute secret key.
+     * 
+     * @param raw_password the raw_password to set
+     */
+    public void setRawPassword(String raw_password) {
+        this.raw_password = raw_password;
+    }
+    
+    public static String doPasswordDigest(String nonce, String created,
+            String password) {
+        String passwdDigest = null;
+        try {
+            byte[] b1 = nonce != null ? Base64.decode(nonce) : new byte[0];
+            byte[] b2 = created != null ? created.getBytes("UTF-8") : new byte[0];
+            byte[] b3 = password.getBytes("UTF-8");
+            byte[] b4 = new byte[b1.length + b2.length + b3.length];
+            int offset = 0;
+            System.arraycopy(b1, 0, b4, offset, b1.length);
+            offset += b1.length;
+            
+            System.arraycopy(b2, 0, b4, offset, b2.length);
+            offset += b2.length;
+
+            System.arraycopy(b3, 0, b4, offset, b3.length);
+            
+            MessageDigest sha = MessageDigest.getInstance("SHA-1");
+            sha.reset();
+            sha.update(b4);
+            passwdDigest = Base64.encode(sha.digest());
+        } catch (Exception e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+        }
+        return passwdDigest;
+    }
+
+    /**
+     * Returns the first text node of an element.
+     * 
+     * @param e
+     *            the element to get the node from
+     * @return the first text node or <code>null</code> if node is null or is
+     *         not a text node
+     */
+    private Text getFirstNode(Element e) {
+        Node node = e.getFirstChild();
+        return ((node != null) && node instanceof Text) ? (Text) node : null;
+    }
+
+    /**
+     * Returns the data of an element as String or null if either the the element
+     * does not contain a Text node or the node is empty.
+     * 
+     * @param e
+     *            DOM element
+     * @return Element text node data as String
+     */
+    private String nodeString(Element e) {
+        if (e != null) {
+            Text node = getFirstNode(e);
+            if (node != null) {
+                return node.getData();
+            }
+        }
+        return null;
+
+    }
+
+    /**
+     * Returns the dom element of this <code>UsernameToken</code> object.
+     * 
+     * @return the <code>wsse:UsernameToken</code> element
+     */
+    public Element getElement() {
+        return this.element;
+    }
+
+    /**
+     * Returns the string representation of the token.
+     * 
+     * @return a XML string representation
+     */
+    public String toString() {
+        return DOM2Writer.nodeToString((Node) this.element);
+    }
+
+    /**
+     * Gets the id.
+     * 
+     * @return the value of the <code>wsu:Id</code> attribute of this username
+     *         token
+     */
+    public String getID() {
+        return this.element.getAttributeNS(WSConstants.WSU_NS, "Id");
+    }
+
+    /**
+     * Set the id of this username token.
+     * 
+     * @param id
+     *            the value for the <code>wsu:Id</code> attribute of this
+     *            username token
+     */
+    public void setID(String id) {
+        String prefix = WSSecurityUtil.setNamespace(this.element,
+                WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+        this.element.setAttributeNS(WSConstants.WSU_NS, prefix + ":Id", id);
+    }
+
+    /**
+     * Gets the secret key as per WS-Trust spec. This method uses default setting
+     * to generate the secret key. These default values are suitable for .NET
+     * WSE.
+     * 
+     * @return a secret key constructed from information contained in this
+     *         username token
+     */
+    public byte[] getSecretKey() {
+        return getSecretKey(WSConstants.WSE_DERIVED_KEY_LEN,
+                WSConstants.LABEL_FOR_DERIVED_KEY);
+    }
+
+    /**
+     * Gets the secret key as per WS-Trust spec.
+     * 
+     * @param keylen
+     *            How many bytes to generate for the key
+     * @param labelString
+     *            the label used to generate the seed
+     * @return a secret key constructed from information contained in this
+     *         username token
+     */
+    public byte[] getSecretKey(int keylen, String labelString) {
+        byte[] key = null;
+        try {
+            Mac mac = Mac.getInstance("HMACSHA1");
+            byte[] password = raw_password.getBytes("UTF-8"); // enhancement by Alberto Coletti
+            byte[] label = labelString.getBytes("UTF-8");
+            byte[] nonce = Base64.decode(getNonce());
+            byte[] created = getCreated().getBytes("UTF-8");
+            byte[] seed = new byte[label.length + nonce.length + created.length];
+
+            int offset = 0;
+            System.arraycopy(label, 0, seed, offset, label.length);
+            offset += label.length;
+            
+            System.arraycopy(nonce, 0, seed, offset, nonce.length);
+            offset += nonce.length;
+
+            System.arraycopy(created, 0, seed, offset, created.length);
+            
+            key = P_hash(password, seed, mac, keylen);
+
+            if (log.isDebugEnabled()) {
+                log.debug("password   :" + Base64.encode(password));
+                log.debug("label      :" + Base64.encode(label));
+                log.debug("nonce      :" + Base64.encode(nonce));
+                log.debug("created    :" + Base64.encode(created));
+                log.debug("seed       :" + Base64.encode(seed));
+                log.debug("Key        :" + Base64.encode(key));
+            }
+        } catch (Exception e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+            return null;
+        }
+        return key;
+    }
+    
+  
+
+    /**
+     * This static method generates a derived key as defined in WSS Username
+     * Token Profile.
+     * 
+     * @param password
+     *            The password to include in the key generation
+     * @param salt
+     *            The Salt value
+     * @param iteration
+     *            The Iteration value. If zero (0) is given the method uses the
+     *            default value
+     * @return Returns the derived key a byte array
+     * @throws WSSecurityException
+     */
+    public static byte[] generateDerivedKey(String password, byte[] salt,
+            int iteration) throws WSSecurityException {
+
+        if (iteration == 0) {
+            iteration = DEFAULT_ITERATION;
+        }
+        byte[] pwBytes = null;
+        try {
+            pwBytes = password.getBytes("UTF-8");
+        } catch (final java.io.UnsupportedEncodingException e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+            throw new WSSecurityException("Unable to convert password to UTF-8", e);
+        }
+
+        byte[] pwSalt = new byte[salt.length + pwBytes.length];
+        System.arraycopy(pwBytes, 0, pwSalt, 0, pwBytes.length);
+        System.arraycopy(salt, 0, pwSalt, pwBytes.length, salt.length);
+
+        MessageDigest sha = null;
+        try {
+            sha = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException e) {
+            if (doDebug) {
+                log.debug(e.getMessage(), e);
+            }
+            throw new WSSecurityException(
+                WSSecurityException.FAILURE, "noSHA1availabe", null, e
+            );
+        }
+        sha.reset();
+
+        /*
+         * Make the first hash round with start value
+         */
+        byte[] K = sha.digest(pwSalt);
+        /*
+         * Perform the 1st up to iteration-1 hash rounds
+         */
+        for (int i = 1; i < iteration; i++) {
+            sha.reset();
+            K = sha.digest(K);
+        }
+        return K;
+    }
+
+    /**
+     * This static method generates a 128 bit salt value as defined in WSS
+     * Username Token Profile.
+     * 
+     * @param useForMac
+     *            If <code>true</code> define the Salt for use in a MAC
+     * @return Returns the 128 bit salt value as byte array
+     */
+    public static byte[] generateSalt(boolean useForMac) {
+        byte[] saltValue = new byte[16];
+        random.nextBytes(saltValue);
+        if (useForMac) {
+            saltValue[15] = 0x01;
+        } else {
+            saltValue[15] = 0x02;
+        }
+        return saltValue;
+    }
+
+    /**
+     * P_hash as defined in RFC 2246 for TLS.
+     * 
+     * @param secret
+     *            is the key for the HMAC
+     * @param seed
+     *            the seed value to start the generation - A(0)
+     * @param mac
+     *            the HMAC algorithm
+     * @param required
+     *            number of bytes to generate
+     * @return a byte array that contains a secret key
+     * @throws Exception
+     */
+    private static byte[] P_hash(byte[] secret, byte[] seed, Mac mac,
+            int required) throws Exception {
+        byte[] out = new byte[required];
+        int offset = 0, tocpy;
+        byte[] A, tmp;
+        /*
+         * A(0) is the seed
+         */
+        A = seed;
+        SecretKeySpec key = new SecretKeySpec(secret, "HMACSHA1");
+        mac.init(key);
+        while (required > 0) {
+            mac.update(A);
+            A = mac.doFinal();
+            mac.update(A);
+            mac.update(seed);
+            tmp = mac.doFinal();
+            tocpy = min(required, tmp.length);
+            System.arraycopy(tmp, 0, out, offset, tocpy);
+            offset += tocpy;
+            required -= tocpy;
+        }
+        return out;
+    }
+
+    /**
+     * helper method.
+     * <p/>
+     *
+     * @param a
+     * @param b
+     * @return
+     */
+    private static int min(int a, int b) {
+        return (a > b) ? b : a;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/message/token/X509Security.java b/trunk/src/org/apache/ws/security/message/token/X509Security.java
new file mode 100644
index 0000000..5df7985
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/message/token/X509Security.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.message.token;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+
+/**
+ * X509 Security Token.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class X509Security extends BinarySecurity {
+    
+    public static final String X509_V3_TYPE = WSConstants.X509TOKEN_NS + "#X509v3";
+    public static final String X509_V1_TYPE = WSConstants.X509TOKEN_NS + "#X509v1";
+    
+    /*
+     * Stores the associated X.509 Certificate. This saves numerous
+     * crypto loadCertificate operations
+     */
+    private X509Certificate cachedCert = null;
+
+    /**
+     * This constructor creates a new X509 certificate object and initializes
+     * it from the data contained in the element.
+     *
+     * @param elem      the element containing the X509 certificate data
+     * @throws WSSecurityException
+     */
+    public X509Security(Element elem) throws WSSecurityException {
+        super(elem);
+        String valueType = getValueType();
+        if (!(valueType.equals(X509_V3_TYPE) || valueType.equals(X509_V1_TYPE))) {
+            throw new WSSecurityException(
+                WSSecurityException.INVALID_SECURITY_TOKEN, 
+                "invalidValueType", 
+                new Object[]{getValueType()}
+            );
+        }
+    }
+
+    /**
+     * This constructor creates a new X509 certificate element.
+     *
+     * @param doc
+     */
+    public X509Security(Document doc) {
+        super(doc);
+    }
+
+    /**
+     * Gets the X509Certificate certificate.
+     * <p/>
+     *
+     * @return the X509 certificate converted from the base 64 encoded
+     *         element data
+     * @throws WSSecurityException
+     */
+    public X509Certificate getX509Certificate(Crypto crypto) throws WSSecurityException {
+        if (cachedCert != null) {
+            return cachedCert;
+        }
+        byte[] data = getToken();
+        if (data == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "invalidCertData",
+                    new Object[]{new Integer(0)});
+        }
+        ByteArrayInputStream in = new ByteArrayInputStream(data);
+        cachedCert = crypto.loadCertificate(in);
+        return cachedCert;
+    }
+
+    /**
+     * Sets the X509Certificate.
+     * This functions takes the X509 certificate, gets the data from it as
+     * encoded bytes, and sets the data as base 64 encoded data in the text
+     * node of the element
+     *
+     * @param cert the X509 certificate to store in the element
+     * @throws WSSecurityException
+     */
+    public void setX509Certificate(X509Certificate cert)
+            throws WSSecurityException {
+        if (cert == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE, "noCert");
+        }
+        if (cert.getVersion() == 1) {
+            setValueType(X509_V1_TYPE);
+        } else {
+            setValueType(X509_V3_TYPE);
+        }
+        cachedCert = cert;
+        try {
+            setToken(cert.getEncoded());
+        } catch (CertificateEncodingException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError", null, e
+            );
+        }
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/processor/BinarySecurityTokenProcessor.java b/trunk/src/org/apache/ws/security/processor/BinarySecurityTokenProcessor.java
new file mode 100644
index 0000000..69b3a6b
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/BinarySecurityTokenProcessor.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2006,2007 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.security.processor;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.PKIPathSecurity;
+import org.apache.ws.security.message.token.X509Security;
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import java.security.cert.X509Certificate;
+import java.util.Vector;
+
+
+/**
+ * Processor implementation to handle wsse:BinarySecurityToken elements
+ */
+public class BinarySecurityTokenProcessor  implements Processor {
+
+    /**
+     * Token Id
+     */
+    private String id;
+    
+    /**
+     * Token type
+     */
+    private String type;
+    
+    /**
+     * Certificates carried in this token
+     */
+    private X509Certificate[] certificates;
+    
+    /**
+     * Token object representing the token
+     */
+    private BinarySecurity token;
+    
+    /**
+     * {@inheritDoc}
+     */
+    public String getId() {
+        return this.id;
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto,
+            CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults,
+            WSSConfig config) throws WSSecurityException {
+        this.getCertificatesTokenReference(elem, crypto);
+        returnResults.add(0, new WSSecurityEngineResult(WSConstants.BST, this.token, this.certificates));
+    }
+    
+    /**
+     * Extracts the certificate(s) from the Binary Security token reference.
+     * <p/>
+     *
+     * @param elem The element containing the binary security token. This is
+     *             either X509 certificate(s) or a PKIPath. Any other token type
+     *             is ignored.
+     * @throws WSSecurityException
+     */
+    private void getCertificatesTokenReference(Element elem, Crypto crypto)
+            throws WSSecurityException {
+        this.createSecurityToken(elem);
+        if (token instanceof PKIPathSecurity) {
+            this.certificates = ((PKIPathSecurity) token).getX509Certificates(false, crypto);
+        } else if (token instanceof X509Security) {
+            X509Certificate cert = ((X509Security) token).getX509Certificate(crypto);
+            this.certificates = new X509Certificate[1];
+            this.certificates[0] = cert;
+        }
+    }
+
+    /**
+     * Checks the <code>element</code> and creates appropriate binary security object.
+     *
+     * @param element The XML element that contains either a <code>BinarySecurityToken
+     *                </code> or a <code>PKIPath</code> element.
+     * @throws WSSecurityException
+     */
+    private void createSecurityToken(Element element) throws WSSecurityException {
+        this.token = new BinarySecurity(element);
+        String type = token.getValueType();
+
+        if (X509Security.X509_V3_TYPE.equals(type) || X509Security.X509_V1_TYPE.equals(type)) {
+            this.token = new X509Security(element);
+        } else if (PKIPathSecurity.getType().equals(type)) {
+            this.token = new PKIPathSecurity(element);
+        } 
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public X509Certificate[] getCertificates() {
+        return certificates;
+    }
+
+    public BinarySecurity getToken() {
+        return token;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/processor/DerivedKeyTokenProcessor.java b/trunk/src/org/apache/ws/security/processor/DerivedKeyTokenProcessor.java
new file mode 100644
index 0000000..f360581
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/DerivedKeyTokenProcessor.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.conversation.ConversationConstants;
+import org.apache.ws.security.conversation.dkalgo.AlgoFactory;
+import org.apache.ws.security.conversation.dkalgo.DerivationAlgorithm;
+import org.apache.ws.security.message.token.DerivedKeyToken;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.saml.SAMLKeyInfo;
+import org.apache.ws.security.saml.SAMLUtil;
+import org.apache.ws.security.util.Base64;
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * The processor to process <code>wsc:DerivedKeyToken</code>.
+ * 
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public class DerivedKeyTokenProcessor implements Processor {
+
+    private String id;
+    private byte[] keyBytes;
+    
+    private byte[] secret;
+    private int length;
+    private int offset;
+    private byte[] nonce;
+    private String label;
+    private String algorithm;
+    
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto,
+            CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults,
+            WSSConfig config) throws WSSecurityException {
+        
+        //Deserialize the DKT
+        DerivedKeyToken dkt = new DerivedKeyToken(elem);
+        
+        this.extractSecret(wsDocInfo, dkt, cb, crypto);
+        
+        String tempNonce = dkt.getNonce();
+        if(tempNonce == null) {
+            throw new WSSecurityException("Missing wsc:Nonce value");
+        }
+        this.nonce = Base64.decode(tempNonce);
+        
+        this.length = dkt.getLength();
+    
+        this.label = dkt.getLabel();
+        
+        this.algorithm = dkt.getAlgorithm();
+        
+        this.id = dkt.getID();
+
+        if(length > 0) {
+            this.deriveKey();
+        }
+    }
+
+    private void deriveKey() throws WSSecurityException{
+        try {
+            DerivationAlgorithm algo = AlgoFactory.getInstance(this.algorithm);
+            byte[] labelBytes = null;
+            if(label == null || (label != null && label.length() == 0)) {
+                labelBytes = (ConversationConstants.DEFAULT_LABEL + ConversationConstants.DEFAULT_LABEL)
+                        .getBytes("UTF-8");
+            } else {
+                labelBytes = this.label.getBytes("UTF-8");
+            }
+            
+            byte[] seed = new byte[labelBytes.length + nonce.length];
+            System.arraycopy(labelBytes, 0, seed, 0, labelBytes.length);
+            System.arraycopy(nonce, 0, seed, labelBytes.length, nonce.length);
+            
+            this.keyBytes = algo.createKey(this.secret, seed, offset, length);
+            
+        } catch (Exception e) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILURE, null, null, e
+            );
+        }
+    }
+
+    /**
+     * @param wsDocInfo
+     * @param dkt
+     * @throws WSSecurityException
+     */
+    private void extractSecret(WSDocInfo wsDocInfo, DerivedKeyToken dkt, CallbackHandler cb, Crypto crypto)
+            throws WSSecurityException {
+        SecurityTokenReference str = dkt.getSecurityTokenReference();
+        if (str != null) {
+            Processor processor;
+            String uri = null;
+            String keyIdentifierValueType = null;
+            String keyIdentifierValue = null;
+            
+            if(str.containsReference()) {
+                Reference ref = str.getReference();
+                
+                uri = ref.getURI();
+                processor = wsDocInfo.getProcessor(uri.substring(1));
+            } else {
+                //Contains key identifier
+                keyIdentifierValue = str.getKeyIdentifierValue();
+                keyIdentifierValueType = str.getKeyIdentifierValueType();
+                processor = wsDocInfo.getProcessor(keyIdentifierValue);
+            }
+            
+            if(processor == null && uri != null) {
+                //Now use the callback and get it
+                this.secret = this.getSecret(cb, uri.substring(1));
+            } else if (processor == null && keyIdentifierValue != null
+                    && keyIdentifierValueType != null) {                
+                this.secret = this.getSecret(cb, keyIdentifierValue, keyIdentifierValueType); 
+            } else if (processor instanceof EncryptedKeyProcessor) {
+                this.secret = ((EncryptedKeyProcessor) processor)
+                        .getDecryptedBytes();
+            } else if (processor instanceof SecurityContextTokenProcessor) {
+                this.secret = ((SecurityContextTokenProcessor) processor)
+                        .getSecret();
+            } else if (processor instanceof SAMLTokenProcessor) {
+                SAMLTokenProcessor samlp = (SAMLTokenProcessor) processor;
+                SAMLKeyInfo keyInfo = SAMLUtil.getSAMLKeyInfo(samlp
+                        .getSamlTokenElement(), crypto, cb);
+                //TODO Handle malformed SAML tokens where they don't have the 
+                //secret in them
+                this.secret = keyInfo.getSecret();
+            } else {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_CHECK, "unsupportedKeyId");
+            }
+        } else {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
+                    "noReference");
+        }
+    }
+
+    private byte[] getSecret(CallbackHandler cb, String id)
+            throws WSSecurityException {
+
+        if (cb == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noCallback");
+        }
+
+        WSPasswordCallback callback = new WSPasswordCallback(id, WSPasswordCallback.SECURITY_CONTEXT_TOKEN);
+        Callback[] callbacks = new Callback[1];
+        callbacks[0] = callback;
+        try {
+            cb.handle(callbacks);
+        } catch (IOException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE, "noKey",
+                    new Object[] { id }, e);
+        } catch (UnsupportedCallbackException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE, "noKey",
+                    new Object[] { id }, e);
+        }
+
+        return callback.getKey();
+    }
+    
+    private byte[] getSecret(CallbackHandler cb, String keyIdentifierValue, String keyIdentifierType) 
+                                                             throws WSSecurityException {
+        
+        if (cb == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noCallback");
+        }
+        
+        WSPasswordCallback pwcb = null;
+        
+        //Handle the EncryptedKeySHA1 type key references
+        if (keyIdentifierType.equals
+                (SecurityTokenReference.ENC_KEY_SHA1_URI)) {
+
+            pwcb = new WSPasswordCallback(keyIdentifierValue,
+                                               WSPasswordCallback.ENCRYPTED_KEY_TOKEN);
+            try {
+                cb.handle(new Callback[]{pwcb});
+            } catch (IOException e) {
+                throw new WSSecurityException(WSSecurityException.FAILURE, "noKey",
+                        new Object[] { id }, e);
+            } catch (UnsupportedCallbackException e) {
+                throw new WSSecurityException(WSSecurityException.FAILURE, "noKey",
+                        new Object[] { id }, e);
+            }
+            
+        }
+        return pwcb.getKey();
+    }
+    
+    /**
+     * Returns the wsu:Id of the DerivedKeyToken
+     * @see org.apache.ws.security.processor.Processor#getId()
+     */
+    public String getId() {
+        return this.id;
+    }
+
+    /**
+     * @return Returns the keyBytes.
+     */
+    public byte[] getKeyBytes() {
+        return keyBytes;
+    }
+    
+    /**
+     * Get the derived key bytes for a given length
+     * @return Returns the keyBytes.
+     */
+    public byte[] getKeyBytes(int len) throws WSSecurityException {
+        this.length = len;
+        this.deriveKey();
+        return keyBytes;
+    } 
+
+}
diff --git a/trunk/src/org/apache/ws/security/processor/EncryptedDataProcessor.java b/trunk/src/org/apache/ws/security/processor/EncryptedDataProcessor.java
new file mode 100644
index 0000000..4020066
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/EncryptedDataProcessor.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.security.processor;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.crypto.SecretKey;
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+import java.util.Vector;
+
+/**
+ * This will process incoming <code>xenc:EncryptedData</code> elements.
+ * This processor will not be invoked for encrypted content referenced by a 
+ * <code>xenc:ReferenceList</code>.
+ *
+ */
+public class EncryptedDataProcessor implements Processor {
+
+    
+    private byte[] symmKey;
+    
+    
+    public String getId() {
+        return null;
+    }
+
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto,
+            CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults,
+            WSSConfig config) throws WSSecurityException {
+        Element kiElem = (Element)WSSecurityUtil.findElement(elem, "KeyInfo", WSConstants.SIG_NS);
+        
+        
+        NodeList children = kiElem.getChildNodes();
+        int len = children.getLength();
+        
+        for(int i = 0; i < len; i++) {
+            Node child = children.item(i);
+            if (child.getNodeType() != Node.ELEMENT_NODE) {
+                continue;
+            }
+            QName el = new QName(child.getNamespaceURI(), child.getLocalName());
+            if(el.equals(WSSecurityEngine.ENCRYPTED_KEY)) {
+                EncryptedKeyProcessor encrKeyProc = new EncryptedKeyProcessor();
+                encrKeyProc.handleToken((Element)child, crypto, decCrypto, cb, wsDocInfo, returnResults, config);
+                this.symmKey = encrKeyProc.getDecryptedBytes();
+                break;
+            }
+        }
+        
+        String encAlgo = X509Util.getEncAlgo(elem);
+        SecretKey key = WSSecurityUtil.prepareSecretKey(encAlgo, this.symmKey);
+        
+        // initialize Cipher ....
+        XMLCipher xmlCipher = null;
+        try {
+            xmlCipher = XMLCipher.getInstance(encAlgo);
+            xmlCipher.init(XMLCipher.DECRYPT_MODE, key);
+        } catch (XMLEncryptionException e1) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e1);
+        }
+        
+        Node previousSibling = elem.getPreviousSibling();
+
+        try {
+            xmlCipher.doFinal(elem.getOwnerDocument(), elem, false);
+        } catch (Exception e) {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
+                    null, null, e);
+        }
+        
+        //GEt hold of the plain text element
+        Element decryptedElem = (Element)previousSibling.getNextSibling();
+        QName el = new QName(decryptedElem.getNamespaceURI(), decryptedElem
+                .getLocalName());
+        Processor proc = config.getProcessor(el);
+        proc.handleToken((Element) decryptedElem, crypto, decCrypto, cb,
+                wsDocInfo, returnResults, config);
+        wsDocInfo.setProcessor(proc);
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java b/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java
new file mode 100644
index 0000000..80aedc6
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java
@@ -0,0 +1,585 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDataRef;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.util.Base64;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.utils.Constants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.SecretKey;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.xml.namespace.QName;
+
+import java.io.IOException;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Vector;
+
+public class EncryptedKeyProcessor implements Processor {
+    private static Log log = LogFactory.getLog(EncryptedKeyProcessor.class.getName());
+    private static Log tlog =
+            LogFactory.getLog("org.apache.ws.security.TIME");
+    private byte[] encryptedEphemeralKey;
+    
+    private byte[] decryptedBytes = null;
+    
+    private String encryptedKeyId = null;
+
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto, CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults, WSSConfig wsc) throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("Found encrypted key element");
+        }
+        if (decCrypto == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noDecCryptoFile");
+        }
+        if (cb == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noCallback");
+        }
+        ArrayList dataRefUris = handleEncryptedKey((Element) elem, cb, decCrypto);
+        encryptedKeyId = elem.getAttributeNS(null, "Id");
+
+        returnResults.add(0, new WSSecurityEngineResult(WSConstants.ENCR, 
+                                                        this.decryptedBytes,
+                                                        this.encryptedEphemeralKey,
+                                                        this.encryptedKeyId, 
+                                                        dataRefUris));
+    }
+
+    public ArrayList handleEncryptedKey(Element xencEncryptedKey,
+                                   CallbackHandler cb, Crypto crypto) throws WSSecurityException {
+        return handleEncryptedKey(xencEncryptedKey, cb, crypto, null);
+    }
+
+    public ArrayList handleEncryptedKey(Element xencEncryptedKey,
+                                   PrivateKey privatekey) throws WSSecurityException {
+        return handleEncryptedKey(xencEncryptedKey, null, null, privatekey);
+    }
+
+    public ArrayList handleEncryptedKey(Element xencEncryptedKey,
+                                   CallbackHandler cb, Crypto crypto, PrivateKey privateKey)
+            throws WSSecurityException {
+        long t0 = 0, t1 = 0, t2 = 0;
+        if (tlog.isDebugEnabled()) {
+            t0 = System.currentTimeMillis();
+        }
+        // need to have it to find the encrypted data elements in the envelope
+        Document doc = xencEncryptedKey.getOwnerDocument();
+
+        // lookup xenc:EncryptionMethod, get the Algorithm attribute to determine
+        // how the key was encrypted. Then check if we support the algorithm
+
+        Node tmpE = null;    // short living Element used for lookups only
+        tmpE = (Element) WSSecurityUtil.getDirectChild((Node) xencEncryptedKey,
+                "EncryptionMethod", WSConstants.ENC_NS);
+        String keyEncAlgo = null;
+        if (tmpE != null) {
+            keyEncAlgo = ((Element) tmpE).getAttribute("Algorithm");
+        }
+        if (keyEncAlgo == null) {
+            throw new WSSecurityException
+                    (WSSecurityException.UNSUPPORTED_ALGORITHM, "noEncAlgo");
+        }
+        Cipher cipher = WSSecurityUtil.getCipherInstance(keyEncAlgo);
+        /*
+         * Well, we can decrypt the session (symmetric) key. Now lookup CipherValue, this is the value of the
+         * encrypted session key (session key usually is a symmetrical key that encrypts
+         * the referenced content). This is a 2-step lookup
+         */
+        Element xencCipherValue = null;
+        tmpE = (Element) WSSecurityUtil.getDirectChild((Node) xencEncryptedKey, "CipherData", WSConstants.ENC_NS);
+        if (tmpE != null) {
+            xencCipherValue = (Element) WSSecurityUtil.getDirectChild((Node) tmpE,
+                    "CipherValue", WSConstants.ENC_NS);
+        }
+        if (xencCipherValue == null) {
+            throw new WSSecurityException
+                    (WSSecurityException.INVALID_SECURITY, "noCipher");
+        }
+
+        if (privateKey == null) {
+            Element keyInfo = (Element) WSSecurityUtil.getDirectChild((Node) xencEncryptedKey,
+                    "KeyInfo", WSConstants.SIG_NS);
+            String alias;
+            if (keyInfo != null) {
+                Element secRefToken;
+                secRefToken = (Element) WSSecurityUtil.getDirectChild(keyInfo,
+                        "SecurityTokenReference", WSConstants.WSSE_NS);
+                /*
+                 * EncryptedKey must a a STR as child of KeyInfo, KeyName  
+                 * valid only for EncryptedData
+                 */
+//                if (secRefToken == null) {
+//                    secRefToken = (Element) WSSecurityUtil.getDirectChild(keyInfo,
+//                            "KeyName", WSConstants.SIG_NS);
+//                }
+                if (secRefToken == null) {
+                    throw new WSSecurityException
+                            (WSSecurityException.INVALID_SECURITY, "noSecTokRef");
+                }
+                SecurityTokenReference secRef = new SecurityTokenReference(secRefToken);
+                /*
+                 * Well, at this point there are several ways to get the key.
+                 * Try to handle all of them :-).
+                 */
+                alias = null;
+                /*
+                * handle X509IssuerSerial here. First check if all elements are available,
+                * get the appropriate data, check if all data is available.
+                * If all is ok up to that point, look up the certificate alias according
+                * to issuer name and serial number.
+                * This method is recommended by OASIS WS-S specification, X509 profile
+                */
+                if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
+                    alias = secRef.getX509IssuerSerialAlias(crypto);
+                    if (log.isDebugEnabled()) {
+                        log.debug("X509IssuerSerial alias: " + alias);
+                    }
+                }
+                /*
+                * If wsse:KeyIdentifier found, then the public key of the attached cert was used to
+                * encrypt the session (symmetric) key that encrypts the data. Extract the certificate
+                * using the BinarySecurity token (was enhanced to handle KeyIdentifier too).
+                * This method is _not_ recommended by OASIS WS-S specification, X509 profile
+                */
+                else if (secRef.containsKeyIdentifier()) {
+                    X509Certificate[] certs = secRef.getKeyIdentifier(crypto);
+                    if (certs == null || certs.length < 1 || certs[0] == null) {
+                        throw new WSSecurityException(
+                            WSSecurityException.FAILURE,
+                            "noCertsFound", 
+                            new Object[] { "decryption (KeyId)" }
+                        );
+                    }
+                    /*
+                    * Here we have the certificate. Now find the alias for it. Needed to identify
+                    * the private key associated with this certificate
+                    */
+                    alias = crypto.getAliasForX509Cert(certs[0]);
+                    if (log.isDebugEnabled()) {
+                        log.debug("cert: " + certs[0]);
+                        log.debug("KeyIdentifier Alias: " + alias);
+                    }
+                } else if (secRef.containsReference()) {
+                    Element bstElement = secRef.getTokenElement(doc, null, cb);
+
+                    // at this point ... check token type: Binary
+                    QName el =
+                            new QName(bstElement.getNamespaceURI(),
+                                    bstElement.getLocalName());
+                    if (el.equals(WSSecurityEngine.binaryToken)) {
+                        X509Security token = null;
+                        String value = bstElement.getAttribute(WSSecurityEngine.VALUE_TYPE);
+                        if (!(X509Security.X509_V3_TYPE.equals(value)
+                                || X509Security.X509_V1_TYPE.equals(value))
+                                || ((token = new X509Security(bstElement)) == null)) {
+                            throw new WSSecurityException(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+                                    "unsupportedBinaryTokenType",
+                                    new Object[]{"for decryption (BST)"});
+                        }
+                        X509Certificate cert = token.getX509Certificate(crypto);
+                        if (cert == null) {
+                            throw new WSSecurityException(
+                                WSSecurityException.FAILURE,
+                                "noCertsFound", 
+                                new Object[] { "decryption" }
+                            );
+                        }
+                        /*
+                        * Here we have the certificate. Now find the alias for it. Needed to identify
+                        * the private key associated with this certificate
+                        */
+                        alias = crypto.getAliasForX509Cert(cert);
+                        if (log.isDebugEnabled()) {
+                            log.debug("BST Alias: " + alias);
+                        }
+                    } else {
+                        throw new WSSecurityException(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+                                "unsupportedBinaryTokenType",
+                                null);
+                    }
+                    /*
+                     * The following code is somewhat strange: the called crypto method gets
+                     * the keyname and searches for a certificate with an issuer's name that is
+                     * equal to this keyname. No serialnumber is used - IMHO this does
+                     * not identifies a certificate. In addition neither the WSS4J encryption
+                     * nor signature methods use this way to identify a certificate. Because of that
+                     * the next lines of code are disabled.  
+                     */
+//                } else if (secRef.containsKeyName()) {
+//                    alias = crypto.getAliasForX509Cert(secRef.getKeyNameValue());
+//                    if (log.isDebugEnabled()) {
+//                        log.debug("KeyName alias: " + alias);
+//                    }
+                } else {
+                    throw new WSSecurityException(WSSecurityException.INVALID_SECURITY, "unsupportedKeyId");
+                }
+            } else if (crypto.getDefaultX509Alias() != null) {
+                alias = crypto.getDefaultX509Alias();
+            } else {
+                throw new WSSecurityException
+                        (WSSecurityException.INVALID_SECURITY, "noKeyinfo");
+            }
+            /*
+            * At this point we have all information necessary to decrypt the session
+            * key:
+            * - the Cipher object intialized with the correct methods
+            * - The data that holds the encrypted session key
+            * - the alias name for the private key
+            *
+            * Now use the callback here to get password that enables
+            * us to read the private key
+            */
+            WSPasswordCallback pwCb = new WSPasswordCallback(alias, WSPasswordCallback.DECRYPT);
+            Callback[] callbacks = new Callback[1];
+            callbacks[0] = pwCb;
+            try {
+                cb.handle(callbacks);
+            } catch (IOException e) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noPassword",
+                        new Object[]{alias}, e);
+            } catch (UnsupportedCallbackException e) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noPassword",
+                        new Object[]{alias}, e);
+            }
+            String password = pwCb.getPassword();
+            if (password == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noPassword", new Object[]{alias});
+            }
+
+            try {
+                privateKey = crypto.getPrivateKey(alias, password);
+            } catch (Exception e) {
+                throw new WSSecurityException(WSSecurityException.FAILED_CHECK, null, null, e);
+            }
+        }
+
+        try {
+            cipher.init(Cipher.DECRYPT_MODE,
+                    privateKey);
+        } catch (Exception e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK, null, null, e1);
+        }
+
+        try {
+            encryptedEphemeralKey = getDecodedBase64EncodedData(xencCipherValue);
+            decryptedBytes =
+                    cipher.doFinal(encryptedEphemeralKey);
+        } catch (IllegalStateException e2) {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK, null, null, e2);
+        } catch (IllegalBlockSizeException e2) {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK, null, null, e2);
+        } catch (BadPaddingException e2) {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK, null, null, e2);
+        }
+
+        if (tlog.isDebugEnabled()) {
+            t1 = System.currentTimeMillis();
+        }
+
+        /* At this point we have the decrypted session (symmetric) key. According
+         * to W3C XML-Enc this key is used to decrypt _any_ references contained in
+         * the reference list
+         * Now lookup the references that are encrypted with this key
+         */
+        String dataRefURI = null;
+        WSDataRef dataRef = null;
+        Element refList = (Element) WSSecurityUtil.getDirectChild((Node) xencEncryptedKey,
+                "ReferenceList", WSConstants.ENC_NS);
+        ArrayList dataRefs = new ArrayList();
+        if (refList != null) {
+                    
+            for (tmpE = refList.getFirstChild();
+                 tmpE != null; tmpE = tmpE.getNextSibling()) {
+                if (tmpE.getNodeType() != Node.ELEMENT_NODE) {
+                    continue;
+                }
+                if (!tmpE.getNamespaceURI().equals(WSConstants.ENC_NS)) {
+                    continue;
+                }
+                if (tmpE.getLocalName().equals("DataReference")) {                   
+                    dataRefURI = ((Element) tmpE).getAttribute("URI");
+                    dataRef = new WSDataRef(dataRefURI.substring(1));
+                    Element elt = 
+                        decryptDataRef(doc, dataRefURI,dataRef, decryptedBytes);
+                    dataRef.setName(
+                        new javax.xml.namespace.QName(
+                            elt.getNamespaceURI(),
+                            elt.getLocalName()
+                        )
+                    );
+                    dataRefs.add(dataRef);
+                }
+            }
+            return dataRefs;
+        }
+
+        if (tlog.isDebugEnabled()) {
+            t2 = System.currentTimeMillis();
+            tlog.debug("XMLDecrypt: total= " + (t2 - t0) +
+                    ", get-sym-key= " + (t1 - t0) +
+                    ", decrypt= " + (t2 - t1));
+        }
+        
+        return null;
+    }
+
+    /**
+     * Method getDecodedBase64EncodedData
+     *
+     * @param element
+     * @return a byte array containing the decoded data
+     * @throws WSSecurityException
+     */
+    public static byte[] getDecodedBase64EncodedData(Element element) throws WSSecurityException {
+        StringBuffer sb = new StringBuffer();
+        NodeList children = element.getChildNodes();
+        int iMax = children.getLength();
+        for (int i = 0; i < iMax; i++) {
+            Node curr = children.item(i);
+            if (curr.getNodeType() == Node.TEXT_NODE)
+                sb.append(((Text) curr).getData());
+        }
+        String encodedData = sb.toString();
+        return Base64.decode(encodedData);
+    }
+
+    private Element decryptDataRef(Document doc, String dataRefURI, WSDataRef wsDataRef, byte[] decryptedData) throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("found data refernce: " + dataRefURI);
+        }
+        /*
+         * Look up the encrypted data. First try wsu:Id="someURI". If no such Id then
+         * try the generic lookup to find Id="someURI"
+         */
+        Element encBodyData = null;
+        if ((encBodyData = WSSecurityUtil.getElementByWsuId(doc, dataRefURI)) == null) {
+            encBodyData = WSSecurityUtil.getElementByGenId(doc, dataRefURI);
+        }
+        if (encBodyData == null) {
+            throw new WSSecurityException
+                    (WSSecurityException.INVALID_SECURITY,
+                            "dataRef", new Object[]{dataRefURI});
+        }
+
+        boolean content = X509Util.isContent(encBodyData);
+
+        // get the encryption method
+        String symEncAlgo = X509Util.getEncAlgo(encBodyData);
+
+        SecretKey symmetricKey = WSSecurityUtil.prepareSecretKey(
+                symEncAlgo, decryptedData);
+
+        // initialize Cipher ....
+        XMLCipher xmlCipher = null;
+        try {
+            xmlCipher = XMLCipher.getInstance(symEncAlgo);
+            xmlCipher.init(XMLCipher.DECRYPT_MODE, symmetricKey);
+        } catch (XMLEncryptionException e) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
+        }
+
+        if (content) {
+            encBodyData = (Element) encBodyData.getParentNode();
+        }
+        final Node parent = encBodyData.getParentNode();
+
+        final java.util.List before_peers = listChildren(parent);
+        try {
+            xmlCipher.doFinal(doc, encBodyData, content);
+        } catch (Exception e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK, null, null, e1);
+        }
+        
+        if(parent.getLocalName().equals(WSConstants.ENCRYPTED_HEADER)
+                && parent.getNamespaceURI().equals(WSConstants.WSSE11_NS)) {
+            
+            Node decryptedHeader = parent.getFirstChild();
+            Element decryptedHeaderClone = (Element)decryptedHeader.cloneNode(true);            
+            String sigId = decryptedHeaderClone.getAttributeNS(WSConstants.WSU_NS, "Id");
+            
+            if ( sigId == null || sigId.equals("")) {
+                String id = ((Element)parent).getAttributeNS(WSConstants.WSU_NS, "Id");
+                
+                String wsuPrefix = WSSecurityUtil.setNamespace(decryptedHeaderClone,
+                        WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+                decryptedHeaderClone.setAttributeNS(WSConstants.WSU_NS, wsuPrefix + ":Id", id);
+                wsDataRef.setWsuId(id.substring(1));
+            
+            } else {
+                wsDataRef.setWsuId(sigId);
+            }
+            
+            parent.getParentNode().appendChild(decryptedHeaderClone);
+            parent.getParentNode().removeChild(parent);
+        
+        }
+             
+        final java.util.List after_peers = listChildren(parent);
+        final java.util.List new_nodes = newNodes(before_peers, after_peers);
+        for (
+            final java.util.Iterator pos = new_nodes.iterator();
+            pos.hasNext();
+        ) {
+            Node node = (Node) pos.next();
+            if (node instanceof Element) {
+                if(!Constants.SignatureSpecNS.equals(node.getNamespaceURI()) &&
+                        node.getAttributes().getNamedItemNS(WSConstants.WSU_NS, "Id") == null) {
+                    String wsuPrefix = WSSecurityUtil.setNamespace((Element)node,
+                            WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+                    ((Element)node).setAttributeNS(WSConstants.WSU_NS, wsuPrefix + ":Id", dataRefURI);
+                    wsDataRef.setWsuId(dataRefURI.substring(1));
+                    
+                }
+                wsDataRef.setName(new QName(node.getNamespaceURI(),node.getLocalName()));
+                
+                return (Element) node;
+            }
+        }
+        return encBodyData;
+    }
+    
+    /**
+     * @return      a list of Nodes, representing the 
+     */
+    private static java.util.List
+    listChildren(
+        final Node parent
+    ) {
+        if (parent == null) {
+            return java.util.Collections.EMPTY_LIST;
+        }
+        final java.util.List ret = new java.util.ArrayList();
+        if (parent.hasChildNodes()) {
+            final NodeList children = parent.getChildNodes();
+            if (children != null) {
+                for (int i = 0, n = children.getLength();  i < n;  ++i) {
+                    ret.add(children.item(i));
+                }
+            }
+        }
+        return ret;
+    }
+    
+    /**
+     * @return      a list of Nodes in b that are not in a 
+     */
+    private static java.util.List
+    newNodes(
+        final java.util.List a,
+        final java.util.List b
+    ) {
+        if (a.size() == 0) {
+            return b;
+        }
+        if (b.size() == 0) {
+            return java.util.Collections.EMPTY_LIST;
+        }
+        final java.util.List ret = new java.util.ArrayList();
+        for (
+            final java.util.Iterator bpos = b.iterator();
+            bpos.hasNext();
+        ) {
+            final Node bnode = (Node) bpos.next();
+            final java.lang.String bns = bnode.getNamespaceURI();
+            final java.lang.String bln = bnode.getLocalName();
+            boolean found = false;
+            for (
+                final java.util.Iterator apos = a.iterator();
+                apos.hasNext();
+            ) {
+                final Node anode = (Node) apos.next();
+                final java.lang.String ans = anode.getNamespaceURI();
+                final java.lang.String aln = anode.getLocalName();
+                final boolean nsmatch =
+                    ans == null
+                    ? ((bns == null) ? true : false)
+                    : ((bns == null) ? false : ans.equals(bns));
+                final boolean lnmatch =
+                    aln == null
+                    ? ((bln == null) ? true : false)
+                    : ((bln == null) ? false : aln.equals(bln));
+                if (nsmatch && lnmatch) {
+                    found = true;
+                }
+            }
+            if (!found) {
+                ret.add(bnode);
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Get the Id of the encrypted key element.
+     * 
+     * @return The Id string
+     */
+    public String getId() {
+        return encryptedKeyId;
+    }
+    
+    
+    /**
+     * Get the decrypted key.
+     * 
+     * The encrypted key element contains an encrypted session key. The
+     * security functions use the session key to encrypt contents of the message
+     * with symmetrical encryption methods.
+     *  
+     * @return The decrypted key.
+     */
+    public byte[] getDecryptedBytes() {
+        return decryptedBytes;
+    }
+
+    public byte[] getEncryptedEphemeralKey() {
+        return encryptedEphemeralKey;
+    }
+  
+}
diff --git a/trunk/src/org/apache/ws/security/processor/Processor.java b/trunk/src/org/apache/ws/security/processor/Processor.java
new file mode 100644
index 0000000..3ba080b
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/Processor.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.CallbackHandler;
+import java.util.Vector;
+
+public interface Processor {
+    
+    public void handleToken(
+        Element elem, 
+        Crypto crypto, 
+        Crypto decCrypto,
+        CallbackHandler cb, 
+        WSDocInfo wsDocInfo, 
+        Vector returnResults,
+        WSSConfig config
+    ) throws WSSecurityException;
+    
+    /**
+     * Get the Id of the processor.
+     * 
+     * @return The Id string
+     */
+    public String getId();
+}
diff --git a/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java b/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java
new file mode 100644
index 0000000..87008ab
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/ReferenceListProcessor.java
@@ -0,0 +1,398 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+import javax.crypto.SecretKey;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDataRef;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.saml.SAMLKeyInfo;
+import org.apache.ws.security.saml.SAMLUtil;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
+import org.apache.xml.security.utils.Constants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class ReferenceListProcessor implements Processor {
+    private static Log log = 
+        LogFactory.getLog(ReferenceListProcessor.class.getName());
+
+    private boolean debug = false;
+
+
+    WSDocInfo wsDocInfo = null;
+
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto,
+            CallbackHandler cb, WSDocInfo wdi, Vector returnResults,
+            WSSConfig wsc) throws WSSecurityException {
+
+        debug = log.isDebugEnabled();
+        if (debug) {
+            log.debug("Found reference list element");
+        }
+        if (cb == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noCallback");
+        }
+        wsDocInfo = wdi;
+        ArrayList uris = handleReferenceList((Element) elem, cb, crypto);
+        returnResults.add(0, new WSSecurityEngineResult(WSConstants.ENCR, uris));
+    }
+
+    /**
+     * Dereferences and decodes encrypted data elements.
+     * 
+     * @param elem
+     *            contains the <code>ReferenceList</code> to the encrypted
+     *            data elements
+     * @param cb
+     *            the callback handler to get the key for a key name stored if
+     *            <code>KeyInfo</code> inside the encrypted data elements
+     */
+    private ArrayList handleReferenceList(Element elem, CallbackHandler cb,
+            Crypto crypto) throws WSSecurityException {
+
+        Document doc = elem.getOwnerDocument();
+
+        Node tmpE = null;
+        ArrayList dataRefUris = new ArrayList();
+        for (tmpE = elem.getFirstChild(); tmpE != null; tmpE = tmpE
+                .getNextSibling()) {
+            if (tmpE.getNodeType() != Node.ELEMENT_NODE) {
+                continue;
+            }
+            if (!tmpE.getNamespaceURI().equals(WSConstants.ENC_NS)) {
+                continue;
+            }
+            if (tmpE.getLocalName().equals("DataReference")) {
+                String dataRefURI = ((Element) tmpE).getAttribute("URI");
+                WSDataRef dataRef = new WSDataRef(dataRefURI.substring(1));
+                decryptDataRefEmbedded(doc, dataRefURI, dataRef,cb, crypto);
+                dataRefUris.add(dataRef);
+            }
+        }
+        
+        return dataRefUris;
+    }
+
+    public void decryptDataRefEmbedded(Document doc, String dataRefURI, WSDataRef dataRef,
+            CallbackHandler cb, Crypto crypto) throws WSSecurityException {
+
+        if (log.isDebugEnabled()) {
+            log.debug("Found data reference: " + dataRefURI);
+        }
+        /*
+         * Look up the encrypted data. First try wsu:Id="someURI". If no such Id
+         * then try the generic lookup to find Id="someURI"
+         */
+        Element encBodyData = null;
+        if ((encBodyData = WSSecurityUtil.getElementByWsuId(doc, dataRefURI)) == null) {            
+            encBodyData = WSSecurityUtil.getElementByGenId(doc, dataRefURI);
+        }
+        if (encBodyData == null) {
+            throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+                    "dataRef", new Object[] { dataRefURI });
+        }
+
+        boolean content = X509Util.isContent(encBodyData);
+
+        // Now figure out the encryption algorithm
+        String symEncAlgo = X509Util.getEncAlgo(encBodyData);
+
+        Element tmpE = (Element) WSSecurityUtil.findElement((Node) encBodyData,
+                "KeyInfo", WSConstants.SIG_NS);
+        if (tmpE == null) {
+            throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+                    "noKeyinfo");
+        }
+
+        /*
+         * Try to get a security reference token, if none found try to get a
+         * shared key using a KeyName.
+         */
+        Element secRefToken = (Element) WSSecurityUtil.getDirectChild(tmpE,
+                "SecurityTokenReference", WSConstants.WSSE_NS);
+
+        SecretKey symmetricKey = null;
+        if (secRefToken == null) {
+            symmetricKey = X509Util.getSharedKey(tmpE, symEncAlgo, cb);
+        } else
+            symmetricKey = getKeyFromSecurityTokenReference(secRefToken, symEncAlgo, crypto, cb);
+
+        // initialize Cipher ....
+        XMLCipher xmlCipher = null;
+        try {
+            xmlCipher = XMLCipher.getInstance(symEncAlgo);
+            xmlCipher.init(XMLCipher.DECRYPT_MODE, symmetricKey);
+        } catch (XMLEncryptionException e1) {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e1);
+        }
+
+        if (content) {
+            encBodyData = (Element) encBodyData.getParentNode();
+        }
+            
+        try {
+            Node parentEncBody =encBodyData.getParentNode();
+            
+                final java.util.List before_peers = listChildren(parentEncBody);
+            
+            xmlCipher.doFinal(doc, encBodyData, content);
+            
+            if(parentEncBody.getLocalName().equals(WSConstants.ENCRYPTED_HEADER)
+                    && parentEncBody.getNamespaceURI().equals(WSConstants.WSSE11_NS)) {
+                Node decryptedHeader = parentEncBody.getFirstChild();
+                Element decryptedHeaderClone = (Element)decryptedHeader.cloneNode(true);
+                    String sigId = decryptedHeaderClone.getAttributeNS(WSConstants.WSU_NS, "Id");
+                
+                    if ( sigId == null || sigId.equals("") ) {
+                            String id = ((Element)parentEncBody).getAttributeNS(WSConstants.WSU_NS, "Id");                              
+                            String wsuPrefix = WSSecurityUtil.setNamespace(decryptedHeaderClone,
+                                        WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+                            decryptedHeaderClone.setAttributeNS(WSConstants.WSU_NS, wsuPrefix + ":Id", id);
+                            dataRef.setWsuId(id.substring(1));
+                    } else {
+                        dataRef.setWsuId(sigId);
+                    }
+                    
+                parentEncBody.getParentNode().appendChild(decryptedHeaderClone);
+                parentEncBody.getParentNode().removeChild(parentEncBody);
+                
+            } 
+            
+            final java.util.List after_peers = listChildren(parentEncBody);
+            final java.util.List new_nodes = newNodes(before_peers, after_peers);
+
+            for (
+                final java.util.Iterator pos = new_nodes.iterator();
+                pos.hasNext();
+            ) {
+                Node node = (Node) pos.next();
+                if (node instanceof Element) {
+                    if(!Constants.SignatureSpecNS.equals(node.getNamespaceURI()) &&
+                            node.getAttributes().getNamedItemNS(WSConstants.WSU_NS, "Id") == null) {
+                        String wsuPrefix = WSSecurityUtil.setNamespace((Element)node,
+                                WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
+                        ((Element)node).setAttributeNS(WSConstants.WSU_NS, wsuPrefix + ":Id", dataRefURI);
+                        dataRef.setWsuId(dataRefURI.substring(1));                              
+                    }
+                    dataRef.setName(new QName(node.getNamespaceURI(),node.getLocalName()));
+                }
+            }
+
+        } catch (Exception e) {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
+                    null, null, e);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.ws.security.processor.Processor#getId()
+     * 
+     * A reference list does not have an id.
+     */
+    public String getId() {
+        return null;
+    }
+
+    /**
+     * Retrieves a secret key (session key) from a already parsed EncryptedKey
+     * element
+     * 
+     * This method takes a security token reference (STR) element and checks if
+     * it contains a Reference element. Then it gets the vale of the URI
+     * attribute of the Reference and uses the retrieved value to lookup an
+     * EncrypteKey element to get the decrypted session key bytes. Using the
+     * algorithm parameter these bytes are converted into a secret key.
+     * 
+     * <p/>
+     * 
+     * This method requires that the EncyrptedKey element is already available,
+     * thus requires a strict layout of the security header. This method
+     * supports EncryptedKey elements within the same message.
+     * 
+     * @param secRefToken
+     *            The element containing the STR
+     * @param algorithm
+     *            A string that identifies the symmetric decryption algorithm
+     * @param crypto Crypto instance to obtain key
+     * @param cb CAllback handler to obtain the key passwords
+     * @return The secret key for the specified algorithm
+     * @throws WSSecurityException
+     */
+    private SecretKey getKeyFromSecurityTokenReference(Element secRefToken, String algorithm,
+            Crypto crypto, CallbackHandler cb)
+            throws WSSecurityException {
+
+        SecurityTokenReference secRef = new SecurityTokenReference(secRefToken);
+        byte[] decryptedData = null;
+
+        if (secRef.containsReference()) {
+            Reference reference = secRef.getReference();
+            String uri = reference.getURI();
+            String id = uri.substring(1);
+            Processor p = wsDocInfo.getProcessor(id);
+            if (p == null
+                    || (!(p instanceof EncryptedKeyProcessor)
+                            && !(p instanceof DerivedKeyTokenProcessor) 
+                            && !(p instanceof SAMLTokenProcessor))) {
+                
+                // Try custom token
+                WSPasswordCallback pwcb = new WSPasswordCallback(id, WSPasswordCallback.CUSTOM_TOKEN);
+                try {
+                    cb.handle(new Callback[]{pwcb});
+                } catch (Exception e) {
+                    throw new WSSecurityException(WSSecurityException.FAILURE,
+                            "noPassword", new Object[] { id }, e);
+                }
+                decryptedData = pwcb.getKey();
+                
+                if(decryptedData == null) {
+                    throw new WSSecurityException(
+                        WSSecurityException.FAILED_CHECK, "unsupportedKeyId");
+                }
+            }
+            if(p instanceof EncryptedKeyProcessor) {
+                EncryptedKeyProcessor ekp = (EncryptedKeyProcessor) p;
+                decryptedData = ekp.getDecryptedBytes();
+            } else if(p instanceof DerivedKeyTokenProcessor) {
+                DerivedKeyTokenProcessor dkp = (DerivedKeyTokenProcessor) p;
+                decryptedData = dkp.getKeyBytes(WSSecurityUtil.getKeyLength(algorithm));
+            } else if(p instanceof SAMLTokenProcessor) {
+                SAMLTokenProcessor samlp = (SAMLTokenProcessor) p;
+                SAMLKeyInfo keyInfo = SAMLUtil.getSAMLKeyInfo(samlp
+                        .getSamlTokenElement(), crypto, cb);
+                //TODO Handle malformed SAML tokens where they don't have the 
+                //secret in them
+                decryptedData = keyInfo.getSecret();
+            }
+        } else if (secRef.containsKeyIdentifier()){
+            if (secRef.getKeyIdentifierValueType().equals(SecurityTokenReference.ENC_KEY_SHA1_URI)) {
+                String sha = secRef.getKeyIdentifierValue();
+                WSPasswordCallback pwcb = new WSPasswordCallback(sha, WSPasswordCallback.ENCRYPTED_KEY_TOKEN);
+                
+                try {
+                    cb.handle(new Callback[]{pwcb});
+                } catch (Exception e) {
+                    throw new WSSecurityException(WSSecurityException.FAILURE,
+                            "noPassword", new Object[] { sha }, e);
+                }
+                decryptedData = pwcb.getKey();
+            }
+        
+        } else {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
+                    "noReference");
+        }
+        return WSSecurityUtil.prepareSecretKey(algorithm, decryptedData);
+    }
+    
+    /**
+     * @return      a list of Nodes, representing the 
+     */
+    private static java.util.List
+    listChildren(
+        final Node parent
+    ) {
+        if (parent == null) {
+            return java.util.Collections.EMPTY_LIST;
+        }
+        final java.util.List ret = new java.util.ArrayList();
+        if (parent.hasChildNodes()) {
+            final NodeList children = parent.getChildNodes();
+            if (children != null) {
+                for (int i = 0, n = children.getLength();  i < n;  ++i) {
+                    ret.add(children.item(i));
+                }
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * @return      a list of Nodes in b that are not in a 
+     */
+    private static java.util.List
+    newNodes(
+        final java.util.List a,
+        final java.util.List b
+    ) {
+        if (a.size() == 0) {
+            return b;
+        }
+        if (b.size() == 0) {
+            return java.util.Collections.EMPTY_LIST;
+        }
+        final java.util.List ret = new java.util.ArrayList();
+        for (
+            final java.util.Iterator bpos = b.iterator();
+            bpos.hasNext();
+        ) {
+            final Node bnode = (Node) bpos.next();
+            final java.lang.String bns = bnode.getNamespaceURI();
+            final java.lang.String bln = bnode.getLocalName();
+            boolean found = false;
+            for (
+                final java.util.Iterator apos = a.iterator();
+                apos.hasNext();
+            ) {
+                final Node anode = (Node) apos.next();
+                final java.lang.String ans = anode.getNamespaceURI();
+                final java.lang.String aln = anode.getLocalName();
+                final boolean nsmatch =
+                    ans == null
+                    ? ((bns == null) ? true : false)
+                            : ((bns == null) ? false : ans.equals(bns));
+                final boolean lnmatch =
+                    aln == null
+                    ? ((bln == null) ? true : false)
+                            : ((bln == null) ? false : aln.equals(bln));
+                if (nsmatch && lnmatch) {
+                    found = true;
+                }
+            }
+            if (!found) {
+                ret.add(bnode);
+            }
+        }
+        return ret;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/processor/SAMLTokenProcessor.java b/trunk/src/org/apache/ws/security/processor/SAMLTokenProcessor.java
new file mode 100644
index 0000000..47de64e
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/SAMLTokenProcessor.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.opensaml.SAMLAssertion;
+import org.opensaml.SAMLException;
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.CallbackHandler;
+import java.util.Vector;
+
+public class SAMLTokenProcessor implements Processor {
+    private static Log log = LogFactory.getLog(SAMLTokenProcessor.class.getName());
+    
+    private String id;
+    private Element samlTokenElement;
+
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto, CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults, WSSConfig wsc) throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("Found SAML Assertion element");
+        }
+        SAMLAssertion assertion = handleSAMLToken((Element) elem);
+        this.id = assertion.getId();
+        wsDocInfo.setAssertion((Element) elem);
+        returnResults.add(0,
+                new WSSecurityEngineResult(WSConstants.ST_UNSIGNED, assertion));
+        this.samlTokenElement = elem;
+
+    }
+
+    public SAMLAssertion handleSAMLToken(Element token) throws WSSecurityException {
+        boolean result = false;
+        SAMLAssertion assertion = null;
+        try {
+            assertion = new SAMLAssertion(token);
+            result = true;
+            if (log.isDebugEnabled()) {
+                log.debug("SAML Assertion issuer " + assertion.getIssuer());
+            }
+        } catch (SAMLException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "invalidSAMLsecurity", null, e);
+        }
+        if (!result) {
+            throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+        }
+        return assertion;
+    }
+
+    /**
+     * Return the id of the SAML token
+     */
+    public String getId() {
+        return this.id;
+    }
+
+    public Element getSamlTokenElement() {
+        return samlTokenElement;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/processor/SecurityContextTokenProcessor.java b/trunk/src/org/apache/ws/security/processor/SecurityContextTokenProcessor.java
new file mode 100644
index 0000000..85a668c
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/SecurityContextTokenProcessor.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.security.processor;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.SecurityContextToken;
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * The processor to process <code>wsc:SecurityContextToken</code>.
+ * 
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public class SecurityContextTokenProcessor implements Processor {
+
+    /**
+     * The <code>wsi:ID</code> of the <code>wsc:SecurityContextToken</code>
+     * element.
+     */
+    private String sctId;
+
+    /**
+     * The secret associated with the <code>wsc:SecurityContextToken</code>.
+     */
+    private byte[] secret;
+
+    /**
+     * The <code>wsc:Identifier</code> of the
+     * <code>wsc:SecurityContextToken</code> element.
+     */
+    private String identifier;
+
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto,
+            CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults,
+            WSSConfig config) throws WSSecurityException {
+
+        SecurityContextToken sct = new SecurityContextToken(elem);
+        this.identifier = sct.getIdentifier();
+        this.secret = this.getSecret(cb, sct);
+        this.sctId = sct.getID();
+        
+        returnResults.add(0, new WSSecurityEngineResult(WSConstants.SCT, sct));
+    }
+
+    /**
+     * Get the secret from the provided callback handler and return it.
+     * 
+     * @param cb
+     * @param sct
+     * @return The key collected using the callback handler
+     */
+    private byte[] getSecret(CallbackHandler cb, SecurityContextToken sct)
+            throws WSSecurityException {
+
+        if (cb == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noCallback");
+        }
+
+        WSPasswordCallback callback = new WSPasswordCallback(sct
+                .getIdentifier(), WSPasswordCallback.SECURITY_CONTEXT_TOKEN);
+        Callback[] callbacks = new Callback[1];
+        callbacks[0] = callback;
+        try {
+            cb.handle(callbacks);
+        } catch (IOException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE, "noKey",
+                    new Object[] { sct.getIdentifier() }, e);
+        } catch (UnsupportedCallbackException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE, "noKey",
+                    new Object[] { sct.getIdentifier() }, e);
+        }
+
+        return callback.getKey();
+    }
+
+    /**
+     * Return the id of the 
+     */
+    public String getId() {
+        return this.sctId;
+    }
+
+    /**
+     * @return Returns the identifier.
+     */
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    /**
+     * @return Returns the secret.
+     */
+    public byte[] getSecret() {
+        return secret;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/processor/SignatureConfirmationProcessor.java b/trunk/src/org/apache/ws/security/processor/SignatureConfirmationProcessor.java
new file mode 100644
index 0000000..01f5b1f
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/SignatureConfirmationProcessor.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.SignatureConfirmation;
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.CallbackHandler;
+import java.util.Vector;
+
+public class SignatureConfirmationProcessor implements Processor {
+    private static Log log = LogFactory.getLog(SignatureConfirmationProcessor.class.getName());
+
+    private String scId;
+    
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto, CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults, WSSConfig wsc) throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("Found SignatureConfirmation list element");
+        }
+        /*
+         * Decode SignatureConfirmation, just store in result
+         */
+        SignatureConfirmation sigConf = new SignatureConfirmation(
+                (Element) elem);
+        returnResults.add(0, new WSSecurityEngineResult(WSConstants.SC,
+                sigConf));
+        
+        scId = elem.getAttributeNS(WSConstants.WSU_NS, "Id");
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.ws.security.processor.Processor#getId()
+     */
+    public String getId() {
+        return scId;
+    }    
+}
diff --git a/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java b/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
new file mode 100644
index 0000000..96d878b
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright  2003-2006 The Apache Software Foundation, or their licensors, as
+ * appropriate.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.CustomTokenPrincipal;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDerivedKeyTokenPrincipal;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSDocInfoStore;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSUsernameTokenPrincipal;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.EnvelopeIdResolver;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.DerivedKeyToken;
+import org.apache.ws.security.message.token.PKIPathSecurity;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.saml.SAMLKeyInfo;
+import org.apache.ws.security.saml.SAMLUtil;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.signature.Reference;
+import org.apache.xml.security.signature.SignedInfo;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.signature.XMLSignatureException;
+import org.opensaml.SAMLAssertion;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+import java.security.Principal;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Vector;
+
+public class SignatureProcessor implements Processor {
+    private static Log log = LogFactory.getLog(SignatureProcessor.class.getName());
+    private static Log tlog =
+            LogFactory.getLog("org.apache.ws.security.TIME");
+    
+    private String signatureId;
+
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto, CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults, WSSConfig wsc) throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("Found signature element");
+        }
+        WSDocInfoStore.store(wsDocInfo);
+        X509Certificate[] returnCert = new X509Certificate[1];
+        Set returnElements = new HashSet();
+        Set protectedElements = new java.util.TreeSet();
+        byte[][] signatureValue = new byte[1][];
+        Principal lastPrincipalFound = null;
+        try {
+            lastPrincipalFound = verifyXMLSignature((Element) elem,
+                    crypto, returnCert, returnElements, protectedElements, signatureValue, cb);
+        } catch (WSSecurityException ex) {
+            throw ex;
+        } finally {
+            WSDocInfoStore.delete(wsDocInfo);
+        }
+        if (lastPrincipalFound instanceof WSUsernameTokenPrincipal) {
+            returnResults.add(0, new WSSecurityEngineResult(
+                    WSConstants.UT_SIGN, lastPrincipalFound, null,
+                    returnElements, protectedElements, signatureValue[0]));
+        } else {
+            returnResults.add(0, new WSSecurityEngineResult(
+                    WSConstants.SIGN, lastPrincipalFound,
+                    returnCert[0], returnElements, protectedElements, signatureValue[0]));
+        }
+        signatureId = elem.getAttributeNS(null, "Id");
+    }
+
+    /**
+     * Verify the WS-Security signature.
+     * <p/>
+     * The functions at first checks if then <code>KeyInfo</code> that is
+     * contained in the signature contains standard X509 data. If yes then
+     * get the certificate data via the standard <code>KeyInfo</code> methods.
+     * <p/>
+     * Otherwise, if the <code>KeyInfo</code> info does not contain X509 data, check
+     * if we can find a <code>wsse:SecurityTokenReference</code> element. If yes, the next
+     * step is to check how to get the certificate. Two methods are currently supported
+     * here:
+     * <ul>
+     * <li> A URI reference to a binary security token contained in the <code>wsse:Security
+     * </code> header.  If the dereferenced token is
+     * of the correct type the contained certificate is extracted.
+     * </li>
+     * <li> Issuer name an serial number of the certificate. In this case the method
+     * looks up the certificate in the keystore via the <code>crypto</code> parameter.
+     * </li>
+     * </ul>
+     * <p/>
+     * The methods checks is the certificate is valid and calls the
+     * {@link org.apache.xml.security.signature.XMLSignature#checkSignatureValue(X509Certificate) 
+     * verification} function.
+     *
+     * @param elem        the XMLSignature DOM Element.
+     * @param crypto      the object that implements the access to the keystore and the
+     *                    handling of certificates.
+     * @param returnCert  verifyXMLSignature stores the certificate in the first
+     *                    entry of this array. Ther caller may then further validate
+     *                    the certificate
+     * @param returnElements verifyXMLSignature adds the wsu:ID attribute values for
+     *               the signed elements to this Set
+     * @param cb CallbackHandler instance to extract key passwords
+     * @return the subject principal of the validated X509 certificate (the
+     *         authenticated subject). The calling function may use this
+     *         principal for further authentication or authorization.
+     * @throws WSSecurityException
+     */
+    protected Principal verifyXMLSignature(Element elem,
+                                           Crypto crypto,
+                                           X509Certificate[] returnCert,
+                                           Set returnElements,
+                                           Set protectedElements,
+                                           byte[][] signatureValue,
+                                           CallbackHandler cb)
+            throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("Verify XML Signature");
+        }
+        long t0 = 0, t1 = 0, t2 = 0;
+        if (tlog.isDebugEnabled()) {
+            t0 = System.currentTimeMillis();
+        }
+
+        XMLSignature sig = null;
+        try {
+            sig = new XMLSignature(elem, null);
+        } catch (XMLSecurityException e2) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILED_CHECK, "noXMLSig", null, e2
+            );
+        }
+
+        sig.addResourceResolver(EnvelopeIdResolver.getInstance());
+
+        X509Certificate[] certs = null;
+        KeyInfo info = sig.getKeyInfo();
+        byte[] secretKey = null;
+        UsernameToken ut = null;
+        DerivedKeyToken dkt = null;
+        SAMLKeyInfo samlKi = null;
+        String customTokenId = null;
+        
+        if (info != null) {
+            Node node = WSSecurityUtil.getDirectChild(info.getElement(),
+                    SecurityTokenReference.SECURITY_TOKEN_REFERENCE,
+                    WSConstants.WSSE_NS);
+            if (node == null) {
+                throw new WSSecurityException(
+                        WSSecurityException.INVALID_SECURITY,
+                        "unsupportedKeyInfo");
+            }
+            SecurityTokenReference secRef = new SecurityTokenReference((Element) node);
+
+            int docHash = elem.getOwnerDocument().hashCode();
+            /*
+             * Here we get some information about the document that is being
+             * processed, in particular the crypto implementation, and already
+             * detected BST that may be used later during dereferencing.
+             */
+            WSDocInfo wsDocInfo = WSDocInfoStore.lookup(docHash);
+
+            if (secRef.containsReference()) {
+                Element token = secRef.getTokenElement(elem.getOwnerDocument(),
+                        wsDocInfo, cb);
+                /*
+                 * at this point check token type: UsernameToken, Binary, SAML
+                 * Crypto required only for Binary and SAML
+                 */
+                QName el = new QName(token.getNamespaceURI(), token
+                        .getLocalName());
+                if (el.equals(WSSecurityEngine.usernameToken)) {
+                    String id = token.getAttributeNS(WSConstants.WSU_NS, "Id");
+                    UsernameTokenProcessor utProcessor = 
+                        (UsernameTokenProcessor) wsDocInfo.getProcessor(id);
+                    ut = utProcessor.getUt();
+                    secretKey = ut.getSecretKey();
+                } else if(el.equals(WSSecurityEngine.DERIVED_KEY_TOKEN_05_02) ||
+                        el.equals(WSSecurityEngine.DERIVED_KEY_TOKEN_05_12)) {
+                    dkt = new DerivedKeyToken(token);
+                    String id = dkt.getID();
+                    DerivedKeyTokenProcessor dktProcessor = 
+                        (DerivedKeyTokenProcessor) wsDocInfo.getProcessor(id);
+                    String signatureMethodURI = sig.getSignedInfo().getSignatureMethodURI();
+                    int keyLength = (dkt.getLength() > 0) ? dkt.getLength() : 
+                        WSSecurityUtil.getKeyLength(signatureMethodURI);
+                    
+                    secretKey = dktProcessor.getKeyBytes(keyLength);
+                } else {
+                    if (el.equals(WSSecurityEngine.binaryToken)) {
+                        //TODO: Use results from BinarySecurityTokenProcessor
+                        certs = getCertificatesTokenReference((Element) token,
+                                crypto);
+                    } else if (el.equals(WSSecurityEngine.SAML_TOKEN)) {
+                        if (crypto == null) {
+                            throw new WSSecurityException(WSSecurityException.FAILURE,
+                                "noSigCryptoFile");
+                        }
+                        samlKi = SAMLUtil.getSAMLKeyInfo(
+                                (Element) token, crypto, cb);
+                        certs = samlKi.getCerts();
+                        secretKey = samlKi.getSecret();
+
+                    } else if (el.equals(WSSecurityEngine.ENCRYPTED_KEY)){
+                        String encryptedKeyID = token.getAttributeNS(null,"Id");                   
+                        EncryptedKeyProcessor encryptKeyProcessor = (EncryptedKeyProcessor)
+                                wsDocInfo.getProcessor(encryptedKeyID);
+                        
+                        if (encryptKeyProcessor == null ) {
+                            if (crypto == null) {
+                                throw new WSSecurityException(WSSecurityException.FAILURE,
+                                    "noSigCryptoFile");
+                            }
+                            encryptKeyProcessor = new EncryptedKeyProcessor();
+                            encryptKeyProcessor.handleEncryptedKey((Element)token, cb, crypto);
+                        
+                        } 
+                        secretKey = encryptKeyProcessor.getDecryptedBytes();
+                     
+                    } else {
+                        
+                        //Try custom token through callback handler
+                        //try to find a custom token
+                        String id = secRef
+                                .getReference().getURI().substring(1);
+                        WSPasswordCallback pwcb = new WSPasswordCallback(id,
+                                WSPasswordCallback.CUSTOM_TOKEN);
+                        try {
+                            cb.handle(new Callback[]{pwcb});
+                        } catch (Exception e) {
+                            throw new WSSecurityException(WSSecurityException.FAILURE,
+                                    "noPassword", new Object[] { id }, e);
+                        }
+                        
+                        secretKey = pwcb.getKey();
+                        customTokenId = id;
+                        
+                        if(secretKey == null) {
+                            throw new WSSecurityException(
+                                    WSSecurityException.INVALID_SECURITY,
+                                    "unsupportedKeyInfo", new Object[]{el
+                                    .toString()});
+                        }
+                    }
+                }
+            } else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
+                certs = secRef.getX509IssuerSerial(crypto);
+            } else if (secRef.containsKeyIdentifier()) {
+                if (secRef.getKeyIdentifierValueType().equals
+                        (SecurityTokenReference.ENC_KEY_SHA1_URI)) {
+                    
+                    String id = secRef.getKeyIdentifierValue();
+                    WSPasswordCallback pwcb = new WSPasswordCallback(id,
+                                                       WSPasswordCallback.ENCRYPTED_KEY_TOKEN);
+                    try {
+                        cb.handle(new Callback[]{pwcb});
+                    } catch (Exception e) {
+                        throw new WSSecurityException(WSSecurityException.FAILURE,
+                                "noPassword", new Object[] { id }, e);
+                    }
+                    secretKey = pwcb.getKey();
+                    
+                } else {
+                    certs = secRef.getKeyIdentifier(crypto);
+                }
+            } else {
+                throw new WSSecurityException(
+                        WSSecurityException.INVALID_SECURITY,
+                        "unsupportedKeyInfo", new Object[]{node.toString()});
+            }
+        } else {
+            if (crypto == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noSigCryptoFile");
+            }
+            if (crypto.getDefaultX509Alias() != null) {
+                certs = crypto.getCertificates(crypto.getDefaultX509Alias());
+            } else {
+                throw new WSSecurityException(
+                        WSSecurityException.INVALID_SECURITY,
+                        "unsupportedKeyInfo");
+            }
+        }
+        if (tlog.isDebugEnabled()) {
+            t1 = System.currentTimeMillis();
+        }
+        if ((certs == null || certs.length == 0 || certs[0] == null) && secretKey == null) {
+            throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
+        }
+        if (certs != null) {
+            try {
+                certs[0].checkValidity();
+            } catch (CertificateExpiredException e) {
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_CHECK, "invalidCert", null, e
+                );
+            } catch (CertificateNotYetValidException e) {
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_CHECK, "invalidCert", null, e
+                );
+            }
+        }
+        try {
+            boolean signatureOk = false;
+            if (certs != null) {
+                signatureOk = sig.checkSignatureValue(certs[0]);
+            } else {
+                signatureOk = sig.checkSignatureValue(sig
+                        .createSecretKey(secretKey));
+            }
+            if (signatureOk) {
+                if (tlog.isDebugEnabled()) {
+                    t2 = System.currentTimeMillis();
+                    tlog.debug("Verify: total= " + (t2 - t0)
+                            + ", prepare-cert= " + (t1 - t0) + ", verify= "
+                            + (t2 - t1));
+                }
+                signatureValue[0] = sig.getSignatureValue();
+                /*
+                 * Now dig into the Signature element to get the elements that
+                 * this Signature covers. Build the QName of these Elements and
+                 * return them to caller
+                 */
+                SignedInfo si = sig.getSignedInfo();
+                int numReferences = si.getLength();
+                for (int i = 0; i < numReferences; i++) {
+                    Reference siRef;
+                    try {
+                        siRef = si.item(i);
+                    } catch (XMLSecurityException e3) {
+                        throw new WSSecurityException(
+                            WSSecurityException.FAILED_CHECK, null, null, e3
+                        );
+                    }
+                    String uri = siRef.getURI();
+                    if(uri != null && !"".equals(uri)) {
+                        Element se = WSSecurityUtil.getElementByWsuId(elem.getOwnerDocument(), uri);
+                        if (se == null) {
+                            se = WSSecurityUtil.getElementByGenId(elem
+                                    .getOwnerDocument(), uri);
+                        }
+                        if (se == null) {
+                            throw new WSSecurityException(
+                                    WSSecurityException.FAILED_CHECK);
+                        }
+                        returnElements.add(WSSecurityUtil.getIDFromReference(uri));
+                    } else {
+                       //This is the case where the signed element is identified 
+                       //by a transform such as XPath filtering
+                       //We add the complete reference element to the return 
+                       //elements
+                       returnElements.add(siRef); 
+                    }
+                }
+                
+                if (certs != null) {
+                    returnCert[0] = certs[0];
+                    return certs[0].getSubjectDN();
+                } else if(ut != null){
+                    WSUsernameTokenPrincipal principal = new WSUsernameTokenPrincipal(
+                            ut.getName(), ut.isHashed());
+                    principal.setNonce(ut.getNonce());
+                    principal.setPassword(ut.getPassword());
+                    principal.setCreatedTime(ut.getCreated());
+                    return principal;
+                } else if (dkt != null) {
+                    WSDerivedKeyTokenPrincipal principal = new WSDerivedKeyTokenPrincipal(dkt.getID());
+                    principal.setNonce(dkt.getNonce());
+                    principal.setLabel(dkt.getLabel());
+                    principal.setLength(dkt.getLength());
+                    principal.setOffset(dkt.getOffset());
+                    String basetokenId = null;
+                    SecurityTokenReference securityTokenReference = dkt
+                            .getSecurityTokenReference();
+                    if (securityTokenReference.containsReference()) {
+                        basetokenId = securityTokenReference.getReference()
+                                .getURI().substring(1);
+                    } else {
+                        // KeyIdentifier
+                        basetokenId = securityTokenReference
+                                .getKeyIdentifierValue();
+                    }
+                    principal.setBasetokenId(basetokenId);
+                    return principal;
+                } else if(samlKi != null) {
+                    final SAMLAssertion assertion = samlKi.getAssertion();
+                    CustomTokenPrincipal principal = new CustomTokenPrincipal(assertion.getId());
+                    principal.setTokenObject(assertion);
+                    return principal;
+                } else if(secretKey != null) {
+                    //This is the custom key scenario
+                    CustomTokenPrincipal principal = new CustomTokenPrincipal(customTokenId);
+                    return principal;
+                } else {
+                    throw new WSSecurityException("Cannot determine principal");
+                }
+            } else {
+                throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
+            }
+        } catch (XMLSignatureException e1) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILED_CHECK, null, null, e1
+            );
+        }
+    }
+
+    /**
+     * Extracts the certificate(s) from the Binary Security token reference.
+     * <p/>
+     *
+     * @param elem The element containing the binary security token. This is
+     *             either X509 certificate(s) or a PKIPath.
+     * @return an array of X509 certificates
+     * @throws WSSecurityException
+     */
+    public X509Certificate[] getCertificatesTokenReference(Element elem,
+                                                           Crypto crypto)
+            throws WSSecurityException {
+        if (crypto == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noSigCryptoFile");
+        }
+        BinarySecurity token = createSecurityToken(elem);
+        if (token instanceof PKIPathSecurity) {
+            return ((PKIPathSecurity) token).getX509Certificates(false, crypto);
+        } else if (token instanceof X509Security) {
+            X509Certificate cert = ((X509Security) token).getX509Certificate(crypto);
+            X509Certificate[] certs = new X509Certificate[1];
+            certs[0] = cert;
+            return certs;
+        }
+        return null;
+    }
+
+    /**
+     * Checks the <code>element</code> and creates appropriate binary security object.
+     *
+     * @param element The XML element that contains either a <code>BinarySecurityToken
+     *                </code> or a <code>PKIPath</code> element. Other element types a not
+     *                supported
+     * @return the BinarySecurity object, either a <code>X509Security</code> or a
+     *         <code>PKIPathSecurity</code> object.
+     * @throws WSSecurityException
+     */
+    private BinarySecurity createSecurityToken(Element element) throws WSSecurityException {
+        BinarySecurity token = new BinarySecurity(element);
+        String type = token.getValueType();
+        X509Security x509 = null;
+        PKIPathSecurity pkiPath = null;
+
+        if (X509Security.X509_V3_TYPE.equals(type)) {
+            x509 = new X509Security(element);
+            return (BinarySecurity) x509;
+        } else if (X509Security.X509_V1_TYPE.equals(type)) {
+            x509 = new X509Security(element);
+            return (BinarySecurity) x509;
+        } else if (PKIPathSecurity.getType().equals(type)) {
+            pkiPath = new PKIPathSecurity(element);
+            return (BinarySecurity) pkiPath;
+        }
+        throw new WSSecurityException(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+                "unsupportedBinaryTokenType", new Object[]{type});
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.ws.security.processor.Processor#getId()
+     */
+    public String getId() {
+        return signatureId;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/processor/TimestampProcessor.java b/trunk/src/org/apache/ws/security/processor/TimestampProcessor.java
new file mode 100644
index 0000000..1942c58
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/TimestampProcessor.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.Timestamp;
+import org.apache.ws.security.util.XmlSchemaDateFormat;
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.CallbackHandler;
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Vector;
+
+public class TimestampProcessor implements Processor {
+    private static Log log = LogFactory.getLog(TimestampProcessor.class.getName());
+
+    private WSSConfig wssConfig = null;
+    private String tsId;
+    
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto, CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults, WSSConfig wsc) throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("Found Timestamp list element");
+        }
+        wssConfig = wsc;
+        /*
+         * Decode Timestamp, add the found time (created/expiry) to result
+         */
+        Timestamp timestamp = new Timestamp((Element) elem);
+        handleTimestamp(timestamp);
+        returnResults.add(0,
+                new WSSecurityEngineResult(WSConstants.TS,
+                        timestamp));
+        tsId = elem.getAttributeNS(WSConstants.WSU_NS, "Id");
+
+    }
+
+    public void handleTimestamp(Timestamp timestamp) throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("Preparing to verify the timestamp");
+
+            DateFormat zulu = new XmlSchemaDateFormat();
+
+            log.debug("Current time: "
+                    + zulu.format(Calendar.getInstance().getTime()));
+            if (timestamp.getCreated() != null) {
+                log.debug("Timestamp created: "
+                        + zulu.format(timestamp.getCreated().getTime()));
+            }
+            if (timestamp.getExpires() != null) {
+                log.debug("Timestamp expires: "
+                        + zulu.format(timestamp.getExpires().getTime()));
+            }
+        }
+
+        // Validate whether the security semantics have expired
+        Calendar rightNow = Calendar.getInstance();
+        Calendar exp = timestamp.getExpires();
+        if (exp != null && wssConfig.isTimeStampStrict() && exp.before(rightNow)) {
+            throw new WSSecurityException(
+                    WSSecurityException.MESSAGE_EXPIRED,
+                    "invalidTimestamp",
+                    new Object[] { "The security semantics of message have expired" });
+        }
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.ws.security.processor.Processor#getId()
+     */
+    public String getId() {
+        return tsId;
+    }    
+    
+}
diff --git a/trunk/src/org/apache/ws/security/processor/UsernameTokenProcessor.java b/trunk/src/org/apache/ws/security/processor/UsernameTokenProcessor.java
new file mode 100644
index 0000000..32fb630
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/UsernameTokenProcessor.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSUsernameTokenPrincipal;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Vector;
+
+public class UsernameTokenProcessor implements Processor {
+    private static Log log = LogFactory.getLog(UsernameTokenProcessor.class.getName());
+
+    private String utId;
+    private UsernameToken ut;
+    private boolean handleCustomPasswordTypes;
+    
+    public void handleToken(Element elem, Crypto crypto, Crypto decCrypto, CallbackHandler cb, WSDocInfo wsDocInfo, Vector returnResults, WSSConfig wsc) throws WSSecurityException {
+        if (log.isDebugEnabled()) {
+            log.debug("Found UsernameToken list element");
+        }
+        handleCustomPasswordTypes = wsc.getHandleCustomPasswordTypes();
+        
+        Principal lastPrincipalFound = handleUsernameToken((Element) elem, cb);
+        returnResults.add(0, new WSSecurityEngineResult(WSConstants.UT,
+                lastPrincipalFound, null, null, null));
+        utId = elem.getAttributeNS(WSConstants.WSU_NS, "Id");
+    }
+
+    /**
+     * Check the UsernameToken element. Depending on the password type
+     * contained in the element the processing differs. If the password type
+     * is digested, then retrieve a password from the callback handler and
+     * authenticate the UsernameToken here.
+     * <p/>
+     * If the password is in plaintext or any other yet unknown password type
+     * then delegate the password validation to the callback class. Note that for unknown
+     * password types an exception is thrown if WSSConfig.getHandleCustomPasswordTypes()
+     * is set to false (as it is by default). The security engine hands over all necessary
+     * data to the callback class via the WSPasswordCallback object. The usage parameter of
+     * WSPasswordCallback is set to <code>USERNAME_TOKEN_UNKNOWN</code>.
+     *
+     * @param token the DOM element that contains the UsernameToken
+     * @param cb    the reference to the callback object
+     * @return WSUsernameTokenPrincipal that contain data that an application
+     *         may use to further validate the password/user combination.
+     * @throws WSSecurityException
+     */
+    public WSUsernameTokenPrincipal handleUsernameToken(Element token, CallbackHandler cb) 
+        throws WSSecurityException {
+        ut = new UsernameToken(token);
+        String user = ut.getName();
+        String password = ut.getPassword();
+        String nonce = ut.getNonce();
+        String createdTime = ut.getCreated();
+        String pwType = ut.getPasswordType();
+        if (log.isDebugEnabled()) {
+            log.debug("UsernameToken user " + user);
+            log.debug("UsernameToken password " + password);
+        }
+
+        Callback[] callbacks = new Callback[1];
+        String origPassword = null;
+        
+        //
+        // If the UsernameToken is hashed, then retrieve the password from the callback handler 
+        // and compare directly. If the UsernameToken is in plaintext or of some unknown type,
+        // then delegate authentication to the callback handler
+        //
+        if (ut.isHashed()) {
+            if (cb == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE, "noCallback");
+            }
+
+            WSPasswordCallback pwCb = new WSPasswordCallback(user, WSPasswordCallback.USERNAME_TOKEN);
+            callbacks[0] = pwCb;
+            try {
+                cb.handle(callbacks);
+            } catch (IOException e) {
+                if (log.isDebugEnabled()) {
+                    log.debug(e);
+                }
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_AUTHENTICATION, null, null, e
+                );
+            } catch (UnsupportedCallbackException e) {
+                if (log.isDebugEnabled()) {
+                    log.debug(e);
+                }
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_AUTHENTICATION, null, null, e
+                );
+            }
+            origPassword = pwCb.getPassword();
+            if (log.isDebugEnabled()) {
+                log.debug("UsernameToken callback password " + origPassword);
+            }
+            if (origPassword == null) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Callback supplied no password for: " + user);
+                }
+                throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+            }
+            String passDigest = UsernameToken.doPasswordDigest(nonce, createdTime, origPassword);
+            if (!passDigest.equals(password)) {
+                throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+            }
+            ut.setRawPassword(origPassword);
+        } else {
+            if (cb == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE, "noCallback");
+            } else if (!WSConstants.PASSWORD_TEXT.equals(pwType) && !handleCustomPasswordTypes) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Authentication failed as handleCustomUsernameTokenTypes is false");
+                }
+                throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+            }
+            WSPasswordCallback pwCb = new WSPasswordCallback(user, password,
+                    pwType, WSPasswordCallback.USERNAME_TOKEN_UNKNOWN);
+            callbacks[0] = pwCb;
+            try {
+                cb.handle(callbacks);
+            } catch (IOException e) {
+                if (log.isDebugEnabled()) {
+                    log.debug(e);
+                }
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_AUTHENTICATION, null, null, e
+                );
+            } catch (UnsupportedCallbackException e) {
+                if (log.isDebugEnabled()) {
+                    log.debug(e);
+                }
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_AUTHENTICATION, null, null, e
+                );
+            }
+            ut.setRawPassword(password);
+        }
+        WSUsernameTokenPrincipal principal = new WSUsernameTokenPrincipal(user, ut.isHashed());
+        principal.setNonce(nonce);
+        principal.setPassword(password);
+        principal.setCreatedTime(createdTime);
+        principal.setPasswordType(pwType);
+
+        return principal;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.ws.security.processor.Processor#getId()
+     */
+    public String getId() {
+        return utId;
+    }
+
+    /**
+     * Get the processed UsernameToken.
+     * 
+     * @return the ut
+     */
+    public UsernameToken getUt() {
+        return ut;
+    }    
+}
diff --git a/trunk/src/org/apache/ws/security/processor/X509Util.java b/trunk/src/org/apache/ws/security/processor/X509Util.java
new file mode 100644
index 0000000..75d9c94
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/processor/X509Util.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.processor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.crypto.SecretKey;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+public class X509Util {
+    private static Log log = LogFactory.getLog(X509Util.class.getName());
+
+    public static boolean isContent(Node encBodyData) {
+        /*
+         * Depending on the encrypted data type (Content or Element) the encBodyData either
+         * holds the element whose contents where encrypted, e.g. soapenv:Body, or the
+         * xenc:EncryptedData element (in case of Element encryption). In either case we need
+         * to get the xenc:EncryptedData element. So get it. The findElement method returns
+         * immediately if its already the correct element.
+         * Then we can get the Type attribute.
+         */
+
+        Element tmpE = (Element) WSSecurityUtil.findElement(encBodyData,
+                "EncryptedData", WSConstants.ENC_NS);
+        String typeStr = null;
+        boolean content = true;
+        if (tmpE != null) {
+            typeStr = tmpE.getAttribute("Type");
+        }
+        if (typeStr != null) {
+            content = typeStr.equals(WSConstants.ENC_NS + "Content") ? true : false;
+        }
+        return content;
+    }
+
+    public static String getEncAlgo(Node encBodyData) throws WSSecurityException {
+        Element tmpE = (Element) WSSecurityUtil.findElement(encBodyData,
+                "EncryptionMethod", WSConstants.ENC_NS);
+
+        String symEncAlgo = null;
+        if (tmpE != null) {
+            symEncAlgo = tmpE.getAttribute("Algorithm");
+        }
+        if (symEncAlgo == null) {
+            throw new WSSecurityException
+                    (WSSecurityException.UNSUPPORTED_ALGORITHM,
+                            "noEncAlgo");
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("Sym Enc Algo: " + symEncAlgo);
+        }
+        return symEncAlgo;
+    }
+
+    protected static SecretKey getSharedKey(Element keyInfoElem,
+                                            String algorithm,
+                                            CallbackHandler cb)
+            throws WSSecurityException {
+        String keyName = null;
+        Element keyNmElem =
+                (Element) WSSecurityUtil.getDirectChild(keyInfoElem,
+                        "KeyName",
+                        WSConstants.SIG_NS);
+        if (keyNmElem != null) {
+            keyNmElem.normalize();
+            Node tmpN;
+            if ((tmpN = keyNmElem.getFirstChild()) != null
+                    && tmpN.getNodeType() == Node.TEXT_NODE) {
+                keyName = tmpN.getNodeValue();
+            }
+        }
+        if (keyName == null) {
+            throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+                    "noKeyname");
+        }
+        WSPasswordCallback pwCb = new WSPasswordCallback(
+                keyName, WSPasswordCallback.KEY_NAME);
+        Callback[] callbacks = new Callback[1];
+        callbacks[0] = pwCb;
+        try {
+            cb.handle(callbacks);
+        } catch (IOException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noPassword",
+                    new Object[]{keyName}, e);
+        } catch (UnsupportedCallbackException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noPassword",
+                    new Object[]{keyName}, e);
+        }
+        byte[] decryptedData = pwCb.getKey();
+        if (decryptedData == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "noPassword",
+                    new Object[]{keyName});
+        }
+        return WSSecurityUtil.prepareSecretKey(algorithm, decryptedData);
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/saml/SAMLIssuer.java b/trunk/src/org/apache/ws/security/saml/SAMLIssuer.java
new file mode 100644
index 0000000..4542485
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/saml/SAMLIssuer.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.saml;
+
+import org.apache.ws.security.components.crypto.Crypto;
+import org.opensaml.SAMLAssertion;
+import org.w3c.dom.Document;
+
+/**
+ * Builds a WS SAML Assertion and inserts it into the SOAP Envelope.
+ * Refer to the WS specification, SAML Token profile
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+
+public interface SAMLIssuer {
+
+    /**
+     * Creates a new <code>SAMLAssertion</code>.
+     * <p/>
+     * A complete <code>SAMLAssertion</code> is constructed.
+     *
+     * @return SAMLAssertion
+     */
+    public SAMLAssertion newAssertion();
+
+    /**
+     * @param userCrypto The userCrypto to set.
+     */
+    public void setUserCrypto(Crypto userCrypto);
+
+    /**
+     * @param username The username to set.
+     */
+    public void setUsername(String username);
+
+    /**
+     * @return Returns the issuerCrypto.
+     */
+    public Crypto getIssuerCrypto();
+
+    /**
+     * @return Returns the issuerKeyName.
+     */
+    public String getIssuerKeyName();
+
+    /**
+     * @return Returns the issuerKeyPassword.
+     */
+    public String getIssuerKeyPassword();
+
+    /**
+     * @return Returns the senderVouches.
+     */
+    public boolean isSenderVouches();
+
+    /**
+     * @param instanceDoc The instanceDoc to set.
+     */
+    public void setInstanceDoc(Document instanceDoc);
+}
diff --git a/trunk/src/org/apache/ws/security/saml/SAMLIssuerFactory.java b/trunk/src/org/apache/ws/security/saml/SAMLIssuerFactory.java
new file mode 100644
index 0000000..a60c911
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/saml/SAMLIssuerFactory.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.saml;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.util.Loader;
+
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.util.Properties;
+
+/**
+ * CryptoFactory.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public abstract class SAMLIssuerFactory {
+    private static final Log log = LogFactory.getLog(SAMLIssuerFactory.class);
+    private static final boolean doDebug = log.isDebugEnabled();
+    private static final String defaultSAMLClassName =
+            "org.apache.ws.security.saml.SAMLIssuerImpl";
+
+    /**
+     * getInstance
+     * <p/>
+     * Returns an instance of SAMLIssuer. This method uses the file
+     * <code>saml.properties</code> to determine which implementation to
+     * use. Thus the property <code>org.apache.ws.security.saml.issuerClass</code>
+     * must define the classname of the SAMLIssuer implementation. The file
+     * may contain other property definitions as well. These properties are
+     * handed over to the  SAMLIssuer implementation. The file
+     * <code>saml.properties</code> is loaded with the
+     * <code>Loader.getResource()</code> method.
+     * <p/>
+     *
+     * @return The SAMLIssuer implementation was defined
+     */
+    public static SAMLIssuer getInstance() {
+        return getInstance("saml.properties");
+    }
+
+    /**
+     * getInstance
+     * <p/>
+     * Returns an instance of SAMLIssuer. The properties are handed over the the SAMLIssuer
+     * implementation. The porperties can be <code>null</code>. It is depenend on the
+     * SAMLIssuer implementation how the initialization is done in this case.
+     * <p/>
+     *
+     * @param samlClassName This is the SAMLIssuer implementation class. No default is
+     *                      provided here.
+     * @param properties    The Properties that are forwarded to the SAMLIssuer implementaion.
+     *                      These properties are dependend on the SAMLIssuer implementatin
+     * @return The SAMLIssuer implementation or null if no samlClassName was defined
+     */
+    public static SAMLIssuer getInstance(String samlClassName,
+                                         Properties properties) {
+        return loadClass(samlClassName, properties);
+    }
+
+    /**
+     * getInstance
+     * <p/>
+     * Returns an instance of SAMLIssuer. This method uses the specifed filename
+     * to load a property file. This file shall use the property
+     * <code>org.apache.ws.security.saml.issuerClass</code>
+     * to define the classname of the SAMLIssuer implementation. The file
+     * may contain other property definitions as well. These properties are
+     * handed over to the SAMLIssuer implementation. The specified file
+     * is loaded with the <code>Loader.getResource()</code> method.
+     * <p/>
+     *
+     * @param propFilename The name of the property file to load
+     * @return The SAMLIssuer implementation that was defined
+     */
+    public static SAMLIssuer getInstance(String propFilename) {
+        Properties properties = null;
+        String samlClassName = null;
+
+        if ((samlClassName == null) || (samlClassName.length() == 0)) {
+            properties = getProperties(propFilename);
+            samlClassName =
+                    properties.getProperty("org.apache.ws.security.saml.issuerClass",
+                            defaultSAMLClassName);
+        }
+        return loadClass(samlClassName, properties);
+    }
+
+    private static SAMLIssuer loadClass(String samlClassName,
+                                        Properties properties) {
+        Class samlIssuerClass = null;
+        SAMLIssuer samlIssuer = null;
+        try {
+            // instruct the class loader to load the crypto implementation
+            samlIssuerClass = Loader.loadClass(samlClassName);
+        } catch (ClassNotFoundException ex) {
+            if (log.isDebugEnabled()) {
+                log.debug(ex.getMessage(), ex);
+            }
+            throw new RuntimeException(samlClassName + " Not Found", ex);
+        }
+        log.info("Using Crypto Engine [" + samlClassName + "]");
+        try {
+            Class[] classes = new Class[]{Properties.class};
+            Constructor c = samlIssuerClass.getConstructor(classes);
+            samlIssuer =
+                    (SAMLIssuer) c.newInstance(new Object[]{properties});
+            return samlIssuer;
+        } catch (java.lang.Exception ex) {
+            if (log.isDebugEnabled()) {
+                log.debug(ex.getMessage(), ex);
+            }
+        }
+        try {
+            // try to instantiate the Crypto subclass
+            samlIssuer = (SAMLIssuer) samlIssuerClass.newInstance();
+            return samlIssuer;
+        } catch (java.lang.Exception ex) {
+            if (log.isDebugEnabled()) {
+                log.debug(ex.getMessage(), ex);
+            }
+            throw new RuntimeException(samlClassName + " cannot create instance", ex);
+        }
+    }
+
+    /**
+     * Gets the properties for SAML issuer.
+     * The functions loads the property file via
+     * {@link Loader.getResource(String)}, thus the property file
+     * should be accessible via the classpath
+     *
+     * @param propFilename the properties file to load
+     * @return a <code>Properties</code> object loaded from the filename
+     */
+    private static Properties getProperties(String propFilename) {
+        Properties properties = new Properties();
+        try {
+            URL url = Loader.getResource(propFilename);
+            properties.load(url.openStream());
+        } catch (Exception e) {
+            if (doDebug) {
+                log.debug("Cannot find SAML property file: " + propFilename, e);
+            }
+            throw new RuntimeException("SAMLIssuerFactory: Cannot load properties: " + propFilename, e);
+        }
+        return properties;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/saml/SAMLIssuerImpl.java b/trunk/src/org/apache/ws/security/saml/SAMLIssuerImpl.java
new file mode 100644
index 0000000..122ef7f
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/saml/SAMLIssuerImpl.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.saml;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.signature.XMLSignature;
+import org.opensaml.SAMLAssertion;
+import org.opensaml.SAMLAuthenticationStatement;
+import org.opensaml.SAMLException;
+import org.opensaml.SAMLNameIdentifier;
+import org.opensaml.SAMLStatement;
+import org.opensaml.SAMLSubject;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Properties;
+
+/**
+ * Builds a WS SAML Assertion and inserts it into the SOAP Envelope. Refer to
+ * the WS specification, SAML Token profile
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class SAMLIssuerImpl implements SAMLIssuer {
+
+    private static final Log log = LogFactory.getLog(SAMLIssuerImpl.class.getName());
+
+    private SAMLAssertion sa = null;
+
+    private Document instanceDoc = null;
+
+    private Properties properties = null;
+
+    private Crypto issuerCrypto = null;
+    private String issuerKeyPassword = null;
+    private String issuerKeyName = null;
+
+    private boolean senderVouches = true;
+
+    private String[] confirmationMethods = new String[1];
+    private Crypto userCrypto = null;
+    private String username = null;
+
+    /**
+     * Constructor.
+     */
+    public SAMLIssuerImpl() {
+    }
+
+    public SAMLIssuerImpl(Properties prop) {
+        /*
+         * if no properties .. just return an instance, the rest will be done
+         * later or this instance is just used to handle certificate
+         * conversions in this implementation
+         */
+        if (prop == null) {
+            return;
+        }
+        properties = prop;
+
+        String cryptoProp =
+                properties.getProperty("org.apache.ws.security.saml.issuer.cryptoProp.file");
+        if (cryptoProp != null) {
+            issuerCrypto = CryptoFactory.getInstance(cryptoProp);
+            issuerKeyName =
+                    properties.getProperty("org.apache.ws.security.saml.issuer.key.name");
+            issuerKeyPassword =
+                    properties.getProperty("org.apache.ws.security.saml.issuer.key.password");
+        }
+
+        if ("senderVouches"
+                .equals(properties.getProperty("org.apache.ws.security.saml.confirmationMethod"))) {
+            confirmationMethods[0] = SAMLSubject.CONF_SENDER_VOUCHES;
+        } else if (
+                "keyHolder".equals(properties.getProperty("org.apache.ws.security.saml.confirmationMethod"))) {
+            confirmationMethods[0] = SAMLSubject.CONF_HOLDER_KEY;
+            senderVouches = false;
+        } else {
+            // throw something here - this is a mandatory property
+        }
+    }
+
+    /**
+     * Creates a new <code>SAMLAssertion</code>.
+     * <p/>
+     * <p/>
+     * A complete <code>SAMLAssertion</code> is constructed.
+     *
+     * @return SAMLAssertion
+     */
+    public SAMLAssertion newAssertion() { // throws Exception {
+        log.debug("Begin add SAMLAssertion token...");
+
+        /*
+         * if (senderVouches == false && userCrypto == null) { throw
+         * exception("need user crypto data to insert key") }
+         */
+        // Issuer must enable crypto functions to get the issuer's certificate
+        String issuer =
+                properties.getProperty("org.apache.ws.security.saml.issuer");
+        String name =
+                properties.getProperty("org.apache.ws.security.saml.subjectNameId.name");
+        String qualifier =
+                properties.getProperty("org.apache.ws.security.saml.subjectNameId.qualifier");
+        try {
+            SAMLNameIdentifier nameId =
+                    new SAMLNameIdentifier(name, qualifier, "");
+            String subjectIP = null;
+            String authMethod = null;
+            if ("password"
+                    .equals(properties.getProperty("org.apache.ws.security.saml.authenticationMethod"))) {
+                authMethod =
+                        SAMLAuthenticationStatement.AuthenticationMethod_Password;
+            }
+            Date authInstant = new Date();
+            Collection bindings = null;
+
+            SAMLSubject subject =
+                    new SAMLSubject(nameId,
+                            Arrays.asList(confirmationMethods),
+                            null,
+                            null);
+            SAMLStatement[] statements =
+                    {
+                        new SAMLAuthenticationStatement(subject,
+                                authMethod,
+                                authInstant,
+                                subjectIP,
+                                null,
+                                bindings)};
+            sa =
+                    new SAMLAssertion(issuer,
+                            null,
+                            null,
+                            null,
+                            null,
+                            Arrays.asList(statements));
+
+            if (!senderVouches) {
+                KeyInfo ki = new KeyInfo(instanceDoc);
+                try {
+                    X509Certificate[] certs =
+                            userCrypto.getCertificates(username);
+                    X509Data certElem = new X509Data(instanceDoc);
+                    certElem.addCertificate(certs[0]);
+                    ki.add(certElem);
+                } catch (WSSecurityException ex) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(ex.getMessage(), ex);
+                    }
+                    return null;
+                } catch (XMLSecurityException ex) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(ex.getMessage(), ex);
+                    }
+                    return null;
+                }
+                Element keyInfoElement = ki.getElement();
+                keyInfoElement.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                        + WSConstants.SIG_PREFIX, WSConstants.SIG_NS);
+
+                subject.setKeyInfo(ki);
+                // prepare to sign the SAML token
+                try {
+                    X509Certificate[] issuerCerts =
+                            issuerCrypto.getCertificates(issuerKeyName);
+
+                    String sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
+                    String pubKeyAlgo =
+                            issuerCerts[0].getPublicKey().getAlgorithm();
+                    log.debug("automatic sig algo detection: " + pubKeyAlgo);
+                    if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
+                        sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+                    }
+                    java.security.Key issuerPK =
+                            issuerCrypto.getPrivateKey(issuerKeyName,
+                                    issuerKeyPassword);
+                    sa.sign(sigAlgo, issuerPK, Arrays.asList(issuerCerts));
+                } catch (WSSecurityException ex) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(ex.getMessage(), ex);
+                    }
+                    return null;
+                } catch (Exception ex) {
+                    if (log.isDebugEnabled()) {
+                        log.debug(ex.getMessage(), ex);
+                    }
+                    return null;
+                }
+            }
+        } catch (SAMLException ex) {
+            if (log.isDebugEnabled()) {
+                log.debug(ex.getMessage(), ex);
+            }
+            throw new RuntimeException(ex.toString(), ex);
+        }
+        return sa;
+    }
+
+    /**
+     * @param userCrypto The userCrypto to set.
+     */
+    public void setUserCrypto(Crypto userCrypto) {
+        this.userCrypto = userCrypto;
+    }
+
+    /**
+     * @param username The username to set.
+     */
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    /**
+     * @return Returns the issuerCrypto.
+     */
+    public Crypto getIssuerCrypto() {
+        return issuerCrypto;
+    }
+
+    /**
+     * @return Returns the issuerKeyName.
+     */
+    public String getIssuerKeyName() {
+        return issuerKeyName;
+    }
+
+    /**
+     * @return Returns the issuerKeyPassword.
+     */
+    public String getIssuerKeyPassword() {
+        return issuerKeyPassword;
+    }
+
+    /**
+     * @return Returns the senderVouches.
+     */
+    public boolean isSenderVouches() {
+        return senderVouches;
+    }
+
+    /**
+     * @param instanceDoc The instanceDoc to set.
+     */
+    public void setInstanceDoc(Document instanceDoc) {
+        this.instanceDoc = instanceDoc;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/saml/SAMLKeyInfo.java b/trunk/src/org/apache/ws/security/saml/SAMLKeyInfo.java
new file mode 100644
index 0000000..d1d5555
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/saml/SAMLKeyInfo.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 20046,2007 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.security.saml;
+
+import org.opensaml.SAMLAssertion;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * This holds key/cert information extracted from a SAML assertion
+ */
+public class SAMLKeyInfo {
+
+    /**
+     * Certificates
+     */
+    private X509Certificate[] certs;
+    
+    /**
+     * Key bytes (e.g.: held in an encrypted key)
+     */
+    private byte[] secret;
+    
+    /**
+     * SAMLAssertion
+     */
+    SAMLAssertion assertion;
+    
+    public SAMLKeyInfo(SAMLAssertion assertions, X509Certificate[] certs) {
+        this.certs = certs;
+        this.assertion = assertions;
+    }
+    
+    public SAMLKeyInfo(SAMLAssertion assertions, byte[] secret) {
+        this.secret = secret;
+        this.assertion = assertions;
+    }
+    
+    public X509Certificate[] getCerts() {
+        return certs;
+    }
+    public byte[] getSecret() {
+        return secret;
+    }
+
+    public SAMLAssertion getAssertion() {
+        return assertion;
+    }
+    
+}
\ No newline at end of file
diff --git a/trunk/src/org/apache/ws/security/saml/SAMLUtil.java b/trunk/src/org/apache/ws/security/saml/SAMLUtil.java
new file mode 100644
index 0000000..1497e28
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/saml/SAMLUtil.java
@@ -0,0 +1,256 @@
+package org.apache.ws.security.saml;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.processor.EncryptedKeyProcessor;
+import org.apache.ws.security.util.Base64;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.keys.content.x509.XMLX509Certificate;
+import org.opensaml.SAMLAssertion;
+import org.opensaml.SAMLAttributeStatement;
+import org.opensaml.SAMLAuthenticationStatement;
+import org.opensaml.SAMLException;
+import org.opensaml.SAMLObject;
+import org.opensaml.SAMLStatement;
+import org.opensaml.SAMLSubject;
+import org.opensaml.SAMLSubjectStatement;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.namespace.QName;
+
+import java.security.cert.X509Certificate;
+import java.util.Iterator;
+
+/**
+ * Utility methods for SAML stuff
+ */
+public class SAMLUtil {
+    private static Log log = LogFactory.getLog(SAMLUtil.class.getName());
+
+    
+    
+    /**
+     * Extract certificates or the key available in the SAMLAssertion
+     * @param elem
+     * @return the SAML Key Info
+     * @throws WSSecurityException
+     */
+    public static SAMLKeyInfo getSAMLKeyInfo(Element elem, Crypto crypto,
+            CallbackHandler cb) throws WSSecurityException {
+        SAMLAssertion assertion;
+        try {
+            assertion = new SAMLAssertion(elem);
+            return getSAMLKeyInfo(assertion, crypto, cb);
+        } catch (SAMLException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "invalidSAMLToken", new Object[]{"for Signature (cannot parse)"}, e);
+        }
+
+    }
+    
+    public static SAMLKeyInfo getSAMLKeyInfo(SAMLAssertion assertion, Crypto crypto,
+            CallbackHandler cb) throws WSSecurityException {
+        
+        //First ask the cb whether it can provide the secret
+        WSPasswordCallback pwcb = new WSPasswordCallback(assertion.getId(), WSPasswordCallback.CUSTOM_TOKEN);
+        if(cb != null) {
+            try {
+                cb.handle(new Callback[]{pwcb});
+            } catch (Exception e1) {
+                throw new WSSecurityException(WSSecurityException.FAILURE, "noKey",
+                        new Object[] { assertion.getId() }, e1);
+            }
+        }
+        
+        byte[] key = pwcb.getKey();
+        
+        if(key != null) {
+            return new SAMLKeyInfo(assertion, key);
+        } else {
+            Iterator statements = assertion.getStatements();
+            while (statements.hasNext()) {
+                SAMLStatement stmt = (SAMLStatement) statements.next();
+                if (stmt instanceof SAMLAttributeStatement) {
+                    SAMLAttributeStatement attrStmt = (SAMLAttributeStatement) stmt;
+                    SAMLSubject samlSubject = attrStmt.getSubject();
+                    Element kiElem = samlSubject.getKeyInfo();
+                    
+                    NodeList children = kiElem.getChildNodes();
+                    int len = children.getLength();
+                    
+                    for(int i = 0; i < len; i++) {
+                        Node child = children.item(i);
+                        if (child.getNodeType() != Node.ELEMENT_NODE) {
+                            continue;
+                        }
+                        QName el = new QName(child.getNamespaceURI(), child.getLocalName());
+                        if(el.equals(WSSecurityEngine.ENCRYPTED_KEY)) {
+                            
+                            EncryptedKeyProcessor proc = new EncryptedKeyProcessor();
+                            proc.handleEncryptedKey((Element)child, cb, crypto, null);
+                            
+                            return new SAMLKeyInfo(assertion, proc.getDecryptedBytes());
+                        } else if(el.equals(new QName(WSConstants.WST_NS, "BinarySecret"))) {
+                            Text txt = (Text)child.getFirstChild();
+                            return new SAMLKeyInfo(assertion, Base64.decode(txt.getData()));
+                        }
+                    }
+
+                } else if( stmt instanceof SAMLAuthenticationStatement) {
+                    SAMLAuthenticationStatement authStmt = (SAMLAuthenticationStatement)stmt;
+                    SAMLSubject samlSubj = authStmt.getSubject(); 
+                    if (samlSubj == null) {
+                        throw new WSSecurityException(WSSecurityException.FAILURE,
+                                "invalidSAMLToken", new Object[]{"for Signature (no Subject)"});
+                    }
+
+                    Element e = samlSubj.getKeyInfo();
+                    X509Certificate[] certs = null;
+                    try {
+                        KeyInfo ki = new KeyInfo(e, null);
+
+                        if (ki.containsX509Data()) {
+                            X509Data data = ki.itemX509Data(0);
+                            XMLX509Certificate certElem = null;
+                            if (data != null && data.containsCertificate()) {
+                                certElem = data.itemCertificate(0);
+                            }
+                            if (certElem != null) {
+                                X509Certificate cert = certElem.getX509Certificate();
+                                certs = new X509Certificate[1];
+                                certs[0] = cert;
+                                return new SAMLKeyInfo(assertion, certs);
+                            }
+                        }
+
+                    } catch (XMLSecurityException e3) {
+                        throw new WSSecurityException(WSSecurityException.FAILURE,
+                                "invalidSAMLsecurity",
+                                new Object[]{"cannot get certificate (key holder)"}, e3);
+                    }
+                    
+                } else {
+                    throw new WSSecurityException(WSSecurityException.FAILURE,
+                            "invalidSAMLsecurity",
+                            new Object[]{"cannot get certificate or key "});
+                }
+            }
+            
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "invalidSAMLsecurity",
+                    new Object[]{"cannot get certificate or key "});
+                        
+        }
+
+    }
+    
+    /**
+     * Extracts the certificate(s) from the SAML token reference.
+     * <p/>
+     *
+     * @param elem The element containing the SAML token.
+     * @return an array of X509 certificates
+     * @throws org.apache.ws.security.WSSecurityException
+     */
+    public static X509Certificate[] getCertificatesFromSAML(Element elem)
+            throws WSSecurityException {
+
+        /*
+         * Get some information about the SAML token content. This controls how
+         * to deal with the whole stuff. First get the Authentication statement
+         * (includes Subject), then get the _first_ confirmation method only.
+         */
+        SAMLAssertion assertion;
+        try {
+            assertion = new SAMLAssertion(elem);
+        } catch (SAMLException e) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "invalidSAMLToken", new Object[]{"for Signature (cannot parse)"}, e);
+        }
+        SAMLSubjectStatement samlSubjS = null;
+        Iterator it = assertion.getStatements();
+        while (it.hasNext()) {
+            SAMLObject so = (SAMLObject) it.next();
+            if (so instanceof SAMLSubjectStatement) {
+                samlSubjS = (SAMLSubjectStatement) so;
+                break;
+            }
+        }
+        SAMLSubject samlSubj = null;
+        if (samlSubjS != null) {
+            samlSubj = samlSubjS.getSubject();
+        }
+        if (samlSubj == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "invalidSAMLToken", new Object[]{"for Signature (no Subject)"});
+        }
+
+//        String confirmMethod = null;
+//        it = samlSubj.getConfirmationMethods();
+//        if (it.hasNext()) {
+//            confirmMethod = (String) it.next();
+//        }
+//        boolean senderVouches = false;
+//        if (SAMLSubject.CONF_SENDER_VOUCHES.equals(confirmMethod)) {
+//            senderVouches = true;
+//        }
+        Element e = samlSubj.getKeyInfo();
+        X509Certificate[] certs = null;
+        try {
+            KeyInfo ki = new KeyInfo(e, null);
+
+            if (ki.containsX509Data()) {
+                X509Data data = ki.itemX509Data(0);
+                XMLX509Certificate certElem = null;
+                if (data != null && data.containsCertificate()) {
+                    certElem = data.itemCertificate(0);
+                }
+                if (certElem != null) {
+                    X509Certificate cert = certElem.getX509Certificate();
+                    certs = new X509Certificate[1];
+                    certs[0] = cert;
+                }
+            }
+            // TODO: get alias name for cert, check against username set by caller
+        } catch (XMLSecurityException e3) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "invalidSAMLsecurity",
+                    new Object[]{"cannot get certificate (key holder)"}, e3);
+        }
+        return certs;
+    }
+
+    public static String getAssertionId(Element envelope, String elemName, String nmSpace) throws WSSecurityException {
+        String id;
+        // Make the AssertionID the wsu:Id and the signature reference the same
+        SAMLAssertion assertion;
+
+        Element assertionElement = (Element) WSSecurityUtil
+                .findElement(envelope, elemName, nmSpace);
+
+        try {
+            assertion = new SAMLAssertion(assertionElement);
+            id = assertion.getId();
+        } catch (Exception e1) {
+            log.error(e1);
+            throw new WSSecurityException(
+                    WSSecurityException.FAILED_SIGNATURE,
+                    "noXMLSig", null, e1);
+        }
+        return id;
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java b/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java
new file mode 100644
index 0000000..c9b7b67
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/saml/WSSecSignatureSAML.java
@@ -0,0 +1,602 @@
+package org.apache.ws.security.saml;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSDocInfoStore;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.EnvelopeIdResolver;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.transform.STRTransform;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.algorithms.SignatureAlgorithm;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.keys.content.x509.XMLX509Certificate;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.signature.XMLSignatureException;
+import org.apache.xml.security.transforms.TransformationException;
+import org.apache.xml.security.transforms.Transforms;
+import org.apache.xml.security.transforms.params.InclusiveNamespaces;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xml.security.utils.XMLUtils;
+import org.opensaml.SAMLAssertion;
+import org.opensaml.SAMLException;
+import org.opensaml.SAMLObject;
+import org.opensaml.SAMLSubject;
+import org.opensaml.SAMLSubjectStatement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.security.cert.X509Certificate;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Vector;
+
+public class WSSecSignatureSAML extends WSSecSignature {
+
+    private static Log log = LogFactory.getLog(WSSecSignatureSAML.class
+            .getName());
+
+    private boolean senderVouches = false;
+
+    private SecurityTokenReference secRefSaml = null;
+
+    private Element samlToken = null;
+
+    private Crypto userCrypto = null;
+
+    private Crypto issuerCrypto = null;
+
+    private String issuerKeyName = null;
+
+    private String issuerKeyPW = null;
+
+    /**
+     * Constructor.
+     */
+    public WSSecSignatureSAML() {
+    }
+
+    /**
+     * Builds a signed soap envelope with SAML token.
+     * 
+     * <p/>
+     * 
+     * The method first gets an appropriate security header. According to the
+     * defined parameters for certificate handling the signature elements are
+     * constructed and inserted into the <code>wsse:Signature</code>
+     * 
+     * @param doc
+     *            The unsigned SOAP envelope as <code>Document</code>
+     * @param uCrypto
+     *            The user's Crypto instance
+     * @param assertion
+     *            the complete SAML assertion
+     * @param iCrypto
+     *            An instance of the Crypto API to handle keystore SAML token
+     *            issuer and to generate certificates
+     * @param iKeyName
+     *            Private key to use in case of "sender-Vouches"
+     * @param iKeyPW
+     *            Password for issuer private key
+     * @param secHeader
+     *            The Security header
+     * @return A signed SOAP envelope as <code>Document</code>
+     * @throws org.apache.ws.security.WSSecurityException
+     */
+    public Document build(Document doc, Crypto uCrypto,
+            SAMLAssertion assertion, Crypto iCrypto, String iKeyName,
+            String iKeyPW, WSSecHeader secHeader) throws WSSecurityException {
+
+        prepare(doc, uCrypto, assertion, iCrypto, iKeyName, iKeyPW, secHeader);
+
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+        addReferencesToSign(parts, secHeader);
+
+        /*
+         * The order to prepend is: - signature Element - BinarySecurityToken
+         * (depends on mode) - SecurityTokenRefrence (depends on mode) - SAML
+         * token
+         */
+
+        prependToHeader(secHeader);
+
+        /*
+         * if we have a BST prepend it in front of the Signature according to
+         * strict layout rules.
+         */
+        if (bstToken != null) {
+            prependBSTElementToHeader(secHeader);
+        }
+
+        prependSAMLElementsToHeader(secHeader);
+
+        computeSignature();
+
+        return doc;
+    }
+
+    /**
+     * Initialize a WSSec SAML Signature.
+     * 
+     * The method sets up and initializes a WSSec SAML Signature structure after
+     * the relevant information was set. After setup of the references to
+     * elements to sign may be added. After all references are added they can be
+     * signed.
+     * 
+     * <p/>
+     * 
+     * This method does not add the Signature element to the security header.
+     * See <code>prependSignatureElementToHeader()</code> method.
+     * 
+     * @param doc
+     *            The SOAP envelope as <code>Document</code>
+     * @param uCrypto
+     *            The user's Crypto instance
+     * @param assertion
+     *            the complete SAML assertion
+     * @param iCrypto
+     *            An instance of the Crypto API to handle keystore SAML token
+     *            issuer and to generate certificates
+     * @param iKeyName
+     *            Private key to use in case of "sender-Vouches"
+     * @param iKeyPW
+     *            Password for issuer private key
+     * @param secHeader
+     *            The Security header
+     * @throws WSSecurityException
+     */
+    public void prepare(Document doc, Crypto uCrypto, SAMLAssertion assertion,
+            Crypto iCrypto, String iKeyName, String iKeyPW,
+            WSSecHeader secHeader) throws WSSecurityException {
+
+        doDebug = log.isDebugEnabled();
+        if (doDebug) {
+            log.debug("Beginning ST signing...");
+        }
+
+        userCrypto = uCrypto;
+        issuerCrypto = iCrypto;
+        document = doc;
+        issuerKeyName = iKeyName;
+        issuerKeyPW = iKeyPW;
+
+        /*
+         * Get some information about the SAML token content. This controls how
+         * to deal with the whole stuff. First get the Authentication statement
+         * (includes Subject), then get the _first_ confirmation method only
+         * thats if "senderVouches" is true.
+         */
+        SAMLSubjectStatement samlSubjS = null;
+        Iterator it = assertion.getStatements();
+        while (it.hasNext()) {
+            SAMLObject so = (SAMLObject) it.next();
+            if (so instanceof SAMLSubjectStatement) {
+                samlSubjS = (SAMLSubjectStatement) so;
+                break;
+            }
+        }
+        SAMLSubject samlSubj = null;
+        if (samlSubjS != null) {
+            samlSubj = samlSubjS.getSubject();
+        }
+        if (samlSubj == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "invalidSAMLToken", new Object[] { "for Signature" });
+        }
+
+        String confirmMethod = null;
+        it = samlSubj.getConfirmationMethods();
+        if (it.hasNext()) {
+            confirmMethod = (String) it.next();
+        }
+        if (SAMLSubject.CONF_SENDER_VOUCHES.equals(confirmMethod)) {
+            senderVouches = true;
+        }
+        /*
+         * Gather some info about the document to process and store it for
+         * retrieval
+         */
+        wsDocInfo = new WSDocInfo(doc.hashCode());
+
+        X509Certificate[] certs = null;
+
+        if (senderVouches) {
+            certs = issuerCrypto.getCertificates(issuerKeyName);
+            wsDocInfo.setCrypto(issuerCrypto);
+        }
+        /*
+         * in case of key holder: - get the user's certificate that _must_ be
+         * included in the SAML token. To ensure the cert integrity the SAML
+         * token must be signed (by the issuer). Just check if its signed, but
+         * don't verify this SAML token's signature here (maybe later).
+         */
+        else {
+            if (userCrypto == null || assertion.isSigned() == false) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "invalidSAMLsecurity",
+                        new Object[] { "for SAML Signature (Key Holder)" });
+            }
+            Element e = samlSubj.getKeyInfo();
+            try {
+                KeyInfo ki = new KeyInfo(e, null);
+
+                if (ki.containsX509Data()) {
+                    X509Data data = ki.itemX509Data(0);
+                    XMLX509Certificate certElem = null;
+                    if (data != null && data.containsCertificate()) {
+                        certElem = data.itemCertificate(0);
+                    }
+                    if (certElem != null) {
+                        X509Certificate cert = certElem.getX509Certificate();
+                        certs = new X509Certificate[1];
+                        certs[0] = cert;
+                    }
+                }
+                // TODO: get alias name for cert, check against username set by
+                // caller
+            } catch (XMLSecurityException e3) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "invalidSAMLsecurity",
+                        new Object[] { "cannot get certificate (key holder)" },
+                        e3);
+            }
+            wsDocInfo.setCrypto(userCrypto);
+        }
+        if (certs == null || certs.length <= 0) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILURE,
+                "noCertsFound",
+                new Object[] { "SAML signature" }
+            );
+        }
+        if (sigAlgo == null) {
+            String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm();
+            log.debug("automatic sig algo detection: " + pubKeyAlgo);
+            if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
+                sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+            } else if (pubKeyAlgo.equalsIgnoreCase("RSA")) {
+                sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
+            } else {
+                throw new WSSecurityException(
+                    WSSecurityException.FAILURE,
+                    "unknownSignatureAlgorithm",
+                    new Object[] {
+                        pubKeyAlgo
+                    }
+                );
+            }
+        }
+        sig = null;
+        if (canonAlgo.equals(WSConstants.C14N_EXCL_OMIT_COMMENTS)) {
+            Element canonElem = XMLUtils.createElementInSignatureSpace(doc,
+                    Constants._TAG_CANONICALIZATIONMETHOD);
+
+            canonElem.setAttributeNS(null, Constants._ATT_ALGORITHM, canonAlgo);
+
+            if (wssConfig.isWsiBSPCompliant()) {
+                Set prefixes = getInclusivePrefixes(secHeader
+                        .getSecurityHeader(), false);
+
+                InclusiveNamespaces inclusiveNamespaces = new InclusiveNamespaces(
+                        doc, prefixes);
+
+                canonElem.appendChild(inclusiveNamespaces.getElement());
+            }
+            try {
+                SignatureAlgorithm signatureAlgorithm = new SignatureAlgorithm(
+                        doc, sigAlgo);
+                sig = new XMLSignature(doc, null, signatureAlgorithm
+                        .getElement(), canonElem);
+            } catch (XMLSecurityException e) {
+                log.error("", e);
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e
+                );
+            }
+        } else {
+            try {
+                sig = new XMLSignature(doc, null, sigAlgo, canonAlgo);
+            } catch (XMLSecurityException e) {
+                log.error("", e);
+                throw new WSSecurityException(
+                    WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e
+                );
+            }
+        }
+
+        sig.addResourceResolver(EnvelopeIdResolver.getInstance());
+        String sigUri = "Signature-" + sig.hashCode();
+        sig.setId(sigUri);
+
+        keyInfo = sig.getKeyInfo();
+        keyInfoUri = "KeyId-" + keyInfo.hashCode();
+        keyInfo.setId(keyInfoUri);
+
+        secRef = new SecurityTokenReference(doc);
+        strUri = "STRId-" + secRef.hashCode();
+        secRef.setID(strUri);
+
+        certUri = "CertId-" + certs[0].hashCode();
+
+        /*
+         * If the sender vouches, then we must sign the SAML token _and_ at
+         * least one part of the message (usually the SOAP body). To do so we
+         * need to - put in a reference to the SAML token. Thus we create a STR
+         * and insert it into the wsse:Security header - set a reference of the
+         * created STR to the signature and use STR Transfrom during the
+         * signature
+         */
+        Transforms transforms = null;
+
+        try {
+            if (senderVouches) {
+                secRefSaml = new SecurityTokenReference(doc);
+                String strSamlUri = "STRSAMLId-" + secRefSaml.hashCode();
+                secRefSaml.setID(strSamlUri);
+
+                // Decouple Reference/KeyInfo setup - quick shot here
+                Reference ref = new Reference(doc);
+                ref.setURI("#" + assertion.getId());
+                ref.setValueType(WSConstants.WSS_SAML_NS
+                        + WSConstants.WSS_SAML_ASSERTION);
+                secRefSaml.setReference(ref);
+                // up to here
+
+                Element ctx = createSTRParameter(doc);
+                transforms = new Transforms(doc);
+                transforms.addTransform(STRTransform.implementedTransformURI,
+                        ctx);
+                sig.addDocument("#" + strSamlUri, transforms);
+            }
+        } catch (TransformationException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    "noXMLSig", null, e1);
+        } catch (XMLSignatureException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    "noXMLSig", null, e1);
+        }
+
+        switch (keyIdentifierType) {
+        case WSConstants.BST_DIRECT_REFERENCE:
+            Reference ref = new Reference(doc);
+            if (senderVouches) {
+                ref.setURI("#" + certUri);
+                bstToken = new X509Security(doc);
+                ((X509Security) bstToken).setX509Certificate(certs[0]);
+                bstToken.setID(certUri);
+                wsDocInfo.setBst(bstToken.getElement());
+                ref.setValueType(bstToken.getValueType());
+            } else {
+                ref.setURI("#" + assertion.getId());
+                ref.setValueType(WSConstants.WSS_SAML_NS
+                        + WSConstants.WSS_SAML_ASSERTION);
+            }
+            secRef.setReference(ref);
+            break;
+        //
+        // case WSConstants.ISSUER_SERIAL :
+        // XMLX509IssuerSerial data =
+        // new XMLX509IssuerSerial(doc, certs[0]);
+        // secRef.setX509IssuerSerial(data);
+        // break;
+        //
+        // case WSConstants.X509_KEY_IDENTIFIER :
+        // secRef.setKeyIdentifier(certs[0]);
+        // break;
+        //
+        // case WSConstants.SKI_KEY_IDENTIFIER :
+        // secRef.setKeyIdentifierSKI(certs[0], crypto);
+        // break;
+        //
+        default:
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unsupportedKeyId");
+        }
+
+        keyInfo.addUnknownElement(secRef.getElement());
+        
+        Element keyInfoElement = keyInfo.getElement();
+        keyInfoElement.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                + WSConstants.SIG_PREFIX, WSConstants.SIG_NS);
+
+        try {
+            samlToken = (Element) assertion.toDOM(doc);
+        } catch (SAMLException e2) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    "noSAMLdoc", null, e2);
+        }
+        wsDocInfo.setAssertion(samlToken);
+    }
+
+    /**
+     * Prepend the SAML elements to the elements already in the Security header.
+     * 
+     * The method can be called any time after <code>prepare()</code>. This
+     * allows to insert the SAML elements at any position in the Security
+     * header.
+     * 
+     * <p/>
+     * 
+     * This methods first prepends the SAML security reference if mode is
+     * <code>senderVouches</code>, then the SAML token itself,
+     * 
+     * @param secHeader
+     *            The security header that holds the BST element.
+     */
+    public void prependSAMLElementsToHeader(WSSecHeader secHeader) {
+        if (senderVouches) {
+            WSSecurityUtil.prependChildElement(document, secHeader
+                    .getSecurityHeader(), secRefSaml.getElement(), true);
+        }
+
+        WSSecurityUtil.prependChildElement(document, secHeader
+                .getSecurityHeader(), samlToken, true);
+    }
+
+    /**
+     * This method adds references to the Signature.
+     * 
+     * The added references are signed when calling
+     * <code>computeSignature()</code>. This method can be called several
+     * times to add references as required. <code>addReferencesToSign()</code>
+     * can be called anytime after <code>prepare</code>.
+     * 
+     * @param references
+     *            A vector containing <code>WSEncryptionPart</code> objects
+     *            that define the parts to sign.
+     * @param secHeader
+     *            Used to compute namespaces to be inserted by
+     *            InclusiveNamespaces to be WSI compliant.
+     * @throws WSSecurityException
+     */
+    public void addReferencesToSign(Vector references, WSSecHeader secHeader)
+            throws WSSecurityException {
+        Transforms transforms = null;
+
+        Element envelope = document.getDocumentElement();
+        for (int part = 0; part < parts.size(); part++) {
+            WSEncryptionPart encPart = (WSEncryptionPart) references.get(part);
+
+            String idToSign = encPart.getId();
+
+            String elemName = encPart.getName();
+            String nmSpace = encPart.getNamespace();
+
+            /*
+             * Set up the elements to sign. There are two resevered element
+             * names: "Token" and "STRTransform" "Token": Setup the Signature to
+             * either sign the information that points to the security token or
+             * the token itself. If its a direct reference sign the token,
+             * otherwise sign the KeyInfo Element. "STRTransform": Setup the
+             * ds:Reference to use STR Transform
+             * 
+             */
+            transforms = new Transforms(document);
+            try {
+                if (idToSign != null) {
+                    Element toSignById = WSSecurityUtil.findElementById(
+                            document.getDocumentElement(), idToSign,
+                            WSConstants.WSU_NS);
+                    if (toSignById == null) {
+                        toSignById = WSSecurityUtil.findElementById(document
+                                .getDocumentElement(), idToSign, null);
+                    }
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(document,
+                                        getInclusivePrefixes(toSignById))
+                                        .getElement());
+                    }
+                    sig.addDocument("#" + idToSign, transforms);
+                } else if (elemName.equals("Token")) {
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (keyIdentifierType == WSConstants.BST_DIRECT_REFERENCE) {
+                        if (wssConfig.isWsiBSPCompliant()) {
+                            transforms.item(0).getElement().appendChild(
+                                    new InclusiveNamespaces(document,
+                                            getInclusivePrefixes(secHeader
+                                                    .getSecurityHeader()))
+                                            .getElement());
+                        }
+                        sig.addDocument("#" + certUri, transforms);
+                    } else {
+                        if (wssConfig.isWsiBSPCompliant()) {
+                            transforms.item(0).getElement().appendChild(
+                                    new InclusiveNamespaces(document,
+                                            getInclusivePrefixes(keyInfo
+                                                    .getElement()))
+                                            .getElement());
+                        }
+                        sig.addDocument("#" + keyInfoUri, transforms);
+                    }
+                } else if (elemName.equals("STRTransform")) { // STRTransform
+                    Element ctx = createSTRParameter(document);
+                    transforms.addTransform(
+                            STRTransform.implementedTransformURI, ctx);
+                    sig.addDocument("#" + strUri, transforms);
+                } else {
+                    Element body = (Element) WSSecurityUtil.findElement(
+                            envelope, elemName, nmSpace);
+                    if (body == null) {
+                        throw new WSSecurityException(
+                                WSSecurityException.FAILURE, "noEncElement",
+                                new Object[] { nmSpace + ", " + elemName });
+                    }
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (wssConfig.isWsiBSPCompliant()) {
+                        transforms.item(0).getElement().appendChild(
+                                new InclusiveNamespaces(document,
+                                        getInclusivePrefixes(body))
+                                        .getElement());
+                    }
+                    sig.addDocument("#" + setWsuId(body), transforms);
+                }
+            } catch (TransformationException e1) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null,
+                        e1);
+            } catch (XMLSignatureException e1) {
+                throw new WSSecurityException(
+                        WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null,
+                        e1);
+            }
+        }
+    }
+
+    /**
+     * Compute the Signature over the references.
+     * 
+     * After references are set this method computes the Signature for them.
+     * This method can be called anytime after the references were set. See
+     * <code>addReferencesToSign()</code>.
+     * 
+     * @throws WSSecurityException
+     */
+    public void computeSignature() throws WSSecurityException {
+
+        WSDocInfoStore.store(wsDocInfo);
+
+        try {
+            if (senderVouches) {
+                sig
+                        .sign(issuerCrypto.getPrivateKey(issuerKeyName,
+                                issuerKeyPW));
+            } else {
+                sig.sign(userCrypto.getPrivateKey(user, password));
+            }
+            signatureValue = sig.getSignatureValue();
+        } catch (XMLSignatureException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } catch (Exception e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } finally {
+            WSDocInfoStore.delete(wsDocInfo);
+        }
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/saml/WSSignSAMLEnvelope.java b/trunk/src/org/apache/ws/security/saml/WSSignSAMLEnvelope.java
new file mode 100644
index 0000000..df7de3b
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/saml/WSSignSAMLEnvelope.java
@@ -0,0 +1,439 @@
+package org.apache.ws.security.saml;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSDocInfoStore;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.EnvelopeIdResolver;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSignEnvelope;
+import org.apache.ws.security.message.token.BinarySecurity;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.transform.STRTransform;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.keys.content.X509Data;
+import org.apache.xml.security.keys.content.x509.XMLX509Certificate;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.signature.XMLSignatureException;
+import org.apache.xml.security.transforms.TransformationException;
+import org.apache.xml.security.transforms.Transforms;
+import org.opensaml.SAMLAssertion;
+import org.opensaml.SAMLException;
+import org.opensaml.SAMLObject;
+import org.opensaml.SAMLSubject;
+import org.opensaml.SAMLSubjectStatement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.security.cert.X509Certificate;
+import java.util.Iterator;
+import java.util.Vector;
+
+public class WSSignSAMLEnvelope extends WSSignEnvelope {
+
+    private static Log log = LogFactory.getLog(WSSignSAMLEnvelope.class
+            .getName());
+
+    private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
+
+    /**
+     * Constructor.
+     * 
+     * @deprecated replaced by {@link WSSecSignatureSAML#WSSecSignatureSAML()}
+     */
+    public WSSignSAMLEnvelope() {
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param actor
+     *            The actor name of the <code>wsse:Security</code> header
+     * @param mu
+     *            Set <code>mustUnderstand</code> to true or false
+     * 
+     * @deprecated replaced by {@link WSSecSignatureSAML#WSSecSignatureSAML()} and
+     *             {@link WSSecHeader} for actor and mustunderstand
+     *             specification.
+     */
+    public WSSignSAMLEnvelope(String actor, boolean mu) {
+        super(actor, mu);
+    }
+
+    /**
+     * Builds a signed soap envelope with SAML token. <p/>The method first gets
+     * an appropriate security header. According to the defined parameters for
+     * certificate handling the signature elements are constructed and inserted
+     * into the <code>wsse:Signature</code>
+     * 
+     * @param doc
+     *            The unsigned SOAP envelope as <code>Document</code>
+     * @param assertion
+     *            the complete SAML assertion
+     * @param issuerCrypto
+     *            An instance of the Crypto API to handle keystore SAML token
+     *            issuer and to generate certificates
+     * @param issuerKeyName
+     *            Private key to use in case of "sender-Vouches"
+     * @param issuerKeyPW
+     *            Password for issuer private key
+     * @return A signed SOAP envelope as <code>Document</code>
+     * @throws org.apache.ws.security.WSSecurityException
+     * @deprecated replaced by
+     *             {@link WSSecSignatureSAML#build(Document, Crypto, SAMLAssertion, Crypto, String, String, WSSecHeader)}
+     */
+    public Document build(Document doc, Crypto userCrypto,
+            SAMLAssertion assertion, Crypto issuerCrypto, String issuerKeyName,
+            String issuerKeyPW) throws WSSecurityException {
+
+        doDebug = log.isDebugEnabled();
+
+        long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
+        if (tlog.isDebugEnabled()) {
+            t0 = System.currentTimeMillis();
+        }
+        if (doDebug) {
+            log.debug("Beginning ST signing...");
+        }
+        /*
+         * Get some information about the SAML token content. This controls how
+         * to deal with the whole stuff. First get the Authentication statement
+         * (includes Subject), then get the _first_ confirmation method only.
+         */
+        SAMLSubjectStatement samlSubjS = null;
+        Iterator it = assertion.getStatements();
+        while (it.hasNext()) {
+            SAMLObject so = (SAMLObject) it.next();
+            if (so instanceof SAMLSubjectStatement) {
+                samlSubjS = (SAMLSubjectStatement) so;
+                break;
+            }
+        }
+        SAMLSubject samlSubj = null;
+        if (samlSubjS != null) {
+            samlSubj = samlSubjS.getSubject();
+        }
+        if (samlSubj == null) {
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "invalidSAMLToken", new Object[] { "for Signature" });
+        }
+
+        String confirmMethod = null;
+        it = samlSubj.getConfirmationMethods();
+        if (it.hasNext()) {
+            confirmMethod = (String) it.next();
+        }
+        boolean senderVouches = false;
+        if (SAMLSubject.CONF_SENDER_VOUCHES.equals(confirmMethod)) {
+            senderVouches = true;
+        }
+        /*
+         * Gather some info about the document to process and store it for
+         * retrieval
+         */
+        WSDocInfo wsDocInfo = new WSDocInfo(doc.hashCode());
+
+        Element envelope = doc.getDocumentElement();
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+
+        Element securityHeader = insertSecurityHeader(doc);
+        X509Certificate[] certs = null;
+
+        if (senderVouches) {
+            certs = issuerCrypto.getCertificates(issuerKeyName);
+            wsDocInfo.setCrypto(issuerCrypto);
+        }
+        /*
+         * in case of key holder: - get the user's certificate that _must_ be
+         * included in the SAML token. To ensure the cert integrity the SAML
+         * token must be signed (by the issuer). Just check if its signed, but
+         * don't verify this SAML token's signature here (maybe later).
+         */
+        else {
+            if (userCrypto == null || assertion.isSigned() == false) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "invalidSAMLsecurity",
+                        new Object[] { "for SAML Signature (Key Holder)" });
+            }
+            Element e = samlSubj.getKeyInfo();
+            try {
+                KeyInfo ki = new KeyInfo(e, null);
+
+                if (ki.containsX509Data()) {
+                    X509Data data = ki.itemX509Data(0);
+                    XMLX509Certificate certElem = null;
+                    if (data != null && data.containsCertificate()) {
+                        certElem = data.itemCertificate(0);
+                    }
+                    if (certElem != null) {
+                        X509Certificate cert = certElem.getX509Certificate();
+                        certs = new X509Certificate[1];
+                        certs[0] = cert;
+                    }
+                }
+                // TODO: get alias name for cert, check against username set by
+                // caller
+            } catch (XMLSecurityException e3) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "invalidSAMLsecurity",
+                        new Object[] { "cannot get certificate (key holder)" },
+                        e3);
+            }
+            wsDocInfo.setCrypto(userCrypto);
+        }
+        // Set the id of the elements to be used as digest source
+        // String id = setBodyID(doc);
+        if (certs == null || certs.length <= 0) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILURE,
+                "noCertsFound",
+                new Object[] { "SAML signature" }
+            );
+        }
+        if (sigAlgo == null) {
+            String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm();
+            log.debug("automatic sig algo detection: " + pubKeyAlgo);
+            if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
+                sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+            } else if (pubKeyAlgo.equalsIgnoreCase("RSA")) {
+                sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
+            } else {
+                throw new WSSecurityException(
+                    WSSecurityException.FAILURE,
+                    "unknownSignatureAlgorithm",
+                    new Object[] {
+                        pubKeyAlgo
+                    }
+                );
+            }
+        }
+        XMLSignature sig = null;
+        try {
+            sig = new XMLSignature(doc, null, sigAlgo, canonAlgo);
+        } catch (XMLSecurityException e) {
+            throw new WSSecurityException(
+                WSSecurityException.FAILED_SIGNATURE, "noXMLSig", null, e
+            );
+        }
+
+        KeyInfo info = sig.getKeyInfo();
+        String keyInfoUri = "KeyId-" + info.hashCode();
+        info.setId(keyInfoUri);
+
+        SecurityTokenReference secRef = new SecurityTokenReference(doc);
+        String strUri = "STRId-" + secRef.hashCode();
+        secRef.setID(strUri);
+
+        String certUri = "CertId-" + certs[0].hashCode();
+
+        if (tlog.isDebugEnabled()) {
+            t1 = System.currentTimeMillis();
+        }
+
+        if (parts == null) {
+            parts = new Vector();
+            WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                    .getBodyQName().getLocalPart(), soapConstants
+                    .getEnvelopeURI(), "Content");
+            parts.add(encP);
+        }
+
+        /*
+         * If the sender vouches, then we must sign the SAML token _and_ at
+         * least one part of the message (usually the SOAP body). To do so we
+         * need to - put in a reference to the SAML token. Thus we create a STR
+         * and insert it into the wsse:Security header - set a reference of the
+         * created STR to the signature and use STR Transfrom during the
+         * signature
+         */
+        Transforms transforms = null;
+        SecurityTokenReference secRefSaml = null;
+
+        try {
+            if (senderVouches) {
+                secRefSaml = new SecurityTokenReference(doc);
+                String strSamlUri = "STRSAMLId-" + secRefSaml.hashCode();
+                secRefSaml.setID(strSamlUri);
+                // Decouple Refernce/KeyInfo setup - quick shot here
+                Reference ref = new Reference(doc);
+                ref.setURI("#" + assertion.getId());
+                ref.setValueType(WSConstants.WSS_SAML_NS
+                        + WSConstants.WSS_SAML_ASSERTION);
+                secRefSaml.setReference(ref);
+                // up to here
+                Element ctx = createSTRParameter(doc);
+                transforms = new Transforms(doc);
+                transforms.addTransform(STRTransform.implementedTransformURI,
+                        ctx);
+                sig.addDocument("#" + strSamlUri, transforms);
+            }
+            for (int part = 0; part < parts.size(); part++) {
+                WSEncryptionPart encPart = (WSEncryptionPart) parts.get(part);
+                String elemName = encPart.getName();
+                String nmSpace = encPart.getNamespace();
+
+                /*
+                 * Set up the elements to sign. There are two resevered element
+                 * names: "Token" and "STRTransform" "Token": Setup the
+                 * Signature to either sign the information that points to the
+                 * security token or the token itself. If its a direct reference
+                 * sign the token, otherwise sign the KeyInfo Element.
+                 * "STRTransform": Setup the ds:Reference to use STR Transform
+                 * 
+                 */
+                if (elemName.equals("Token")) {
+                    transforms = new Transforms(doc);
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    if (keyIdentifierType == WSConstants.BST_DIRECT_REFERENCE) {
+                        sig.addDocument("#" + certUri, transforms);
+                    } else {
+                        sig.addDocument("#" + keyInfoUri, transforms);
+                    }
+                } else if (elemName.equals("STRTransform")) { // STRTransform
+                    Element ctx = createSTRParameter(doc);
+                    transforms = new Transforms(doc);
+                    transforms.addTransform(
+                            STRTransform.implementedTransformURI, ctx);
+                    sig.addDocument("#" + strUri, transforms);
+                } else {
+                    Element body = (Element) WSSecurityUtil.findElement(
+                            envelope, elemName, nmSpace);
+                    if (body == null) {
+                        throw new WSSecurityException(
+                                WSSecurityException.FAILURE, "noEncElement",
+                                new Object[] { nmSpace + ", " + elemName });
+                    }
+                    transforms = new Transforms(doc);
+                    transforms
+                            .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+                    sig.addDocument("#" + setWsuId(body), transforms);
+                }
+            }
+        } catch (TransformationException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    "noXMLSig", null, e1);
+        } catch (XMLSignatureException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    "noXMLSig", null, e1);
+        }
+
+        sig.addResourceResolver(EnvelopeIdResolver.getInstance());
+
+        /*
+         * The order to prepend is: - signature - BinarySecurityToken (depends
+         * on mode) - SecurityTokenRefrence (depends on mode) - SAML token
+         */
+
+        WSSecurityUtil.prependChildElement(doc, securityHeader, sig
+                .getElement(), false);
+
+        if (tlog.isDebugEnabled()) {
+            t2 = System.currentTimeMillis();
+        }
+        switch (keyIdentifierType) {
+        case WSConstants.BST_DIRECT_REFERENCE:
+            Reference ref = new Reference(doc);
+            if (senderVouches) {
+                ref.setURI("#" + certUri);
+                BinarySecurity bstToken = null;
+                bstToken = new X509Security(doc);
+                ((X509Security) bstToken).setX509Certificate(certs[0]);
+                bstToken.setID(certUri);
+                WSSecurityUtil.prependChildElement(doc, securityHeader,
+                        bstToken.getElement(), false);
+                wsDocInfo.setBst(bstToken.getElement());
+                ref.setValueType(bstToken.getValueType());
+            } else {
+                ref.setURI("#" + assertion.getId());
+                ref.setValueType(WSConstants.WSS_SAML_NS
+                        + WSConstants.WSS_SAML_ASSERTION);
+            }
+            secRef.setReference(ref);
+            break;
+        //
+        // case WSConstants.ISSUER_SERIAL :
+        // XMLX509IssuerSerial data =
+        // new XMLX509IssuerSerial(doc, certs[0]);
+        // secRef.setX509IssuerSerial(data);
+        // break;
+        //
+        // case WSConstants.X509_KEY_IDENTIFIER :
+        // secRef.setKeyIdentifier(certs[0]);
+        // break;
+        //
+        // case WSConstants.SKI_KEY_IDENTIFIER :
+        // secRef.setKeyIdentifierSKI(certs[0], crypto);
+        // break;
+        //
+        default:
+            throw new WSSecurityException(WSSecurityException.FAILURE,
+                    "unsupportedKeyId");
+        }
+
+        if (tlog.isDebugEnabled()) {
+            t3 = System.currentTimeMillis();
+        }
+        info.addUnknownElement(secRef.getElement());
+        
+        Element keyInfoElement = info.getElement();
+        keyInfoElement.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:"
+                + WSConstants.SIG_PREFIX, WSConstants.SIG_NS);
+
+        Element samlToken = null;
+        try {
+            samlToken = (Element) assertion.toDOM(doc);
+        } catch (SAMLException e2) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    "noSAMLdoc", null, e2);
+        }
+        if (senderVouches) {
+            WSSecurityUtil.prependChildElement(doc, securityHeader, secRefSaml
+                    .getElement(), true);
+        }
+
+        wsDocInfo.setAssertion(samlToken);
+        WSSecurityUtil
+                .prependChildElement(doc, securityHeader, samlToken, true);
+
+        WSDocInfoStore.store(wsDocInfo);
+        try {
+            if (senderVouches) {
+                sig
+                        .sign(issuerCrypto.getPrivateKey(issuerKeyName,
+                                issuerKeyPW));
+            } else {
+                sig.sign(userCrypto.getPrivateKey(user, password));
+            }
+            signatureValue = sig.getSignatureValue();
+        } catch (XMLSignatureException e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } catch (Exception e1) {
+            throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+                    null, null, e1);
+        } finally {
+            WSDocInfoStore.delete(wsDocInfo);
+        }
+        if (tlog.isDebugEnabled()) {
+            t4 = System.currentTimeMillis();
+            tlog.debug("SignEnvelope: cre-Sig= " + (t1 - t0)
+                    + " set transform= " + (t2 - t1) + " sec-ref= " + (t3 - t2)
+                    + " signature= " + (t4 - t3));
+        }
+        if (doDebug) {
+            log.debug("Signing complete.");
+        }
+        return (doc);
+
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/saml/saml.properties b/trunk/src/org/apache/ws/security/saml/saml.properties
new file mode 100644
index 0000000..f8492e9
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/saml/saml.properties
@@ -0,0 +1,10 @@
+org.apache.ws.security.saml.issuerClass=org.apache.ws.security.saml.WSSSAMLIssuerImpl
+org.apache.ws.security.saml.issuerCryptoProp.file=crypto.properties
+org.apache.ws.security.saml.issuer=www.example.com
+org.apache.ws.security.saml.subjectNameId.name=uid=joe,ou=people,ou=saml-demo,o=example.com
+org.apache.ws.security.saml.subjectNameId.qualifier=www.example.com
+org.apache.ws.security.saml.authenticationMethod=password
+org.apache.ws.security.saml.confirmationMethod=senderVouches
+#org.apache.ws.security.saml.confirmationMethod=keyHolder
+#org.apache.ws.security.saml
+#org.apache.ws.security.saml
diff --git a/trunk/src/org/apache/ws/security/transform/STRTransform.java b/trunk/src/org/apache/ws/security/transform/STRTransform.java
new file mode 100644
index 0000000..c7e70ee
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/transform/STRTransform.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.transform;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSDocInfoStore;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.X509Security;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.c14n.CanonicalizationException;
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.apache.xml.security.c14n.InvalidCanonicalizerException;
+import org.apache.xml.security.signature.XMLSignatureInput;
+import org.apache.xml.security.transforms.TransformSpi;
+import org.apache.ws.security.util.Base64;
+import org.apache.xml.security.utils.XMLUtils;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+
+/**
+ * Class STRTransform
+ * 
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com)
+ * @version 1.0
+ */
+public class STRTransform extends TransformSpi {
+
+    /**
+     * Field implementedTransformURI
+     */
+    public static final String implementedTransformURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform";
+
+    private static Log log = LogFactory.getLog(STRTransform.class.getName());
+
+    private static boolean doDebug = false;
+
+    private static String XMLNS = "xmlns=";
+
+    private WSDocInfo wsDocInfo = null;
+
+    public boolean wantsOctetStream() {
+        return false;
+    }
+
+    public boolean wantsNodeSet() {
+        return true;
+    }
+
+    public boolean returnsOctetStream() {
+        return true;
+    }
+
+    public boolean returnsNodeSet() {
+        return false;
+    }
+
+    /**
+     * Method engineGetURI
+     */
+    protected String engineGetURI() {
+        return STRTransform.implementedTransformURI;
+    }
+
+    /**
+     * Method enginePerformTransform
+     * 
+     * @param input
+     * @throws CanonicalizationException
+     * @throws InvalidCanonicalizerException
+     */
+    protected XMLSignatureInput enginePerformTransform(XMLSignatureInput input)
+            throws IOException, CanonicalizationException,
+            InvalidCanonicalizerException {
+
+        doDebug = log.isDebugEnabled();
+
+        if (doDebug) {
+            log.debug("Beginning STRTransform..." + input.toString());
+        }
+
+        try {
+
+            /*
+             * Get the main document, that is the complete SOAP request document
+             */
+            Document thisDoc = this._transformObject.getDocument();
+            int docHash = thisDoc.hashCode();
+            if (doDebug) {
+                log.debug("doc: " + thisDoc.toString() + ", " + docHash);
+            }
+
+            /*
+             * Here we get some information about the document that is being
+             * processed, in particular the crypto implementation, and already
+             * detected BST that may be used later during dereferencing.
+             */
+            wsDocInfo = WSDocInfoStore.lookup(docHash);
+            if (wsDocInfo == null) {
+                throw (new CanonicalizationException("no WSDocInfo found"));
+            }
+
+            /*
+             * According to the OASIS WS Specification "Web Services Security:
+             * SOAP Message Security 1.0" Monday, 19 January 2004, chapter 8.3
+             * describes that the input node set must be processed by the c14n
+             * that is specified in the argument element of the STRTransform
+             * element.
+             * 
+             * First step: Get the required c14n argument and get the specified
+             * Canonicalizer
+             */
+
+            String canonAlgo = null;
+            if (this._transformObject.length(WSConstants.WSSE_NS,
+                    "TransformationParameters") == 1) {
+                Element tmpE = XMLUtils.selectNode(this._transformObject
+                        .getElement().getFirstChild(), WSConstants.WSSE_NS,
+                        "TransformationParameters", 0);
+                Element canonElem = (Element) WSSecurityUtil.getDirectChild(
+                        tmpE, "CanonicalizationMethod", WSConstants.SIG_NS);
+                canonAlgo = canonElem.getAttribute("Algorithm");
+                if (doDebug) {
+                    log.debug("CanonAlgo: " + canonAlgo);
+                }
+            }
+            Canonicalizer canon = Canonicalizer.getInstance(canonAlgo);
+
+            ByteArrayOutputStream bos = null;
+            byte[] buf = null;
+            if (doDebug) {
+                buf = input.getBytes();
+                bos = new ByteArrayOutputStream(buf.length);
+                bos.write(buf, 0, buf.length);
+                log.debug("canon bos: " + bos.toString());
+            }
+
+            /*
+             * Get the input (node) to transform. Currently we support only an
+             * Element as input format. If other formats are required we must
+             * get it as bytes and probably reparse it into a DOM tree (How to
+             * work with nodesets? how to select the right node from a nodeset?)
+             */
+            Element str = null;
+            if (input.isElement()) {
+                str = (Element) input.getSubNode();
+            } else {
+                throw (new CanonicalizationException(
+                        "Wrong input format - only element input supported"));
+            }
+
+            if (doDebug) {
+                log.debug("STR: " + str.toString());
+            }
+            /*
+             * The element to transform MUST be a SecurityTokenReference
+             * element.
+             */
+            SecurityTokenReference secRef = new SecurityTokenReference(str);
+            /*
+             * Third and forth step are performed by derefenceSTR()
+             */
+            Element dereferencedToken = dereferenceSTR(thisDoc, secRef);
+            /*
+             * C14n with specified algorithm. According to WSS Specification.
+             */
+            buf = canon.canonicalizeSubtree(dereferencedToken, "#default");
+            if (doDebug) {
+                bos = new ByteArrayOutputStream(buf.length);
+                bos.write(buf, 0, buf.length);
+                log.debug("after c14n: " + bos.toString());
+            }
+
+            /*
+             * Alert: Hacks ahead According to WSS spec an Apex node must
+             * contain a default namespace. If none is availabe in the first
+             * node of the c14n output (this is the apex element) then we do
+             * some editing to insert an empty default namespace
+             * 
+             * TODO: Rework theses hacks after c14n was updated and can be
+             * instructed to insert empty default namespace if required
+             */
+            // If the problem with c14n method is solved then just do:
+            // return new XMLSignatureInput(buf);
+            
+            // start of HACK
+            StringBuffer bf = new StringBuffer(new String(buf));
+            String bf1 = bf.toString();
+
+            /*
+             * Find start and end of first element <....>, this is the Apex node
+             */
+            int gt = bf1.indexOf(">");
+            /*
+             * Lookup the default namespace
+             */
+            int idx = bf1.indexOf(XMLNS);
+            /*
+             * If none found or if it is outside of this (Apex) element look for
+             * first blank in, insert default namespace there (this is the
+             * correct place according to c14n specification)
+             */
+            if (idx < 0 || idx > gt) {
+                idx = bf1.indexOf(" ");
+                bf.insert(idx + 1, "xmlns=\"\" ");
+                bf1 = bf.toString();
+            }
+            if (doDebug) {
+                log.debug("last result: ");
+                log.debug(bf1);
+            }
+            return new XMLSignatureInput(bf1.getBytes());
+        }
+        // End of HACK
+        catch (WSSecurityException ex) {
+            throw (new CanonicalizationException("WS Security Exception", ex));
+
+        }
+    }
+
+    private Element dereferenceSTR(Document doc, SecurityTokenReference secRef)
+            throws  WSSecurityException {
+
+        /*
+         * Third step: locate the security token referenced by the STR element.
+         * Either the Token is contained in the document as a
+         * BinarySecurityToken or stored in some key storage.
+         * 
+         * Forth step: after security token was located, prepare it. If its
+         * reference via a direct reference, i.e. a relative URI that references
+         * the BST directly in the message then just return that element.
+         * Otherwise wrap the located token in a newly created BST element as
+         * described in WSS Specification.
+         * 
+         */
+        Element tokElement = null;
+
+        /*
+         * First case: direct reference, according to chap 7.2 of OASIS WS
+         * specification (main document). Only in this case return a true
+         * reference to the BST. Copying is done by the caller.
+         */
+        if (secRef.containsReference()) {
+            if (doDebug) {
+                log.debug("STR: Reference");
+            }
+            tokElement = secRef.getTokenElement(doc, wsDocInfo, null);
+        }
+        /*
+         * second case: IssuerSerial, lookup in keystore, wrap in BST according
+         * to specification
+         */
+        else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
+            if (doDebug) {
+                log.debug("STR: IssuerSerial");
+            }
+            X509Certificate cert = null;
+            X509Certificate[] certs = secRef.getX509IssuerSerial(wsDocInfo
+                    .getCrypto());
+            if (certs == null || certs.length == 0 || certs[0] == null) {
+                throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
+            }
+            cert = certs[0];
+            tokElement = createBSTX509(doc, cert, secRef.getElement());
+        }
+        /*
+         * third case: KeyIdentifier, must be SKI, lookup in keystore, wrap in
+         * BST according to specification. No other KeyIdentifier type handled
+         * here - just SKI
+         */
+        else if (secRef.containsKeyIdentifier()) {
+            if (doDebug) {
+                log.debug("STR: KeyIdentifier");
+            }
+            X509Certificate cert = null;
+            X509Certificate[] certs = secRef.getKeyIdentifier(wsDocInfo
+                    .getCrypto());
+            if (certs == null || certs.length == 0 || certs[0] == null) {
+                throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
+            }
+            cert = certs[0];
+            tokElement = createBSTX509(doc, cert, secRef.getElement());
+        }
+        return (Element) tokElement;
+    }
+
+    private Element createBSTX509(Document doc, X509Certificate cert,
+            Element secRefE) throws WSSecurityException {
+
+        byte data[];
+        try {
+            data = cert.getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new WSSecurityException(
+                WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError", null, e
+            );
+        }
+        String prefix = WSSecurityUtil
+                .getPrefixNS(WSConstants.WSSE_NS, secRefE);
+        Element elem = doc.createElementNS(WSConstants.WSSE_NS, prefix
+                + ":BinarySecurityToken");
+        WSSecurityUtil.setNamespace(elem, WSConstants.WSSE_NS, prefix);
+        // elem.setAttributeNS(WSConstants.XMLNS_NS, "xmlns", "");
+        if (cert.getVersion() == 1) {
+            elem.setAttributeNS(null, "ValueType", X509Security.X509_V1_TYPE);
+        } else {
+            elem.setAttributeNS(null, "ValueType", X509Security.X509_V3_TYPE);
+        }
+        Text certText = doc.createTextNode(Base64.encode(data)); // no line
+                                                                    // wrap
+        elem.appendChild(certText);
+        return elem;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/util/Base64.java b/trunk/src/org/apache/ws/security/util/Base64.java
new file mode 100644
index 0000000..9a668cb
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/Base64.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright  1999-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.util;
+
+import org.apache.ws.security.WSSecurityException;
+
+public class Base64 {
+    /**
+     * Implementation of MIME's Base64 encoding and decoding conversions.
+     * Optimized code. (raw version taken from oreilly.jonathan.util,
+     * and currently org.apache.xerces.ds.util.Base64)
+     *
+     * @author Raul Benito(Of the xerces copy, and little adaptations).
+     * @author Anli Shundi
+     * @author Christian Geuer-Pollmann
+     * @see <A HREF="ftp://ftp.isi.edu/in-notes/rfc2045.txt">RFC 2045</A>
+     * @see org.apache.xml.security.transforms.implementations.TransformBase64Decode
+     */
+
+    /**
+     * {@link org.apache.commons.logging} logging facility
+     */
+    static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
+            .getLog(Base64.class.getName());
+
+    /**
+     * Field BASE64DEFAULTLENGTH
+     */
+    public static final int BASE64DEFAULTLENGTH = 76;
+
+    /**
+     * Field _base64length
+     */
+    static int _base64length = Base64.BASE64DEFAULTLENGTH;
+
+    static private final int BASELENGTH = 255;
+
+    static private final int LOOKUPLENGTH = 64;
+
+    static private final int TWENTYFOURBITGROUP = 24;
+
+    static private final int EIGHTBIT = 8;
+
+    static private final int SIXTEENBIT = 16;
+
+    static private final int FOURBYTE = 4;
+
+    static private final int SIGN = -128;
+
+    static private final char PAD = '=';
+
+    static private final boolean IS_DEBUG = log.isDebugEnabled();
+
+    static final private byte[] base64Alphabet = new byte[BASELENGTH];
+
+    static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
+
+    static {
+
+        for (int i = 0; i < BASELENGTH; i++) {
+            base64Alphabet[i] = -1;
+        }
+        for (int i = 'Z'; i >= 'A'; i--) {
+            base64Alphabet[i] = (byte) (i - 'A');
+        }
+        for (int i = 'z'; i >= 'a'; i--) {
+            base64Alphabet[i] = (byte) (i - 'a' + 26);
+        }
+
+        for (int i = '9'; i >= '0'; i--) {
+            base64Alphabet[i] = (byte) (i - '0' + 52);
+        }
+
+        base64Alphabet['+'] = 62;
+        base64Alphabet['/'] = 63;
+
+        for (int i = 0; i <= 25; i++)
+            lookUpBase64Alphabet[i] = (char) ('A' + i);
+
+        for (int i = 26, j = 0; i <= 51; i++, j++)
+            lookUpBase64Alphabet[i] = (char) ('a' + j);
+
+        for (int i = 52, j = 0; i <= 61; i++, j++)
+            lookUpBase64Alphabet[i] = (char) ('0' + j);
+        lookUpBase64Alphabet[62] = '+';
+        lookUpBase64Alphabet[63] = '/';
+
+    }
+
+    private Base64() {
+        // we don't allow instantiation
+    }
+
+    /**
+     * Encode a byte array and fold lines at the standard 76th character.
+     *
+     * @param binaryData <code>byte[]<code> to be base64 encoded
+     * @return the <code>String<code> with encoded data
+     */
+    public static String encode(byte[] binaryData) {
+        return encode(binaryData, BASE64DEFAULTLENGTH, false);
+    }
+
+    protected static boolean isWhiteSpace(byte octect) {
+        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
+    }
+
+    protected static boolean isPad(byte octect) {
+        return (octect == PAD);
+    }
+
+    /**
+     * Encode a byte array in Base64 format and return an optionally
+     * wrapped line.
+     *
+     * @param binaryData <code>byte[]</code> data to be encoded
+     * @param length     <code>int<code> length of wrapped lines; No wrapping if less than 4.
+     * @return a <code>String</code> with encoded data
+     */
+    public static String encode(byte[] binaryData, int length, boolean wrap) {
+
+        if (length < 4) {
+            length = Integer.MAX_VALUE;
+        }
+
+        if (binaryData == null)
+            return null;
+
+        int lengthDataBits = binaryData.length * EIGHTBIT;
+        if (lengthDataBits == 0) {
+            return "";
+        }
+
+        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
+        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
+        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
+                : numberTriplets;
+        int quartesPerLine = length / 4;
+        int numberLines = (numberQuartet - 1) / quartesPerLine;
+        char encodedData[];
+
+        encodedData = new char[(numberQuartet * 4) + (wrap ? numberLines : 0)];
+
+        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+
+        int encodedIndex = 0;
+        int dataIndex = 0;
+        int tripletsDone = 0;
+        if (IS_DEBUG) {
+            log.debug("number of triplets = " + numberTriplets);
+        }
+
+        for (int line = 0; line < numberLines; line++) {
+            for (int quartet = 0; quartet < quartesPerLine; quartet++) {
+                b1 = binaryData[dataIndex++];
+                b2 = binaryData[dataIndex++];
+                b3 = binaryData[dataIndex++];
+
+                if (IS_DEBUG) {
+                    log.debug("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
+                }
+
+                l = (byte) (b2 & 0x0f);
+                k = (byte) (b1 & 0x03);
+
+                byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
+                        : (byte) ((b1) >> 2 ^ 0xc0);
+
+                byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
+                        : (byte) ((b2) >> 4 ^ 0xf0);
+                byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
+                        : (byte) ((b3) >> 6 ^ 0xfc);
+
+                if (IS_DEBUG) {
+                    log.debug("val2 = " + val2);
+                    log.debug("k4   = " + (k << 4));
+                    log.debug("vak  = " + (val2 | (k << 4)));
+                }
+
+                encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+                encodedData[encodedIndex++] = lookUpBase64Alphabet[val2
+                        | (k << 4)];
+                encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2)
+                        | val3];
+                encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
+
+                tripletsDone++;
+            }
+            if (wrap) {
+                encodedData[encodedIndex++] = 0xa;
+            }
+        }
+
+        for (; tripletsDone < numberTriplets; tripletsDone++) {
+            b1 = binaryData[dataIndex++];
+            b2 = binaryData[dataIndex++];
+            b3 = binaryData[dataIndex++];
+
+            if (IS_DEBUG) {
+                log.debug("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
+            }
+
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
+                    : (byte) ((b1) >> 2 ^ 0xc0);
+
+            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
+                    : (byte) ((b2) >> 4 ^ 0xf0);
+            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
+                    : (byte) ((b3) >> 6 ^ 0xfc);
+
+            if (IS_DEBUG) {
+                log.debug("val2 = " + val2);
+                log.debug("k4   = " + (k << 4));
+                log.debug("vak  = " + (val2 | (k << 4)));
+            }
+
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
+        }
+
+        // form integral number of 6-bit groups
+        if (fewerThan24bits == EIGHTBIT) {
+            b1 = binaryData[dataIndex];
+            k = (byte) (b1 & 0x03);
+            if (IS_DEBUG) {
+                log.debug("b1=" + b1);
+                log.debug("b1<<2 = " + (b1 >> 2));
+            }
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
+                    : (byte) ((b1) >> 2 ^ 0xc0);
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
+            encodedData[encodedIndex++] = PAD;
+            encodedData[encodedIndex++] = PAD;
+        } else if (fewerThan24bits == SIXTEENBIT) {
+            b1 = binaryData[dataIndex];
+            b2 = binaryData[dataIndex + 1];
+            l = (byte) (b2 & 0x0f);
+            k = (byte) (b1 & 0x03);
+
+            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
+                    : (byte) ((b1) >> 2 ^ 0xc0);
+            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
+                    : (byte) ((b2) >> 4 ^ 0xf0);
+
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
+            encodedData[encodedIndex++] = PAD;
+        }
+        return new String(encodedData);
+    }
+
+    /**
+     * Decodes Base64 data into octects
+     *
+     * @param encoded String containing Base64 data
+     * @return Array containing decoded data.
+     */
+    public static byte[] decode(String encoded) throws WSSecurityException {
+        byte[] base64Data = encoded.getBytes();
+        // remove white spaces
+        int len = removeWhiteSpace(base64Data);
+
+        if (len % FOURBYTE != 0) {
+            throw new WSSecurityException("decoding.divisible.four");
+            //should be divisible by four
+        }
+
+        int numberQuadruple = (len / FOURBYTE);
+
+        if (numberQuadruple == 0)
+            return new byte[0];
+
+        byte decodedData[] = null;
+        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
+
+        int i = 0;
+        int encodedIndex = 0;
+        int dataIndex = 0;
+
+        //decodedData      = new byte[ (numberQuadruple)*3];
+        dataIndex = (numberQuadruple - 1) * 4;
+        encodedIndex = (numberQuadruple - 1) * 3;
+        //first last bits.
+        b1 = base64Alphabet[base64Data[dataIndex++]];
+        b2 = base64Alphabet[base64Data[dataIndex++]];
+        if ((b1 == -1) || (b2 == -1)) {
+            throw new WSSecurityException("decoding.general");//if found "no data" just return null
+        }
+
+        byte d3, d4;
+        b3 = base64Alphabet[d3 = base64Data[dataIndex++]];
+        b4 = base64Alphabet[d4 = base64Data[dataIndex++]];
+        if ((b3 == -1) || (b4 == -1)) {
+            //Check if they are PAD characters
+            if (isPad(d3) && isPad(d4)) { //Two PAD e.g. 3c[Pad][Pad]
+                if ((b2 & 0xf) != 0)//last 4 bits should be zero
+                    throw new WSSecurityException("decoding.general");
+                decodedData = new byte[encodedIndex + 1];
+                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+            } else if (!isPad(d3) && isPad(d4)) { //One PAD  e.g. 3cQ[Pad]
+                if ((b3 & 0x3) != 0)//last 2 bits should be zero
+                    throw new WSSecurityException("decoding.general");
+                decodedData = new byte[encodedIndex + 2];
+                decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+                decodedData[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            } else {
+                throw new WSSecurityException("decoding.general");//an error  like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data
+            }
+        } else {
+            //No PAD e.g 3cQl
+            decodedData = new byte[encodedIndex + 3];
+            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+        }
+        encodedIndex = 0;
+        dataIndex = 0;
+        //the begin
+        for (i = numberQuadruple - 1; i > 0; i--) {
+            b1 = base64Alphabet[base64Data[dataIndex++]];
+            b2 = base64Alphabet[base64Data[dataIndex++]];
+            b3 = base64Alphabet[base64Data[dataIndex++]];
+            b4 = base64Alphabet[base64Data[dataIndex++]];
+
+            if ((b1 == -1) || (b2 == -1) || (b3 == -1) || (b4 == -1)) {
+                throw new WSSecurityException("decoding.general");//if found "no data" just return null
+            }
+
+            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+        }
+        return decodedData;
+    }
+
+    /**
+     * remove WhiteSpace from MIME containing encoded Base64 data.
+     *
+     * @param data the byte array of base64 data (with WS)
+     * @return the new length
+     */
+    protected static int removeWhiteSpace(byte[] data) {
+        if (data == null)
+            return 0;
+
+        // count characters that's not whitespace
+        int newSize = 0;
+        int len = data.length;
+        for (int i = 0; i < len; i++) {
+            byte dataS = data[i];
+            if (!isWhiteSpace(dataS))
+                data[newSize++] = dataS;
+        }
+        return newSize;
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        // TODO Auto-generated method stub
+
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/util/DOM2Writer.java b/trunk/src/org/apache/ws/security/util/DOM2Writer.java
new file mode 100644
index 0000000..6abb766
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/DOM2Writer.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.util;
+
+import org.apache.ws.security.WSConstants;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+
+/**
+ * This class is a utility to serialize a DOM node as XML. This class
+ * uses the <code>DOM Level 2</code> APIs.
+ * The main difference between this class and DOMWriter is that this class
+ * generates and prints out namespace declarations.
+ *
+ * @author Matthew J. Duftler (duftler@us.ibm.com)
+ * @author Joseph Kesselman
+ */
+public class DOM2Writer {
+    public static final char NL = '\n';
+    public static final String LS = System.getProperty("line.separator",
+            (new Character(NL)).toString());
+
+    /**
+     * Return a string containing this node serialized as XML.
+     */
+    public static String nodeToString(Node node) {
+        StringWriter sw = new StringWriter();
+        serializeAsXML(node, sw, true);
+        return sw.toString();
+    }
+
+    /**
+     * Return a string containing this node serialized as XML.
+     */
+    public static String nodeToString(Node node, boolean omitXMLDecl) {
+        StringWriter sw = new StringWriter();
+        serializeAsXML(node, sw, omitXMLDecl);
+        return sw.toString();
+    }
+
+    /**
+     * Serialize this node into the writer as XML.
+     */
+    public static void serializeAsXML(Node node, Writer writer,
+                                      boolean omitXMLDecl) {
+        serializeAsXML(node, writer, omitXMLDecl, false);
+    }
+
+    /**
+     * Serialize this node into the writer as XML.
+     */
+    public static void serializeAsXML(Node node, Writer writer,
+                                      boolean omitXMLDecl,
+                                      boolean pretty) {
+        PrintWriter out = new PrintWriter(writer);
+        if (!omitXMLDecl) {
+            out.print("<?xml version=\"1.0\" encoding=UTF-8 ?>");
+        }
+        NSStack namespaceStack = new NSStack();
+        print(node, namespaceStack, out, pretty, 0);
+        out.flush();
+    }
+
+    private static void print(Node node, NSStack namespaceStack,
+                              PrintWriter out, boolean pretty,
+                              int indent) {
+        if (node == null) {
+            return;
+        }
+        boolean hasChildren = false;
+        int type = node.getNodeType();
+        switch (type) {
+            case Node.DOCUMENT_NODE:
+                {
+                    NodeList children = node.getChildNodes();
+                    if (children != null) {
+                        int numChildren = children.getLength();
+                        for (int i = 0; i < numChildren; i++) {
+                            print(children.item(i), namespaceStack, out,
+                                    pretty, indent);
+                        }
+                    }
+                    break;
+                }
+            case Node.ELEMENT_NODE:
+                {
+                    namespaceStack.push();
+                    if (pretty) {
+                        for (int i = 0; i < indent; i++)
+                            out.print(' ');
+                    }
+                    out.print('<' + node.getNodeName());
+                    String elPrefix = node.getPrefix();
+                    String elNamespaceURI = node.getNamespaceURI();
+                    if (elPrefix != null &&
+                            elNamespaceURI != null &&
+                            elPrefix.length() > 0) {
+                        boolean prefixIsDeclared = false;
+                        try {
+                            String namespaceURI = namespaceStack.getNamespaceURI(elPrefix);
+                            if (elNamespaceURI.equals(namespaceURI)) {
+                                prefixIsDeclared = true;
+                            }
+                        } catch (IllegalArgumentException e) {
+                            //
+                        }
+                        if (!prefixIsDeclared) {
+                            printNamespaceDecl(node, namespaceStack, out);
+                        }
+                    }
+                    NamedNodeMap attrs = node.getAttributes();
+                    int len = (attrs != null) ? attrs.getLength() : 0;
+                    for (int i = 0; i < len; i++) {
+                        Attr attr = (Attr) attrs.item(i);
+                        out.print(' ' + attr.getNodeName() + "=\"");
+                        normalize(attr.getValue(), out);
+                        out.print('\"');
+                        String attrPrefix = attr.getPrefix();
+                        String attrNamespaceURI = attr.getNamespaceURI();
+                        if (attrPrefix != null && attrNamespaceURI != null) {
+                            boolean prefixIsDeclared = false;
+                            try {
+                                String namespaceURI = namespaceStack.getNamespaceURI(attrPrefix);
+                                if (attrNamespaceURI.equals(namespaceURI)) {
+                                    prefixIsDeclared = true;
+                                }
+                            } catch (IllegalArgumentException e) {
+                                //
+                            }
+                            if (!prefixIsDeclared) {
+                                printNamespaceDecl(attr, namespaceStack, out);
+                            }
+                        }
+                    }
+                    NodeList children = node.getChildNodes();
+                    if (children != null) {
+                        int numChildren = children.getLength();
+                        hasChildren = (numChildren > 0);
+                        if (hasChildren) {
+                            out.print('>');
+                            if (pretty)
+                                out.print(LS);
+                        }
+                        for (int i = 0; i < numChildren; i++) {
+                            print(children.item(i), namespaceStack, out, pretty,
+                                    indent + 1);
+                        }
+                    } else {
+                        hasChildren = false;
+                    }
+                    if (!hasChildren) {
+                        out.print("/>");
+                        if (pretty)
+                            out.print(LS);
+                    }
+                    namespaceStack.pop();
+                    break;
+                }
+            case Node.ENTITY_REFERENCE_NODE:
+                {
+                    out.print('&');
+                    out.print(node.getNodeName());
+                    out.print(';');
+                    break;
+                }
+            case Node.CDATA_SECTION_NODE:
+                {
+                    out.print("<![CDATA[");
+                    out.print(node.getNodeValue());
+                    out.print("]]>");
+                    break;
+                }
+            case Node.TEXT_NODE:
+                {
+                    normalize(node.getNodeValue(), out);
+                    break;
+                }
+            case Node.COMMENT_NODE:
+                {
+                    out.print("<!--");
+                    out.print(node.getNodeValue());
+                    out.print("-->");
+                    if (pretty)
+                        out.print(LS);
+                    break;
+                }
+            case Node.PROCESSING_INSTRUCTION_NODE:
+                {
+                    out.print("<?");
+                    out.print(node.getNodeName());
+                    String data = node.getNodeValue();
+                    if (data != null && data.length() > 0) {
+                        out.print(' ');
+                        out.print(data);
+                    }
+                    out.println("?>");
+                    if (pretty)
+                        out.print(LS);
+                    break;
+                }
+        }
+        if (type == Node.ELEMENT_NODE && hasChildren == true) {
+            if (pretty) {
+                for (int i = 0; i < indent; i++)
+                    out.print(' ');
+            }
+            out.print("</");
+            out.print(node.getNodeName());
+            out.print('>');
+            if (pretty)
+                out.print(LS);
+            hasChildren = false;
+        }
+    }
+
+    private static void printNamespaceDecl(Node node,
+                                           NSStack namespaceStack,
+                                           PrintWriter out) {
+        switch (node.getNodeType()) {
+            case Node.ATTRIBUTE_NODE:
+                {
+                    printNamespaceDecl(((Attr) node).getOwnerElement(), node,
+                            namespaceStack, out);
+                    break;
+                }
+            case Node.ELEMENT_NODE:
+                {
+                    printNamespaceDecl((Element) node, node, namespaceStack, out);
+                    break;
+                }
+        }
+    }
+
+    private static void printNamespaceDecl(Element owner, Node node,
+                                           NSStack namespaceStack,
+                                           PrintWriter out) {
+        String namespaceURI = node.getNamespaceURI();
+        String prefix = node.getPrefix();
+        if (!(namespaceURI.equals(WSConstants.XMLNS_NS) && prefix.equals("xmlns")) &&
+                !(namespaceURI.equals(WSConstants.XML_NS) && prefix.equals("xml"))) {
+            if (WSSecurityUtil.getNamespace(prefix, owner) == null) {
+                out.print(" xmlns:" + prefix + "=\"" + namespaceURI + '\"');
+            }
+        } else {
+            prefix = node.getLocalName();
+            namespaceURI = node.getNodeValue();
+        }
+        namespaceStack.add(namespaceURI, prefix);
+    }
+
+    /**
+     * Normalizes and prints the given string.
+     */
+    public static void normalize(String s, PrintWriter fOut) {
+        int len = (s != null) ? s.length() : 0;
+        for (int i = 0; i < len; i++) {
+            char c = s.charAt(i);
+            switch (c) {
+                case '<':
+                    {
+                        fOut.print("&lt;");
+                        break;
+                    }
+                case '>':
+                    {
+                        fOut.print("&gt;");
+                        break;
+                    }
+                case '&':
+                    {
+                        fOut.print("&amp;");
+                        break;
+                    }
+                case '"':
+                    {
+                        fOut.print("&quot;");
+                        break;
+                    }
+                case '\r':
+                case '\n':
+                default:
+                    {
+                        fOut.print(c);
+                    }
+            }
+        }
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/util/Loader.java b/trunk/src/org/apache/ws/security/util/Loader.java
new file mode 100644
index 0000000..d463619
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/Loader.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+
+/**
+ * Load resources (or images) from various sources.
+ * <p/>
+ *
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class Loader {
+    private static Log log = LogFactory.getLog(Loader.class.getName());
+
+    /**
+     * This method will search for <code>resource</code> in different
+     * places. The search order is as follows:
+     * <ol>
+     * <p><li>Search for <code>resource</code> using the thread context
+     * class loader under Java2.
+     * <p><li>Try one last time with
+     * <code>ClassLoader.getSystemResource(resource)</code>, that is is
+     * using the system class loader in JDK 1.2 and virtual machine's
+     * built-in class loader in JDK 1.1.
+     * </ol>
+     * <p/>
+     *
+     * @param resource
+     * @return TODO
+     */
+    static public URL getResource(String resource) {
+        ClassLoader classLoader = null;
+        URL url = null;
+        try {
+            classLoader = getTCL();
+            if (classLoader != null) {
+                log.debug("Trying to find [" + resource + "] using " + classLoader + " class loader.");
+                url = classLoader.getResource(resource);
+                if (url != null) {
+                    return url;
+                }
+            }
+        } catch (Throwable t) {
+            log.warn("Caught Exception while in Loader.getResource. This may be innocuous.", t);
+        }
+    
+        // Last ditch attempt: get the resource from the class path. It
+        // may be the case that clazz was loaded by the Extension class
+        // loader which the parent of the system class loader. Hence the
+        // code below.
+        log.debug("Trying to find [" + resource + "] using ClassLoader.getSystemResource().");
+        return ClassLoader.getSystemResource(resource);
+    }
+    
+
+    /**
+     * This method will search for <code>resource</code> in different
+     * places. The search order is as follows:
+     * <ol>
+     * <p><li>Search for <code>resource</code> using the supplied class loader. 
+     * If that fails, search for <code>resource</code> using the thread context
+     * class loader.
+     * <p><li>Try one last time with
+     * <code>ClassLoader.getSystemResource(resource)</code>, that is is
+     * using the system class loader in JDK 1.2 and virtual machine's
+     * built-in class loader in JDK 1.1.
+     * </ol>
+     * <p/>
+     *
+     * @param resource
+     * @return TODO
+     */
+    static public URL getResource(ClassLoader loader, String resource) {
+        URL url = null;
+        try {
+            if (loader != null) {
+                log.debug("Trying to find [" + resource + "] using " + loader + " class loader.");
+                url = loader.getResource(resource);
+                if (url != null) {
+                    return url;
+                }
+            }
+        } catch (Throwable t) {
+            log.warn("Caught Exception while in Loader.getResource. This may be innocuous.", t);
+        }
+        return getResource(resource);
+    }
+
+    /**
+     * Get the Thread context class loader.
+     * <p/>
+     *
+     * @return the Thread context class loader
+     * @throws IllegalAccessException
+     * @throws InvocationTargetException
+     */
+    static public ClassLoader getTCL() throws IllegalAccessException, InvocationTargetException {
+        return Thread.currentThread().getContextClassLoader();
+    }
+
+    /**
+     * Try the specified classloader and then fall back to the loadClass
+     * <p/>
+     *
+     * @param loader
+     * @param clazz
+     * @return Class
+     * @throws ClassNotFoundException
+     */
+    static public Class loadClass(ClassLoader loader, String clazz) throws ClassNotFoundException {
+        try {
+            if (loader != null) {
+                Class c = loader.loadClass(clazz);
+                if (c != null) {
+                    return c;
+                }
+            }
+        } catch (Throwable e) {
+            log.warn(e.getMessage(), e);
+        }
+        return loadClass(clazz);
+    }
+
+    /**
+     * If running under JDK 1.2 load the specified class using the
+     * <code>Thread</code> <code>contextClassLoader</code> if that
+     * fails try Class.forname.
+     * <p/>
+     *
+     * @param clazz
+     * @return TODO
+     * @throws ClassNotFoundException
+     */
+    static public Class loadClass(String clazz) throws ClassNotFoundException {
+        try {
+            ClassLoader tcl = getTCL(); 
+            
+            if (tcl != null) {
+                Class c = tcl.loadClass(clazz);
+                if (c != null) {
+                    return c;
+                }
+            }
+        } catch (Throwable e) {
+            log.warn(e.getMessage(), e);
+        }
+        // we reached here because tcl was null or because of a
+        // security exception, or because clazz could not be loaded...
+        // In any case we now try one more time
+        return Class.forName(clazz);
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/util/Mapping.java b/trunk/src/org/apache/ws/security/util/Mapping.java
new file mode 100644
index 0000000..59bc5d9
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/Mapping.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.util;
+
+import java.io.Serializable;
+
+public class Mapping implements Serializable {
+    private String namespaceURI;
+    private int namespaceHash;
+
+    private String prefix;
+    private int prefixHash;
+
+    public Mapping(String namespaceURI, String prefix) {
+        setPrefix(prefix);
+        setNamespaceURI(namespaceURI);
+    }
+
+    public String getNamespaceURI() {
+        return namespaceURI;
+    }
+
+    public int getNamespaceHash() {
+        return namespaceHash;
+    }
+
+    public void setNamespaceURI(String namespaceURI) {
+        this.namespaceURI = namespaceURI;
+        this.namespaceHash = namespaceURI.hashCode();
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public int getPrefixHash() {
+        return prefixHash;
+    }
+
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+        this.prefixHash = prefix.hashCode();
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/util/NSStack.java b/trunk/src/org/apache/ws/security/util/NSStack.java
new file mode 100644
index 0000000..898fe93
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/NSStack.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+
+/**
+ * The abstraction this class provides is a push down stack of variable
+ * length frames of prefix to namespace mappings.  Used for keeping track
+ * of what namespaces are active at any given point as an XML document is
+ * traversed or produced.
+ * <p/>
+ * From a performance point of view, this data will both be modified frequently
+ * (at a minimum, there will be one push and pop per XML element processed),
+ * and scanned frequently (many of the "good" mappings will be at the bottom
+ * of the stack).  The one saving grace is that the expected maximum
+ * cardinalities of the number of frames and the number of total mappings
+ * is only in the dozens, representing the nesting depth of an XML document
+ * and the number of active namespaces at any point in the processing.
+ * <p/>
+ * Accordingly, this stack is implemented as a single array, will null
+ * values used to indicate frame boundaries.
+ *
+ * @author James Snell
+ * @author Glen Daniels (gdaniels@apache.org)
+ * @author Sam Ruby (rubys@us.ibm.com)
+ */
+public class NSStack {
+    protected static Log log =
+            LogFactory.getLog(NSStack.class.getName());
+
+    private Mapping[] stack;
+    private int top = 0;
+    private int iterator = 0;
+    private int currentDefaultNS = -1;
+    // invariant member variable to track low-level logging requirements
+    // we cache this once per instance lifecycle to avoid repeated lookups
+    // in heavily used code.
+    private final boolean traceEnabled = log.isTraceEnabled();
+
+    public NSStack() {
+        stack = new Mapping[32];
+        stack[0] = null;
+    }
+
+    /**
+     * Create a new frame at the top of the stack.
+     */
+    public void push() {
+        top++;
+        if (top >= stack.length) {
+            Mapping newstack[] = new Mapping[stack.length * 2];
+            System.arraycopy(stack, 0, newstack, 0, stack.length);
+            stack = newstack;
+        }
+        if (traceEnabled)
+            log.trace("NSPush (" + stack.length + ")");
+        stack[top] = null;
+    }
+
+    /**
+     * Remove the top frame from the stack.
+     */
+    public void pop() {
+        clearFrame();
+        top--;
+
+        // If we've moved below the current default NS, figure out the new
+        // default (if any)
+        if (top < currentDefaultNS) {
+            // Reset the currentDefaultNS to ignore the frame just removed.
+            currentDefaultNS = top;
+            while (currentDefaultNS > 0) {
+                if (stack[currentDefaultNS] != null &&
+                        stack[currentDefaultNS].getPrefix().length() == 0)
+                    break;
+                currentDefaultNS--;
+            }
+        }
+        if (top == 0) {
+            if (traceEnabled)
+                log.trace("NSPop (empty)");
+            return;
+        }
+        if (traceEnabled) {
+            log.trace("NSPop (" + stack.length + ")");
+        }
+    }
+
+    /**
+     * Return a copy of the current frame.  Returns null if none are present.
+     */
+    public ArrayList cloneFrame() {
+        if (stack[top] == null) return null;
+        ArrayList clone = new ArrayList();
+        for (Mapping map = topOfFrame(); map != null; map = next()) {
+            clone.add(map);
+        }
+        return clone;
+    }
+
+    /**
+     * Remove all mappings from the current frame.
+     */
+    private void clearFrame() {
+        while (stack[top] != null) top--;
+    }
+
+    /**
+     * Reset the embedded iterator in this class to the top of the current
+     * (i.e., last) frame.  Note that this is not threadsafe, nor does it
+     * provide multiple iterators, so don't use this recursively.  Nor
+     * should you modify the stack while iterating over it.
+     */
+    public Mapping topOfFrame() {
+        iterator = top;
+        while (stack[iterator] != null) iterator--;
+        iterator++;
+        return next();
+    }
+
+    /**
+     * Return the next namespace mapping in the top frame.
+     */
+    public Mapping next() {
+        if (iterator > top) {
+            return null;
+        } else {
+            return stack[iterator++];
+        }
+    }
+
+    /**
+     * Add a mapping for a namespaceURI to the specified prefix to the top
+     * frame in the stack.  If the prefix is already mapped in that frame,
+     * remap it to the (possibly different) namespaceURI.
+     */
+    public void add(String namespaceURI, String prefix) {
+        int idx = top;
+        try {
+            // Replace duplicate prefixes (last wins - this could also fault)
+            for (int cursor = top; stack[cursor] != null; cursor--) {
+                if (stack[cursor].getPrefix().equals(prefix)) {
+                    stack[cursor].setNamespaceURI(namespaceURI);
+                    idx = cursor;
+                    return;
+                }
+            }
+            push();
+            stack[top] = new Mapping(namespaceURI, prefix);
+            idx = top;
+        } finally {
+            // If this is the default namespace, note the new in-scope
+            // default is here.
+            if (prefix.length() == 0) {
+                currentDefaultNS = idx;
+            }
+        }
+    }
+
+    /**
+     * Return an active prefix for the given namespaceURI.  NOTE : This
+     * may return null even if the namespaceURI was actually mapped further
+     * up the stack IF the prefix which was used has been repeated further
+     * down the stack.  I.e.:
+     * <p/>
+     * <pre:outer xmlns:pre="namespace">
+     * <pre:inner xmlns:pre="otherNamespace">
+     * *here's where we're looking*
+     * </pre:inner>
+     * </pre:outer>
+     * <p/>
+     * If we look for a prefix for "namespace" at the indicated spot, we won't
+     * find one because "pre" is actually mapped to "otherNamespace"
+     */
+    public String getPrefix(String namespaceURI, boolean noDefault) {
+        if ((namespaceURI == null) || (namespaceURI.equals("")))
+            return null;
+        int hash = namespaceURI.hashCode();
+
+        // If defaults are OK, and the given NS is the current default,
+        // return "" as the prefix to favor defaults where possible.
+        if (!noDefault && currentDefaultNS > 0 && stack[currentDefaultNS] != null &&
+                namespaceURI.equals(stack[currentDefaultNS].getNamespaceURI()))
+            return "";
+        for (int cursor = top; cursor > 0; cursor--) {
+            Mapping map = stack[cursor];
+            if (map == null) continue;
+            if (map.getNamespaceHash() == hash &&
+                    map.getNamespaceURI().equals(namespaceURI)) {
+                String possiblePrefix = map.getPrefix();
+                if (noDefault && possiblePrefix.length() == 0) continue;
+
+                // now make sure that this is the first occurance of this 
+                // particular prefix
+                int ppHash = possiblePrefix.hashCode();
+                for (int cursor2 = top; true; cursor2--) {
+                    if (cursor2 == cursor) return possiblePrefix;
+                    map = stack[cursor2];
+                    if (map == null) continue;
+                    if (ppHash == map.getPrefixHash() &&
+                            possiblePrefix.equals(map.getPrefix()))
+                        break;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return an active prefix for the given namespaceURI, including
+     * the default prefix ("").
+     */
+    public String getPrefix(String namespaceURI) {
+        return getPrefix(namespaceURI, false);
+    }
+
+    /**
+     * Given a prefix, return the associated namespace (if any).
+     */
+    public String getNamespaceURI(String prefix) {
+        if (prefix == null)
+            prefix = "";
+        int hash = prefix.hashCode();
+        for (int cursor = top; cursor > 0; cursor--) {
+            Mapping map = stack[cursor];
+            if (map == null) continue;
+            if (map.getPrefixHash() == hash && map.getPrefix().equals(prefix))
+                return map.getNamespaceURI();
+        }
+        return null;
+    }
+
+    /**
+     * Produce a trace dump of the entire stack, starting from the top and
+     * including frame markers.
+     */
+    public void dump(String dumpPrefix) {
+        for (int cursor = top; cursor > 0; cursor--) {
+            Mapping map = stack[cursor];
+            if (map == null) {
+                log.trace(dumpPrefix + "stackFrame00");
+            } else {
+                log.trace(dumpPrefix + map.getNamespaceURI() + " -> " + map.getPrefix());
+            }
+        }
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/util/StringUtil.java b/trunk/src/org/apache/ws/security/util/StringUtil.java
new file mode 100644
index 0000000..c64607b
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/StringUtil.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.ws.security.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class StringUtil {
+    /**
+     * An empty immutable <code>String</code> array.
+     */
+    public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+    /**
+     * Tests if this string starts with the specified prefix (Ignoring whitespaces)
+     *
+     * @param prefix
+     * @param string
+     * @return boolean
+     */
+    public static boolean startsWithIgnoreWhitespaces(String prefix, String string) {
+        int index1 = 0;
+        int index2 = 0;
+        int length1 = prefix.length();
+        int length2 = string.length();
+        char ch1 = ' ';
+        char ch2 = ' ';
+        while (index1 < length1 && index2 < length2) {
+            while (index1 < length1 && Character.isWhitespace(ch1 = prefix.charAt(index1))) {
+                index1++;
+            }
+            while (index2 < length2 && Character.isWhitespace(ch2 = string.charAt(index2))) {
+                index2++;
+            }
+            if (index1 == length1 && index2 == length2) {
+                return true;
+            }
+            if (ch1 != ch2) {
+                return false;
+            }
+            index1++;
+            index2++;
+        }
+        if (index1 < length1 && index2 >= length2)
+            return false;
+        return true;
+    }
+
+    /**
+     * <p>Splits the provided text into an array, separator specified.
+     * This is an alternative to using StringTokenizer.</p>
+     * <p/>
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.</p>
+     * <p/>
+     * <p>A <code>null</code> input String returns <code>null</code>.</p>
+     * <p/>
+     * <pre>
+     * StringUtils.split(null, *)         = null
+     * StringUtils.split("", *)           = []
+     * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
+     * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
+     * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
+     * StringUtils.split("a\tb\nc", null) = ["a", "b", "c"]
+     * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
+     * </pre>
+     *
+     * @param str           the String to parse, may be null
+     * @param separatorChar the character used as the delimiter,
+     *                      <code>null</code> splits on whitespace
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     */
+    public static String[] split(String str, char separatorChar) {
+        if (str == null) {
+            return null;
+        }
+        int len = str.length();
+        if (len == 0) {
+            return EMPTY_STRING_ARRAY;
+        }
+        List list = new ArrayList();
+        int i = 0, start = 0;
+        boolean match = false;
+        while (i < len) {
+            if (str.charAt(i) == separatorChar) {
+                if (match) {
+                    list.add(str.substring(start, i));
+                    match = false;
+                }
+                start = ++i;
+                continue;
+            }
+            match = true;
+            i++;
+        }
+        if (match) {
+            list.add(str.substring(start, i));
+        }
+        return (String[]) list.toArray(new String[list.size()]);
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/util/UUIDGenerator.java b/trunk/src/org/apache/ws/security/util/UUIDGenerator.java
new file mode 100644
index 0000000..4592cb5
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/UUIDGenerator.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed 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.ws.security.util;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.Random;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * UUID generator (taken from Axis2) 
+ */
+public class UUIDGenerator {
+    
+    private static final Log log = LogFactory.getLog(UUIDGenerator.class);
+
+    private static String baseUUID = null;
+    private static long incrementingValue = 0;
+
+
+    private static Random myRand = null;
+
+    /**
+     * MD5 a random string with localhost/date etc will return 128 bits
+     * construct a string of 18 characters from those bits.
+     *
+     * @return string
+     */
+    public static String getUUID() {
+        if (baseUUID == null) {
+            baseUUID = getInitialUUID();
+        }
+        if(++incrementingValue >= Long.MAX_VALUE){
+            incrementingValue = 0;
+        }
+        return baseUUID + new Date().getTime() + incrementingValue;
+    }
+
+    protected static String getInitialUUID() {
+        if (myRand == null) {
+            myRand = new Random();
+        }
+        long rand = myRand.nextLong();
+        String sid;
+        try {
+            sid = InetAddress.getLocalHost().toString();
+        } catch (UnknownHostException e) {
+            sid = Thread.currentThread().getName();
+        }
+        StringBuffer sb = new StringBuffer();
+        sb.append(sid);
+        sb.append(":");
+        sb.append(Long.toString(rand));
+        MessageDigest md5 = null;
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            if (log.isDebugEnabled()) {
+                log.debug(e.getMessage(), e);
+            }
+            //todo have to be properly handled
+        }
+        md5.update(sb.toString().getBytes());
+        byte[] array = md5.digest();
+        StringBuffer sb2 = new StringBuffer();
+        for (int j = 0; j < array.length; ++j) {
+            int b = array[j] & 0xFF;
+            sb2.append(Integer.toHexString(b));
+        }
+        int begin = myRand.nextInt();
+        if (begin < 0) begin = begin * -1;
+        begin = begin % 8;
+        return sb2.toString().substring(begin, begin + 18).toUpperCase();
+    }
+
+}
diff --git a/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java b/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java
new file mode 100644
index 0000000..370e787
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/WSSecurityUtil.java
@@ -0,0 +1,1016 @@
+/*
+ * Copyright  2003-2006 The Apache Software Foundation, or their licensors, as
+ * appropriate.
+ *
+ *  Licensed 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.ws.security.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAP11Constants;
+import org.apache.ws.security.SOAP12Constants;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.handler.WSHandlerResult;
+import org.apache.xml.security.algorithms.JCEMapper;
+import org.apache.xml.security.signature.XMLSignature;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.namespace.QName;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ * WS-Security Utility methods. <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com).
+ */
+public class WSSecurityUtil {
+    private static Log log = LogFactory.getLog(WSSecurityUtil.class);
+
+    /**
+     * A cached pseudo-random number generator
+     * NB. On some JVMs, caching this random number
+     * generator is required to overcome punitive
+     * overhead.
+     */
+    private static SecureRandom random = null;
+    
+    /**
+     * Returns the first WS-Security header element for a given actor. Only one
+     * WS-Security header is allowed for an actor.
+     * 
+     * @param doc
+     * @param actor
+     * @return the <code>wsse:Security</code> element or <code>null</code>
+     *         if not such element found
+     */
+    public static Element getSecurityHeader(Document doc, String actor,
+            SOAPConstants sc) {
+        Element soapHeaderElement = (Element) getDirectChild(doc
+                .getDocumentElement(), sc.getHeaderQName().getLocalPart(), sc
+                .getEnvelopeURI());
+
+        if (soapHeaderElement == null) { // no SOAP header at all
+            return null;
+        }
+
+        // get all wsse:Security nodes
+        NodeList list = null;
+        int len = 0;
+        list = soapHeaderElement.getElementsByTagNameNS(WSConstants.WSSE_NS,
+                WSConstants.WSSE_LN);
+        if (list == null) {
+            return null;
+        } else {
+            len = list.getLength();
+        }
+        Element elem;
+        Attr attr;
+        String hActor;
+        for (int i = 0; i < len; i++) {
+            elem = (Element) list.item(i);
+            attr = elem.getAttributeNodeNS(sc.getEnvelopeURI(), sc
+                    .getRoleAttributeQName().getLocalPart());
+            hActor = (attr != null) ? attr.getValue() : null;
+            if (WSSecurityUtil.isActorEqual(actor, hActor)) {
+                return elem;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Compares two actor strings and returns true if these are equal. Takes
+     * care of the null length strings and uses ignore case.
+     * 
+     * @param actor
+     * @param hActor
+     * @return TODO
+     */
+    public static boolean isActorEqual(String actor, String hActor) {
+        if ((((hActor == null) || (hActor.length() == 0)) && ((actor == null) || (actor
+                .length() == 0)))
+                || ((hActor != null) && (actor != null) && hActor
+                        .equalsIgnoreCase(actor))) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Gets a direct child with specified localname and namespace. <p/>
+     * 
+     * @param fNode
+     *            the node where to start the search
+     * @param localName
+     *            local name of the child to get
+     * @param namespace
+     *            the namespace of the child to get
+     * @return the node or <code>null</code> if not such node found
+     */
+    public static Node getDirectChild(Node fNode, String localName,
+            String namespace) {
+        for (Node currentChild = fNode.getFirstChild(); currentChild != null; currentChild = currentChild
+                .getNextSibling()) {
+            if (localName.equals(currentChild.getLocalName())
+                    && namespace.equals(currentChild.getNamespaceURI())) {
+                return currentChild;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * return the first soap "Body" element. <p/>
+     * 
+     * @param doc
+     * @return the body element or <code>null</code> if document does not
+     *         contain a SOAP body
+     */
+    public static Element findBodyElement(Document doc, SOAPConstants sc) {
+        Element soapBodyElement = (Element) WSSecurityUtil.getDirectChild(doc
+                .getFirstChild(), sc.getBodyQName().getLocalPart(), sc
+                .getEnvelopeURI());
+        return soapBodyElement;
+    }
+
+    /**
+     * Returns the first element that matches <code>name</code> and
+     * <code>namespace</code>. <p/> This is a replacement for a XPath lookup
+     * <code>//name</code> with the given namespace. It's somewhat faster than
+     * XPath, and we do not deal with prefixes, just with the real namespace URI
+     * 
+     * @param startNode
+     *            Where to start the search
+     * @param name
+     *            Local name of the element
+     * @param namespace
+     *            Namespace URI of the element
+     * @return The found element or <code>null</code>
+     */
+    public static Node findElement(Node startNode, String name, String namespace) {
+
+        /*
+         * Replace the formely recursive implementation with a depth-first-loop
+         * lookup
+         */
+        if (startNode == null) {
+            return null;
+        }
+        Node startParent = startNode.getParentNode();
+        Node processedNode = null;
+
+        while (startNode != null) {
+            // start node processing at this point
+            if (startNode.getNodeType() == Node.ELEMENT_NODE
+                    && startNode.getLocalName().equals(name)) {
+                String ns = startNode.getNamespaceURI();
+                if (ns != null && ns.equals(namespace)) {
+                    return startNode;
+                }
+
+                if ((namespace == null || namespace.length() == 0)
+                        && (ns == null || ns.length() == 0)) {
+                    return startNode;
+                }
+            }
+            processedNode = startNode;
+            startNode = startNode.getFirstChild();
+
+            // no child, this node is done.
+            if (startNode == null) {
+                // close node processing, get sibling
+                startNode = processedNode.getNextSibling();
+            }
+            // no more siblings, get parent, all children
+            // of parent are processed.
+            while (startNode == null) {
+                processedNode = processedNode.getParentNode();
+                if (processedNode == startParent) {
+                    return null;
+                }
+                // close parent node processing (processed node now)
+                startNode = processedNode.getNextSibling();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the single element that containes an Id with value
+     * <code>uri</code> and <code>namespace</code>. <p/> This is a
+     * replacement for a XPath Id lookup with the given namespace. It's somewhat
+     * faster than XPath, and we do not deal with prefixes, just with the real
+     * namespace URI
+     * 
+     * If there are multiple elements, we log a warning and return null as this
+     * can be used to get around the signature checking.
+     * 
+     * @param startNode
+     *            Where to start the search
+     * @param value
+     *            Value of the Id attribute
+     * @param namespace
+     *            Namespace URI of the Id
+     * @return The found element if there was exactly one match, or
+     *         <code>null</code> otherwise
+     */
+    public static Element findElementById(Node startNode, String value,
+            String namespace) {
+        Element foundElement = null;
+
+        /*
+         * Replace the formerly recursive implementation with a depth-first-loop
+         * lookup
+         */
+        if (startNode == null) {
+            return null;
+        }
+        Node startParent = startNode.getParentNode();
+        Node processedNode = null;
+
+        while (startNode != null) {
+            // start node processing at this point
+            if (startNode.getNodeType() == Node.ELEMENT_NODE) {
+                Element se = (Element) startNode;
+                if (se.hasAttributeNS(namespace, "Id")
+                        && value.equals(se.getAttributeNS(namespace, "Id"))) {
+                    if (foundElement == null) {
+                        foundElement = se; // Continue searching to find
+                        // duplicates
+                    } else {
+                        log
+                                .warn("Multiple elements with the same 'Id' attribute value!");
+                        return null;
+                    }
+                }
+            }
+
+            processedNode = startNode;
+            startNode = startNode.getFirstChild();
+
+            // no child, this node is done.
+            if (startNode == null) {
+                // close node processing, get sibling
+                startNode = processedNode.getNextSibling();
+            }
+            // no more siblings, get parent, all children
+            // of parent are processed.
+            while (startNode == null) {
+                processedNode = processedNode.getParentNode();
+                if (processedNode == startParent) {
+                    return foundElement;
+                }
+                // close parent node processing (processed node now)
+                startNode = processedNode.getNextSibling();
+            }
+        }
+        return foundElement;
+    }
+
+    /**
+     * set the namespace if it is not set already. <p/>
+     * 
+     * @param element
+     * @param namespace
+     * @param prefix
+     * @return TODO
+     */
+    public static String setNamespace(Element element, String namespace,
+            String prefix) {
+        String pre = getPrefixNS(namespace, element);
+        if (pre != null) {
+            return pre;
+        }
+        element.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:" + prefix,
+                namespace);
+        return prefix;
+    }
+
+    /*
+     * ** The following methods were copied over from aixs.utils.XMLUtils and
+     * adapted
+     */
+
+    public static String getPrefixNS(String uri, Node e) {
+        while (e != null && (e.getNodeType() == Element.ELEMENT_NODE)) {
+            NamedNodeMap attrs = e.getAttributes();
+            for (int n = 0; n < attrs.getLength(); n++) {
+                Attr a = (Attr) attrs.item(n);
+                String name;
+                if ((name = a.getName()).startsWith("xmlns:")
+                        && a.getNodeValue().equals(uri)) {
+                    return name.substring(6);
+                }
+            }
+            e = e.getParentNode();
+        }
+        return null;
+    }
+
+    public static String getNamespace(String prefix, Node e) {
+        while (e != null && (e.getNodeType() == Node.ELEMENT_NODE)) {
+            Attr attr = null;
+            if (prefix == null) {
+                attr = ((Element) e).getAttributeNode("xmlns");
+            } else {
+                attr = ((Element) e).getAttributeNodeNS(WSConstants.XMLNS_NS,
+                        prefix);
+            }
+            if (attr != null)
+                return attr.getValue();
+            e = e.getParentNode();
+        }
+        return null;
+    }
+
+    /**
+     * Return a QName when passed a string like "foo:bar" by mapping the "foo"
+     * prefix to a namespace in the context of the given Node.
+     * 
+     * @return a QName generated from the given string representation
+     */
+    public static QName getQNameFromString(String str, Node e) {
+        return getQNameFromString(str, e, false);
+    }
+
+    /**
+     * Return a QName when passed a string like "foo:bar" by mapping the "foo"
+     * prefix to a namespace in the context of the given Node. If default
+     * namespace is found it is returned as part of the QName.
+     * 
+     * @return a QName generated from the given string representation
+     */
+    public static QName getFullQNameFromString(String str, Node e) {
+        return getQNameFromString(str, e, true);
+    }
+
+    private static QName getQNameFromString(String str, Node e,
+            boolean defaultNS) {
+        if (str == null || e == null)
+            return null;
+        int idx = str.indexOf(':');
+        if (idx > -1) {
+            String prefix = str.substring(0, idx);
+            String ns = getNamespace(prefix, e);
+            if (ns == null)
+                return null;
+            return new QName(ns, str.substring(idx + 1));
+        } else {
+            if (defaultNS) {
+                String ns = getNamespace(null, e);
+                if (ns != null)
+                    return new QName(ns, str);
+            }
+            return new QName("", str);
+        }
+    }
+
+    /**
+     * Return a string for a particular QName, mapping a new prefix if
+     * necessary.
+     */
+    public static String getStringForQName(QName qname, Element e) {
+        String uri = qname.getNamespaceURI();
+        String prefix = getPrefixNS(uri, e);
+        if (prefix == null) {
+            int i = 1;
+            prefix = "ns" + i;
+            while (getNamespace(prefix, e) != null) {
+                i++;
+                prefix = "ns" + i;
+            }
+            e.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:" + prefix, uri);
+        }
+        return prefix + ":" + qname.getLocalPart();
+    }
+
+    /* ** up to here */
+
+    /**
+     * Search for an element given its wsu:id. <p/>
+     * 
+     * @param doc
+     *            the DOM document (SOAP request)
+     * @param id
+     *            the Id of the element
+     * @return the found element or null if no element with the Id exists
+     */
+    public static Element getElementByWsuId(Document doc, String id) {
+
+        if (id == null) {
+            return null;
+        }
+        id = getIDFromReference(id);
+        return WSSecurityUtil.findElementById(doc.getDocumentElement(), id,
+                WSConstants.WSU_NS);
+    }
+
+    /**
+     * Turn a reference (eg "#5") into an ID (eg "5").
+     * 
+     * @param ref
+     * @return ref trimmed and with the leading "#" removed, or null if not
+     *         correctly formed
+     */
+    public static String getIDFromReference(String ref) {
+        String id = ref.trim();
+        if ((id.length() == 0) || (id.charAt(0) != '#')) {
+            return null;
+        }
+        return id.substring(1);
+    }
+    
+    /**
+     * Turn a reference (eg "#5") into an ID (eg "5").
+     * 
+     * @param ref
+     * @return ref trimmed and with the leading "#" removed, or null if not
+     *         correctly formed
+     * @deprecated use getIDFromReference instead
+     */
+    public static String getIDfromReference(String ref) {
+        return getIDFromReference(ref);
+    }
+
+    /**
+     * Search for an element given its generic id. <p/>
+     * 
+     * @param doc
+     *            the DOM document (SOAP request)
+     * @param id
+     *            the Id of the element
+     * @return the found element or null if no element with the Id exists
+     */
+    public static Element getElementByGenId(Document doc, String id) {
+        if (id == null) {
+            return null;
+        }
+        id = id.trim();
+        if ((id.length() == 0) || (id.charAt(0) != '#')) {
+            return null;
+        }
+        id = id.substring(1);
+        return WSSecurityUtil.findElementById(doc.getDocumentElement(), id,
+                null);
+    }
+
+    /**
+     * create a new element in the same namespace <p/>
+     * 
+     * @param parent
+     *            for the new element
+     * @param localName
+     *            of the new element
+     * @return the new element
+     */
+    private static Element createElementInSameNamespace(Element parent,
+            String localName) {
+        
+        String qName = localName;
+        
+        String prefix = parent.getPrefix();
+        if (prefix != null && prefix.length() > 0) {
+            qName = prefix + ":" + localName;
+        }
+         
+        String nsUri = parent.getNamespaceURI();
+        return parent.getOwnerDocument().createElementNS(nsUri, qName);
+    }
+
+    /**
+     * find a child element with given namespace and local name <p/>
+     * 
+     * @param parent
+     *            the node to start the search
+     * @param namespaceUri
+     *            of the element
+     * @param localName
+     *            of the element
+     * @return the found element or null if the element does not exist
+     */
+    private static Element findChildElement(Element parent,
+            String namespaceUri, String localName) {
+        NodeList children = parent.getChildNodes();
+        int len = children.getLength();
+        for (int i = 0; i < len; i++) {
+            Node child = children.item(i);
+            if (child.getNodeType() == Node.ELEMENT_NODE) {
+                Element elementChild = (Element) child;
+                if (namespaceUri.equals(elementChild.getNamespaceURI())
+                        && localName.equals(elementChild.getLocalName())) {
+                    return elementChild;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * append a child element <p/>
+     * 
+     * @param doc
+     *            the DOM document (SOAP request)
+     * @param parent
+     *            element of this child element
+     * @param child
+     *            the element to append
+     * @return the child element
+     */
+    public static Element appendChildElement(Document doc, Element parent,
+            Element child) {
+        Node whitespaceText = doc.createTextNode("\n");
+        parent.appendChild(whitespaceText);
+        parent.appendChild(child);
+        return child;
+    }
+
+    /**
+     * prepend a child element <p/>
+     * 
+     * @param doc
+     *            the DOM document (SOAP request)
+     * @param parent
+     *            element of this child element
+     * @param child
+     *            the element to append
+     * @param addWhitespace
+     *            if true prepend a newline before child
+     * @return the child element
+     */
+    public static Element prependChildElement(Document doc, Element parent,
+            Element child, boolean addWhitespace) {
+        Node firstChild = parent.getFirstChild();
+        if (firstChild == null) {
+            parent.appendChild(child);
+        } else {
+            parent.insertBefore(child, firstChild);
+        }
+        if (addWhitespace) {
+            Node whitespaceText = doc.createTextNode("\n");
+            parent.insertBefore(whitespaceText, child);
+        }
+        return child;
+    }
+
+    /**
+     * find the first ws-security header block <p/>
+     * 
+     * @param doc
+     *            the DOM document (SOAP request)
+     * @param envelope
+     *            the SOAP envelope
+     * @param doCreate
+     *            if true create a new WSS header block if none exists
+     * @return the WSS header or null if none found and doCreate is false
+     */
+    public static Element findWsseSecurityHeaderBlock(Document doc,
+            Element envelope, boolean doCreate) {
+        return findWsseSecurityHeaderBlock(doc, envelope, null, doCreate);
+    }
+
+    /**
+     * find a ws-security header block for a given actor <p/>
+     * 
+     * @param doc
+     *            the DOM document (SOAP request)
+     * @param envelope
+     *            the SOAP envelope
+     * @param actor
+     *            the actor (role) name of the WSS header
+     * @param doCreate
+     *            if true create a new WSS header block if none exists
+     * @return the WSS header or null if none found and doCreate is false
+     */
+    public static Element findWsseSecurityHeaderBlock(Document doc,
+            Element envelope, String actor, boolean doCreate) {
+        SOAPConstants sc = getSOAPConstants(envelope);
+        Element wsseSecurity = getSecurityHeader(doc, actor, sc);
+        if (wsseSecurity != null) {
+            return wsseSecurity;
+        }
+        Element header = findChildElement(envelope, sc.getEnvelopeURI(), sc
+                .getHeaderQName().getLocalPart());
+        if (header == null && doCreate) {
+            header = createElementInSameNamespace(envelope, sc
+                    .getHeaderQName().getLocalPart());
+            header = prependChildElement(doc, envelope, header, true);
+        }
+        if (doCreate) {
+            wsseSecurity = header.getOwnerDocument().createElementNS(
+                    WSConstants.WSSE_NS, "wsse:Security");
+            wsseSecurity.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsse",
+                    WSConstants.WSSE_NS);
+            return prependChildElement(doc, header, wsseSecurity, true);
+        }
+        return null;
+    }
+
+    /**
+     * create a base64 test node <p/>
+     * 
+     * @param doc
+     *            the DOM document (SOAP request)
+     * @param data
+     *            to encode
+     * @return a Text node containing the base64 encoded data
+     */
+    public static Text createBase64EncodedTextNode(Document doc, byte data[]) {
+        return doc.createTextNode(Base64.encode(data));
+    }
+
+    public static SecretKey prepareSecretKey(String symEncAlgo, byte[] rawKey) {
+        SecretKeySpec keySpec = new SecretKeySpec(rawKey, JCEMapper
+                .getJCEKeyAlgorithmFromURI(symEncAlgo));
+        return (SecretKey) keySpec;
+    }
+
+    public static SOAPConstants getSOAPConstants(Element startElement) {
+        Document doc = startElement.getOwnerDocument();
+        String ns = doc.getDocumentElement().getNamespaceURI();
+        if (WSConstants.URI_SOAP12_ENV.equals(ns)) {
+            return new SOAP12Constants();
+        } else {
+            return new SOAP11Constants();
+        }
+    }
+
+    public static Cipher getCipherInstance(String cipherAlgo)
+            throws WSSecurityException {
+        Cipher cipher = null;
+        try {
+            if (cipherAlgo.equalsIgnoreCase(WSConstants.KEYTRANSPORT_RSA15)) {
+                cipher = Cipher.getInstance("RSA/NONE/PKCS1PADDING");
+            } else if (cipherAlgo
+                    .equalsIgnoreCase(WSConstants.KEYTRANSPORT_RSAOEP)) {
+                cipher = Cipher.getInstance("RSA/NONE/OAEPPADDING");
+            } else {
+                throw new WSSecurityException(
+                        WSSecurityException.UNSUPPORTED_ALGORITHM,
+                        "unsupportedKeyTransp", new Object[] { cipherAlgo });
+            }
+        } catch (NoSuchPaddingException ex) {
+            throw new WSSecurityException(
+                WSSecurityException.UNSUPPORTED_ALGORITHM, "unsupportedKeyTransp", 
+                new Object[] { "No such padding: " + cipherAlgo }, ex
+            );
+        } catch (NoSuchAlgorithmException ex) {
+            throw new WSSecurityException(
+                WSSecurityException.UNSUPPORTED_ALGORITHM, "unsupportedKeyTransp",
+                new Object[] { "No such algorithm: " + cipherAlgo }, ex
+            );
+        }
+        return cipher;
+    }
+
+    /**
+     * Fetch the result of a given action from a given result vector <p/>
+     * 
+     * @param wsResultVector
+     *            The result vector to fetch an action from
+     * @param action
+     *            The action to fetch
+     * @return The result fetched from the result vector, null if the result
+     *         could not be found
+     */
+    public static WSSecurityEngineResult fetchActionResult(
+            Vector wsResultVector, int action) {
+        WSSecurityEngineResult wsResult = null;
+
+        // Find the part of the security result that matches the given action
+
+        for (int i = 0; i < wsResultVector.size(); i++) {
+            // Check the result of every action whether it matches the given
+            // action
+            WSSecurityEngineResult result = 
+                (WSSecurityEngineResult) wsResultVector.get(i);
+            int resultAction = 
+                ((java.lang.Integer)result.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
+            if (resultAction == action) {
+                wsResult = (WSSecurityEngineResult) wsResultVector.get(i);
+            }
+        }
+
+        return wsResult;
+    }
+
+    /**
+     * Fetch the result of a given action from a given result vector <p/>
+     * 
+     * @param wsResultVector
+     *            The result vector to fetch an action from
+     * @param action
+     *            The action to fetch
+     * @param results
+     *            where to store the found results data for the action
+     * @return The result fetched from the result vector, null if the result
+     *         could not be found
+     */
+    public static Vector fetchAllActionResults(Vector wsResultVector,
+            int action, Vector results) {
+
+        // Find the parts of the security result that matches the given action
+        for (int i = 0; i < wsResultVector.size(); i++) {
+            // Check the result of every action whether it matches the given
+            // action
+            WSSecurityEngineResult result = 
+                (WSSecurityEngineResult) wsResultVector.get(i);
+            int resultAction = 
+                ((java.lang.Integer)result.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
+            if (resultAction == action) {
+                results.add(wsResultVector.get(i));
+            }
+        }
+        return results;
+    }
+
+    static public int decodeAction(String action, Vector actions)
+            throws WSSecurityException {
+
+        int doAction = 0;
+
+        if (action == null) {
+            return doAction;
+        }
+        String single[] = StringUtil.split(action, ' ');
+        for (int i = 0; i < single.length; i++) {
+            if (single[i].equals(WSHandlerConstants.NO_SECURITY)) {
+                doAction = WSConstants.NO_SECURITY;
+                return doAction;
+            } else if (single[i].equals(WSHandlerConstants.USERNAME_TOKEN)) {
+                doAction |= WSConstants.UT;
+                actions.add(new Integer(WSConstants.UT));
+            } else if (single[i].equals(WSHandlerConstants.SIGNATURE)) {
+                doAction |= WSConstants.SIGN;
+                actions.add(new Integer(WSConstants.SIGN));
+            } else if (single[i].equals(WSHandlerConstants.ENCRYPT)) {
+                doAction |= WSConstants.ENCR;
+                actions.add(new Integer(WSConstants.ENCR));
+            } else if (single[i].equals(WSHandlerConstants.SAML_TOKEN_UNSIGNED)) {
+                doAction |= WSConstants.ST_UNSIGNED;
+                actions.add(new Integer(WSConstants.ST_UNSIGNED));
+            } else if (single[i].equals(WSHandlerConstants.SAML_TOKEN_SIGNED)) {
+                doAction |= WSConstants.ST_SIGNED;
+                actions.add(new Integer(WSConstants.ST_SIGNED));
+            } else if (single[i].equals(WSHandlerConstants.TIMESTAMP)) {
+                doAction |= WSConstants.TS;
+                actions.add(new Integer(WSConstants.TS));
+            } else if (single[i].equals(WSHandlerConstants.NO_SERIALIZATION)) {
+                doAction |= WSConstants.NO_SERIALIZE;
+                actions.add(new Integer(WSConstants.NO_SERIALIZE));
+            } else if (single[i].equals(WSHandlerConstants.SIGN_WITH_UT_KEY)) {
+                doAction |= WSConstants.UT_SIGN;
+                actions.add(new Integer(WSConstants.UT_SIGN));
+            } else {
+                throw new WSSecurityException(
+                        "WSDoAllSender: Unknown action defined" + single[i]);
+            }
+        }
+        return doAction;
+    }
+
+    /**
+     * Returns the length of the key in # of bytes
+     * 
+     * @param algorithm
+     * @return the key length
+     */
+    public static int getKeyLength(String algorithm) throws WSSecurityException {
+        if (algorithm.equals(WSConstants.TRIPLE_DES)) {
+            return 24;
+        } else if (algorithm.equals(WSConstants.AES_128)) {
+            return 16;
+        } else if (algorithm.equals(WSConstants.AES_192)) {
+            return 24;
+        } else if (algorithm.equals(WSConstants.AES_256)) {
+            return 32;
+        } else if (XMLSignature.ALGO_ID_MAC_HMAC_SHA1.equals(algorithm)) {
+            return 20;
+        } else if (XMLSignature.ALGO_ID_MAC_HMAC_SHA256.equals(algorithm)) {
+            return 32;
+        } else if (XMLSignature.ALGO_ID_MAC_HMAC_SHA384.equals(algorithm)) {
+            return 48;
+        } else if (XMLSignature.ALGO_ID_MAC_HMAC_SHA512.equals(algorithm)) {
+            return 64;
+        } else if (XMLSignature.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5
+                .equals(algorithm)) {
+            return 16;
+        } else {
+            throw new WSSecurityException(
+                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, null);
+        }
+    }
+
+    /**
+     * Generate a nonce of the given length
+     * 
+     * @return a nonce of the given length
+     * @throws Exception
+     */
+    public static byte[] generateNonce(int length) throws WSSecurityException {
+        try {            
+            final SecureRandom r = resolveSecureRandom();
+            if (r == null) {
+                throw new WSSecurityException("Random generator is not initialzed.");
+            }
+            byte[] temp = new byte[length];            
+            r.nextBytes(temp);
+            return temp;
+        } catch (Exception e) {
+            throw new WSSecurityException(
+                    "Error in generating nonce of length " + length, e);
+        }
+    }
+
+    /**
+     * Search through a WSS4J results vector for a single signature covering all
+     * these elements.
+     * 
+     * NOTE: it is important that the given elements are those that are 
+     * referenced using wsu:Id. When the signed element is referenced using a
+     * transformation such as XPath filtering the validation is carried out 
+     * in signature verification itself.
+     * 
+     * @param results
+     *            results (e.g., as stored as WSHandlerConstants.RECV_RESULTS on
+     *            an Axis MessageContext)
+     * @param elements
+     *            the elements to check
+     * @return the identity of the signer
+     * @throws WSSecurityException
+     *             if no suitable signature could be found or if any element
+     *             didn't have a wsu:Id attribute
+     */
+    public static X509Certificate ensureSignedTogether(Iterator results,
+            Element[] elements) throws WSSecurityException {
+        log.debug("ensureSignedTogether()");
+
+        if (results == null)
+            throw new IllegalArgumentException("No results vector");
+        if (elements == null || elements.length == 0)
+            throw new IllegalArgumentException("No elements to check!");
+
+        // Turn the list of required elements into a list of required wsu:Id
+        // strings
+        String[] requiredIDs = new String[elements.length];
+        for (int i = 0; i < elements.length; i++) {
+            Element e = (Element) elements[i];
+            if (e == null) {
+                throw new IllegalArgumentException("elements[" + i
+                        + "] is null!");
+            }
+            requiredIDs[i] = e.getAttributeNS(WSConstants.WSU_NS, "Id");
+            if (requiredIDs[i] == null) {
+                throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
+                        "requiredElementNoID", new Object[] { e.getNodeName() });
+            }
+            log.debug("Required element " + e.getNodeName() + " has wsu:Id "
+                    + requiredIDs[i]);
+        }
+
+        WSSecurityException fault = null;
+
+        // Search through the results for a SIGN result
+        while (results.hasNext()) {
+            WSHandlerResult result = (WSHandlerResult) results.next();
+            Iterator actions = result.getResults().iterator();
+
+            while (actions.hasNext()) {
+                WSSecurityEngineResult resultItem = 
+                    (WSSecurityEngineResult) actions.next();
+                int resultAction = 
+                    ((java.lang.Integer)resultItem.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
+                
+                if (resultAction == WSConstants.SIGN) {
+                    try {
+                        checkSignsAllElements(resultItem, requiredIDs);
+                        return 
+                            (X509Certificate)resultItem.get(
+                                WSSecurityEngineResult.TAG_X509_CERTIFICATE
+                            );
+                    } catch (WSSecurityException ex) {
+                        // Store the exception but keep going... there may be a
+                        // better signature later
+                        log.debug("SIGN result does not sign all required elements", ex);
+                        fault = ex;
+                    }
+                }
+            }
+        }
+
+        if (fault != null)
+            throw fault;
+
+        throw new WSSecurityException(WSSecurityException.FAILED_CHECK, "noSignResult");
+    }
+
+    /**
+     * Ensure that this signature covers all required elements (identified by
+     * their wsu:Id attributes).
+     * 
+     * @param resultItem
+     *            the signature to check
+     * @param requiredIDs
+     *            the list of wsu:Id values that must be covered
+     * @throws WSSecurityException
+     *             if any required element is not included
+     */
+    private static void checkSignsAllElements(
+            WSSecurityEngineResult resultItem, String[] requiredIDs)
+            throws WSSecurityException {
+        int resultAction = 
+            ((java.lang.Integer)resultItem.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
+        if (resultAction != WSConstants.SIGN) {
+            throw new IllegalArgumentException("Not a SIGN result");
+        }
+
+        Set sigElems = (Set)resultItem.get(WSSecurityEngineResult.TAG_SIGNED_ELEMENT_IDS);
+        if (sigElems == null) {
+            throw new RuntimeException(
+                    "Missing signedElements set in WSSecurityEngineResult!");
+        }
+
+        log.debug("Found SIGN result...");
+        for (Iterator i = sigElems.iterator(); i.hasNext();) {
+            Object sigElement = i.next();
+            if(sigElement instanceof String) {
+                log.debug("Signature includes element with ID " + sigElement);
+            } else {
+                log.debug("Signature includes element with null uri " + 
+                        sigElement.toString());
+            }
+        }
+
+        log.debug("Checking required elements are in the signature...");
+        for (int i = 0; i < requiredIDs.length; i++) {
+            if (!sigElems.contains(requiredIDs[i])) {
+                throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
+                        "requiredElementNotSigned",
+                        new Object[] { requiredIDs[i] });
+            }
+            log.debug("Element with ID " + requiredIDs[i]
+                    + " was correctly signed");
+        }
+        log.debug("All required elements are signed");
+    }
+    
+    /**
+     * @return      a SecureRandom instance initialized with the "SHA1PRNG"
+     *              algorithm identifier
+     */
+    public static SecureRandom
+    resolveSecureRandom() throws NoSuchAlgorithmException {
+        return resolveSecureRandom("SHA1PRNG");
+    }
+    
+    /**
+     * @param       algorithm
+     *              
+     *
+     * @return      a SecureRandom instance initialize with the identifier
+     *              specified in algorithm
+     */
+    public synchronized static SecureRandom
+    resolveSecureRandom(
+        final String algorithm
+    ) throws NoSuchAlgorithmException {
+        if (random == null) {
+            random = SecureRandom.getInstance(algorithm);
+            random.setSeed(System.currentTimeMillis());
+        }
+        return random;
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/util/XMLUtils.java b/trunk/src/org/apache/ws/security/util/XMLUtils.java
new file mode 100644
index 0000000..d04168c
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/XMLUtils.java
@@ -0,0 +1,87 @@
+package org.apache.ws.security.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+
+public class XMLUtils {
+    
+    private static final Log log = LogFactory.getLog(XMLUtils.class.getName());
+    private static final boolean doDebug = log.isDebugEnabled();
+    
+    public static String PrettyDocumentToString(Document doc) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ElementToStream(doc.getDocumentElement(), baos);
+        return new String(baos.toByteArray());
+    }
+
+    public static void ElementToStream(Element element, OutputStream out) {
+        try {
+            DOMSource source = new DOMSource(element);
+            StreamResult result = new StreamResult(out);
+            TransformerFactory transFactory = TransformerFactory.newInstance();
+            Transformer transformer = transFactory.newTransformer();
+            transformer.transform(source, result);
+        } catch (Exception ex) {
+            if (doDebug) {
+                log.debug(ex.getMessage(), ex);
+            }
+        }
+    }
+
+    /**
+     * Utility to get the bytes uri
+     *
+     * @param source the resource to get
+     */
+    public static InputSource sourceToInputSource(Source source) {
+        if (source instanceof SAXSource) {
+            return ((SAXSource) source).getInputSource();
+        } else if (source instanceof DOMSource) {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            Node node = ((DOMSource) source).getNode();
+            if (node instanceof Document) {
+                node = ((Document) node).getDocumentElement();
+            }
+            Element domElement = (Element) node;
+            ElementToStream(domElement, baos);
+            InputSource isource = new InputSource(source.getSystemId());
+            isource.setByteStream(new ByteArrayInputStream(baos.toByteArray()));
+            return isource;
+        } else if (source instanceof StreamSource) {
+            StreamSource ss = (StreamSource) source;
+            InputSource isource = new InputSource(ss.getSystemId());
+            isource.setByteStream(ss.getInputStream());
+            isource.setCharacterStream(ss.getReader());
+            isource.setPublicId(ss.getPublicId());
+            return isource;
+        } else {
+            return getInputSourceFromURI(source.getSystemId());
+        }
+    }
+
+    /**
+     * Utility to get the bytes uri.
+     * Does NOT handle authenticated URLs,
+     * use getInputSourceFromURI(uri, username, password)
+     *
+     * @param uri the resource to get
+     */
+    public static InputSource getInputSourceFromURI(String uri) {
+        return new InputSource(uri);
+    }
+}
diff --git a/trunk/src/org/apache/ws/security/util/XmlSchemaDateFormat.java b/trunk/src/org/apache/ws/security/util/XmlSchemaDateFormat.java
new file mode 100644
index 0000000..21c57b1
--- /dev/null
+++ b/trunk/src/org/apache/ws/security/util/XmlSchemaDateFormat.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright  2003-2005 The Apache Software Foundation.
+ *
+ *  Licensed 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.ws.security.util;
+
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A {@link DateFormat} for the format of the dateTime simpleType as specified in the
+ * XML Schema specification. See <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">
+ * XML Schema Part 2: Datatypes, W3C Recommendation 02 May 2001, Section 3.2.7.1</a>.
+ *
+ * @author Ian P. Springer
+ * @author Werner Dittmann
+ */
+public class XmlSchemaDateFormat extends DateFormat {
+    /**
+     * Logger.
+     */
+    private static Log log = LogFactory.getLog(XmlSchemaDateFormat.class);
+
+    /**
+     * Message retriever.
+     */
+    //   private static final MessageRetriever MSG = ResourceKeys.MSG;
+    /**
+     * DateFormat for Zulu (UTC) form of an XML Schema dateTime string.
+     */
+    private static final DateFormat DATEFORMAT_XSD_ZULU = new SimpleDateFormat(
+            "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+
+    static {
+        DATEFORMAT_XSD_ZULU.setTimeZone(TimeZone.getTimeZone("UTC"));
+    }
+
+    /**
+     * This method was snarfed from <tt>org.apache.axis.encoding.ser.CalendarDeserializer</tt>,
+     * which was written by Sam Ruby (rubys@us.ibm.com) and Rich Scheuerle (scheu@us.ibm.com).
+     * Better error reporting was added.
+     *
+     * @see DateFormat#parse(java.lang.String)
+     */
+    public Date parse(String src, ParsePosition parse_pos) {
+        Date date;
+
+        // validate fixed portion of format
+        int index = 0;
+        try {
+            if (src != null) {
+                if ((src.charAt(0) == '+') || (src.charAt(0) == '-')) {
+                    src = src.substring(1);
+                }
+
+                if (src.length() < 19) {
+                    parse_pos.setIndex(src.length() - 1);
+                    handleParseError(parse_pos, "TOO_FEW_CHARS");
+                }
+                validateChar(src, parse_pos, index = 4, '-', "EXPECTED_DASH");
+                validateChar(src, parse_pos, index = 7, '-', "EXPECTED_DASH");
+                validateChar(src, parse_pos, index = 10, 'T', "EXPECTED_CAPITAL_T");
+                validateChar(src, parse_pos, index = 13, ':', "EXPECTED_COLON_IN_TIME");
+                validateChar(src, parse_pos, index = 16, ':', "EXPECTED_COLON_IN_TIME");
+            }
+
+            // convert what we have validated so far
+            try {
+                synchronized (DATEFORMAT_XSD_ZULU) {
+                    date = DATEFORMAT_XSD_ZULU.parse((src == null) ? null
+                            : (src.substring(0, 19) + ".000Z"));
+                }
+            } catch (Exception e) {
+                throw new NumberFormatException(e.toString());
+            }
+
+            index = 19;
+
+            // parse optional milliseconds
+            if (src != null) {
+                if ((index < src.length()) && (src.charAt(index) == '.')) {
+                    int milliseconds = 0;
+                    int start = ++index;
+
+                    while ((index < src.length())
+                            && Character.isDigit(src.charAt(index))) {
+                        index++;
+                    }
+
+                    String decimal = src.substring(start, index);
+
+                    if (decimal.length() == 3) {
+                        milliseconds = Integer.parseInt(decimal);
+                    } else if (decimal.length() < 3) {
+                        milliseconds = Integer.parseInt((decimal + "000")
+                                .substring(0, 3));
+                    } else {
+                        milliseconds = Integer
+                                .parseInt(decimal.substring(0, 3));
+
+                        if (decimal.charAt(3) >= '5') {
+                            ++milliseconds;
+                        }
+                    }
+
+                    // add milliseconds to the current date
+                    date.setTime(date.getTime() + milliseconds);
+                }
+
+                // parse optional timezone
+                if (((index + 5) < src.length())
+                        && ((src.charAt(index) == '+') || (src.charAt(index) == '-'))) {
+                    validateCharIsDigit(src, parse_pos, index + 1, "EXPECTED_NUMERAL");
+                    validateCharIsDigit(src, parse_pos, index + 2, "EXPECTED_NUMERAL");
+                    validateChar(src, parse_pos, index + 3, ':', "EXPECTED_COLON_IN_TIMEZONE");
+                    validateCharIsDigit(src, parse_pos, index + 4, "EXPECTED_NUMERAL");
+                    validateCharIsDigit(src, parse_pos, index + 5, "EXPECTED_NUMERAL");
+
+                    final int hours = (((src.charAt(index + 1) - '0') * 10) + src
+                            .charAt(index + 2)) - '0';
+                    final int mins = (((src.charAt(index + 4) - '0') * 10) + src
+                            .charAt(index + 5)) - '0';
+                    int millisecs = ((hours * 60) + mins) * 60 * 1000;
+
+                    // subtract millisecs from current date to obtain GMT
+                    if (src.charAt(index) == '+') {
+                        millisecs = -millisecs;
+                    }
+
+                    date.setTime(date.getTime() + millisecs);
+                    index += 6;
+                }
+
+                if ((index < src.length()) && (src.charAt(index) == 'Z')) {
+                    index++;
+                }
+
+                if (index < src.length()) {
+                    handleParseError(parse_pos, "TOO_MANY_CHARS");
+                }
+            }
+        } catch (ParseException pe) {
+            log.error(pe.toString(), pe);
+            index = 0; // IMPORTANT: this tells DateFormat.parse() to throw a ParseException
+            parse_pos.setErrorIndex(index);
+            date = null;
+        }
+        parse_pos.setIndex(index);
+        return (date);
+    }
+
+    /**
+     * @see DateFormat#format(java.util.Date)
+     */
+    public StringBuffer format(Date date, StringBuffer append_buf,
+            FieldPosition field_pos) {
+        String str;
+
+        synchronized (DATEFORMAT_XSD_ZULU) {
+            str = DATEFORMAT_XSD_ZULU.format(date);
+        }
+
+        if (append_buf == null) {
+            append_buf = new StringBuffer();
+        }
+
+        append_buf.append(str);
+
+        return (append_buf);
+    }
+
+    private void validateChar(String str, ParsePosition parse_pos, int index,
+            char expected, String error_reason) throws ParseException {
+        if (str.charAt(index) != expected) {
+            handleParseError(parse_pos, error_reason);
+        }
+    }
+
+    private void validateCharIsDigit(String str, ParsePosition parse_pos,
+            int index, String error_reason) throws ParseException {
+        if (!Character.isDigit(str.charAt(index))) {
+            handleParseError(parse_pos, error_reason);
+        }
+    }
+
+    private void handleParseError(ParsePosition parse_pos, String error_reason)
+            throws ParseException {
+        throw new ParseException("INVALID_XSD_DATETIME", parse_pos.getErrorIndex());
+    }
+
+}
diff --git a/trunk/test/components/PackageTests.java b/trunk/test/components/PackageTests.java
new file mode 100644
index 0000000..d5b135a
--- /dev/null
+++ b/trunk/test/components/PackageTests.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 components;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test package for WS-Security tests
+ */
+public class PackageTests extends TestCase {
+
+    public PackageTests(String name) {
+        super(name);
+    }
+
+    public static Test suite() {
+        TestSuite suite = new TestSuite();
+        suite.addTestSuite(TestMerlin.class);
+        suite.addTestSuite(TestX509NameTokenizer.class);
+        suite.addTestSuite(TestReference.class);
+        suite.addTestSuite(TestWSSecurityUtil.class);
+        return suite;
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+}
diff --git a/trunk/test/components/TestMerlin.java b/trunk/test/components/TestMerlin.java
new file mode 100644
index 0000000..2f27b42
--- /dev/null
+++ b/trunk/test/components/TestMerlin.java
@@ -0,0 +1,60 @@
+package components;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.ws.security.components.crypto.AbstractCrypto;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: srida01
+ * Date: Apr 12, 2004
+ * Time: 10:50:05 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class TestMerlin extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestMerlin(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestMerlin.class);
+    }
+
+    public void testCrypto() {
+        Crypto crypto = CryptoFactory.getInstance();
+        assertTrue(crypto != null);
+    }
+
+    public void testAbstractCryptoWithNullProperties() 
+        throws Exception {
+        Crypto crypto = new NullPropertiesCrypto();
+        assertTrue(crypto != null);
+    }
+    
+    /**
+     * WSS-102 -- ensure AbstractCrypto will null properties
+     * can be instantiated
+     */
+    private static class NullPropertiesCrypto extends AbstractCrypto {
+    
+        public NullPropertiesCrypto() 
+            throws Exception {
+            super((java.util.Properties) null);
+        }
+    }
+}
diff --git a/trunk/test/components/TestReference.java b/trunk/test/components/TestReference.java
new file mode 100644
index 0000000..6600067
--- /dev/null
+++ b/trunk/test/components/TestReference.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright The Apache Software Foundation.
+ *
+ *  Licensed 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 components;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.message.token.Reference;
+
+/**
+ * unit test for the Reference type
+ */
+public class TestReference extends TestCase {
+
+    private static final String 
+    TEST_REFERENCE_TEMPLATE = 
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+        +   "<wss:Reference "
+        +       "xmlns:wss=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" "
+        +       "ValueType=\"TheValueType\" "
+        +       "URI=\"TheURI\" "
+        +       "/>"
+        ;
+
+    private static final String 
+    BOGUS_REFERENCE_TEMPLATE = 
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+        +   "<wss:Reference "
+        +       "xmlns:wss=\"http://something-completely-different\" "
+        +       "ValueType=\"TheValueType\" "
+        +       "URI=\"TheURI\" "
+        +       "/>"
+        ;
+
+
+    public TestReference(String name) {
+        super(name);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestReference.class);
+    }
+    
+    
+    public void
+    testConstructor() throws Exception {
+        //
+        // null input
+        //
+        try {
+            new Reference((org.w3c.dom.Element) null);
+            fail("Expected failure on null Element passed to ctor");
+        } catch (final WSSecurityException e) {
+            // complete
+        }
+        //
+        // The XML doesn't conform to the WSS namespace
+        //
+        try {
+            new Reference(
+                createReferenceDocument(
+                    BOGUS_REFERENCE_TEMPLATE,
+                    "foo", "bar"
+                ).getDocumentElement()
+            );
+            fail("Expected failure on bogus template");
+        } catch (final Exception e) {
+            // complete
+        }
+        //
+        // create a Reference from valid XML
+        //
+        new Reference(
+            createReferenceDocument(
+                TEST_REFERENCE_TEMPLATE,
+                "foo", "bar"
+            )
+        );
+        new Reference(
+            createReferenceDocument(
+                TEST_REFERENCE_TEMPLATE,
+                "foo", "bar"
+            ).getDocumentElement()
+        );
+    }
+    
+    public void
+    testAccessors() throws Exception {
+        final Reference ref = new Reference(
+            createReferenceDocument(
+                TEST_REFERENCE_TEMPLATE,
+                "foo", "bar"
+            ).getDocumentElement()
+        );
+        assertEquals(ref.getValueType(), "foo");
+        assertEquals(ref.getURI(), "bar");
+    }
+    
+    private static org.w3c.dom.Document
+    createReferenceDocument(
+        final String template,
+        final String valueType,
+        final String uri
+    ) throws javax.xml.parsers.ParserConfigurationException,
+             org.xml.sax.SAXException,
+             java.io.IOException {
+        final java.io.InputStream in = 
+            new java.io.ByteArrayInputStream(
+                template.replaceFirst(
+                    "TheValueType", valueType
+                ).replaceFirst(
+                    "TheURI", uri
+                ).getBytes()
+            );
+        final javax.xml.parsers.DocumentBuilderFactory factory = 
+            javax.xml.parsers.DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        final javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
+        return builder.parse(in);
+    }
+}
diff --git a/trunk/test/components/TestWSSecurityUtil.java b/trunk/test/components/TestWSSecurityUtil.java
new file mode 100644
index 0000000..787db28
--- /dev/null
+++ b/trunk/test/components/TestWSSecurityUtil.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright The Apache Software Foundation.
+ *
+ *  Licensed 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 components;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.ws.security.util.WSSecurityUtil;
+
+/**
+ *
+ */
+public class TestWSSecurityUtil extends TestCase {
+
+    public TestWSSecurityUtil(String name) {
+        super(name);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityUtil.class);
+    }
+    
+    
+    public void
+    testResolveSecureRandom() throws java.lang.Exception {
+        //
+        // Expect failure on bogus algorithm id
+        //
+        try {
+            WSSecurityUtil.resolveSecureRandom("no-such-algorithm");
+            fail("Expected failure on resolveSecureRandom");
+        } catch (final NoSuchAlgorithmException e) {
+            // complete
+        }
+        //
+        // Test 
+        //
+        final SecureRandom r1 = WSSecurityUtil.resolveSecureRandom();
+        assertNotNull(r1);
+        final SecureRandom r2 = WSSecurityUtil.resolveSecureRandom();
+        assertSame(r1, r2);
+    }
+}
diff --git a/trunk/test/components/TestX509NameTokenizer.java b/trunk/test/components/TestX509NameTokenizer.java
new file mode 100644
index 0000000..9944cb1
--- /dev/null
+++ b/trunk/test/components/TestX509NameTokenizer.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright The Apache Software Foundation.
+ *
+ *  Licensed 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 components;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.ws.security.components.crypto.X509NameTokenizer;
+
+/**
+ *
+ */
+public class TestX509NameTokenizer extends TestCase {
+
+    public TestX509NameTokenizer(String name) {
+        super(name);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TestX509NameTokenizer.class);
+    }
+
+    public void 
+    testEmptyX509NameTokenizer() {
+        checkEmpty(new X509NameTokenizer(""));
+        checkEmpty(new X509NameTokenizer("  "));
+        checkEmpty(new X509NameTokenizer(" \t \n  \r\n"));
+    }
+    
+    public void 
+    testWellFormedX509NameTokenizer() {
+        checkTokenizer(
+            new X509NameTokenizer("foo"), 
+            new String[] { "foo" }
+        );
+        checkTokenizer(
+            new X509NameTokenizer(" foo   "), 
+            new String[] { "foo" }
+        );
+        checkTokenizer(
+            new X509NameTokenizer(" foo,   "), 
+            new String[] { "foo", "" }
+        );
+        checkTokenizer(
+            new X509NameTokenizer(" foo\\,   "), 
+            new String[] { "foo\\,"}
+        );
+        checkTokenizer(
+            new X509NameTokenizer(" foo\\,   bar  "), 
+            new String[] { "foo\\,   bar"}
+        );
+        checkTokenizer(
+            new X509NameTokenizer(" \"foo,\"   "), 
+            new String[] { "\"foo,\""}
+        );
+        checkTokenizer(
+            new X509NameTokenizer("foo, bar"), 
+            new String[] { "foo", "bar"}
+        );
+        checkTokenizer(
+            new X509NameTokenizer("\"foo bar\", gnu gnat"), 
+            new String[] { "\"foo bar\"", "gnu gnat"}
+        );
+        checkTokenizer(
+            new X509NameTokenizer("foo\\ "), 
+            new String[] { "foo\\ "}
+        );
+        checkTokenizer(
+            new X509NameTokenizer("foo\\\\ "), 
+            new String[] { "foo\\\\"}
+        );
+    }
+    
+    private void
+    checkEmpty(
+        final X509NameTokenizer tokenizer
+    ) {
+        checkTokenizer(
+            tokenizer, new String[0]
+        );
+    }
+    
+    private void
+    checkTokenizer(
+        final X509NameTokenizer tokenizer,
+        final String[] expected
+    ) {
+        for (int i = 0;  i < expected.length;  ++i) {
+            assertTrue(tokenizer.hasMoreTokens());
+            assertEquals(tokenizer.nextToken(), expected[i]);
+        }
+        assertTrue(!tokenizer.hasMoreTokens());
+        assertEquals(tokenizer.nextToken(), "");
+    }
+}
diff --git a/trunk/test/crypto.properties b/trunk/test/crypto.properties
new file mode 100644
index 0000000..9a18040
--- /dev/null
+++ b/trunk/test/crypto.properties
@@ -0,0 +1,6 @@
+org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+org.apache.ws.security.crypto.merlin.keystore.type=pkcs12
+org.apache.ws.security.crypto.merlin.keystore.password=security
+org.apache.ws.security.crypto.merlin.keystore.alias=16c73ab6-b892-458f-abf5-2f875f74882e
+org.apache.ws.security.crypto.merlin.alias.password=security
+org.apache.ws.security.crypto.merlin.file=keys/x509.PFX.MSFT
diff --git a/trunk/test/cryptoSKI.properties b/trunk/test/cryptoSKI.properties
new file mode 100644
index 0000000..014562c
--- /dev/null
+++ b/trunk/test/cryptoSKI.properties
@@ -0,0 +1,4 @@
+org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+org.apache.ws.security.crypto.merlin.keystore.type=jks
+org.apache.ws.security.crypto.merlin.keystore.password=security
+org.apache.ws.security.crypto.merlin.file=keys/wss4j.keystore
diff --git a/trunk/test/interop/PackageTests.java b/trunk/test/interop/PackageTests.java
new file mode 100644
index 0000000..b43ce0b
--- /dev/null
+++ b/trunk/test/interop/PackageTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test package for WS-Security tests
+ */
+public class PackageTests extends TestCase {
+
+    public PackageTests(String name) {
+        super(name);
+    }
+
+    public static Test suite() {
+        TestSuite suite = new TestSuite();
+        suite.addTestSuite(TestInteropKeys.class);
+        suite.addTestSuite(TestScenario1.class);
+        suite.addTestSuite(TestScenario2.class);
+        suite.addTestSuite(TestScenario2a.class);
+        suite.addTestSuite(TestScenario3.class);
+        suite.addTestSuite(TestScenario4.class);
+        suite.addTestSuite(TestScenario5.class);
+        suite.addTestSuite(TestScenario6.class); 
+        suite.addTestSuite(TestScenario7.class); 
+        suite.addTestSuite(TestSTScenario1.class);
+        suite.addTestSuite(TestSTScenario3.class);
+        suite.addTestSuite(TestSTScenario4.class);
+        return suite;
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+}
diff --git a/trunk/test/interop/TestInteropKeys.java b/trunk/test/interop/TestInteropKeys.java
new file mode 100644
index 0000000..3b087b8
--- /dev/null
+++ b/trunk/test/interop/TestInteropKeys.java
@@ -0,0 +1,57 @@
+package interop;
+
+import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+
+import java.security.cert.X509Certificate;
+import java.security.PrivateKey;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: srida01
+ * Date: Mar 15, 2004
+ * Time: 10:47:59 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class TestInteropKeys extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestInteropKeys(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestInteropKeys.class);
+    }
+
+    public void testInteropKeys1() throws Exception {
+        Crypto c = CryptoFactory.getInstance("wsstest.properties");
+        X509Certificate[] certs = c.getCertificates("alice");
+        assertTrue(certs != null);
+        assertTrue(certs[0] != null);
+        PrivateKey privKey = c.getPrivateKey("alice","password");
+        assertTrue(privKey != null);
+    }
+
+    public void testInteropKeys2() throws Exception {
+        Crypto c = CryptoFactory.getInstance("wsstest.properties");
+        X509Certificate[] certs = c.getCertificates("bob");
+        assertTrue(certs != null);
+        assertTrue(certs[0] != null);
+        PrivateKey privKey = c.getPrivateKey("bob","password");
+        assertTrue(privKey != null);
+    }
+}
diff --git a/trunk/test/interop/TestJAXRPCHandler.java b/trunk/test/interop/TestJAXRPCHandler.java
new file mode 100755
index 0000000..f5d7a90
--- /dev/null
+++ b/trunk/test/interop/TestJAXRPCHandler.java
@@ -0,0 +1,147 @@
+package interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.ping.PingPort;
+import org.apache.ws.axis.oasis.ping.PingServiceLocator;
+import org.apache.ws.security.handler.WSS4JHandler;
+
+import javax.xml.namespace.QName;
+import javax.xml.rpc.handler.HandlerInfo;
+import javax.xml.rpc.handler.HandlerRegistry;
+import javax.xml.rpc.holders.StringHolder;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TestJAXRPCHandler extends TestCase {
+    /**
+     * @param name name of the test
+     */
+    public TestJAXRPCHandler(String name) {
+        super(name);
+    }
+
+    /**
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestJAXRPCHandler.class);
+    }
+
+    public void testScenario1() throws Exception {
+        Map config = new HashMap();
+        config.put("deployment", "client");
+        config.put("flow", "request-only");
+        config.put("action", "UsernameToken");
+        config.put("user", "Chris");
+        config.put("passwordType", "PasswordText");
+        config.put("passwordCallbackClass", "org.apache.ws.axis.oasis.PWCallback1");
+        invokeService (config, 1);
+    }
+    public void testScenario2() throws Exception {
+        Map config = new HashMap();
+        config.put("deployment", "client");
+        config.put("flow", "request-only");
+        config.put("user", "Chris");
+        config.put("passwordType", "PasswordText");
+        config.put("action", "UsernameToken Encrypt");
+        config.put("addUTElements", "Nonce Created");
+        config.put("encryptionPropFile", "wsstest.properties");
+        config.put("encryptionKeyIdentifier", "SKIKeyIdentifier");
+        config.put("encryptionUser", "bob");
+        config.put("passwordCallbackClass", "org.apache.ws.axis.oasis.PWCallback1");
+        config.put("encryptionParts", "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken");  
+        invokeService (config, 2);
+    }
+    public void testScenario3() throws Exception {
+        Map config = new HashMap();
+        config.put("deployment", "client");
+        config.put("action", "Signature Encrypt Timestamp");
+        config.put("user", "alice");
+        config.put("passwordCallbackClass", "org.apache.ws.axis.oasis.PWCallback1");
+        config.put("signatureKeyIdentifier", "DirectReference");
+        config.put("signaturePropFile", "wsstest.properties");
+        config.put("encryptionKeyIdentifier", "SKIKeyIdentifier");
+        config.put("encryptionUser", "bob");
+        invokeService (config, 3);
+    }
+    public void testScenario4() throws Exception {
+        Map config = new HashMap();
+        config.put("deployment", "client");
+        config.put("action", "Signature Encrypt Timestamp");
+        config.put("user", "alice");
+        config.put("passwordCallbackClass", "org.apache.ws.axis.oasis.PWCallback1");
+        config.put("signatureKeyIdentifier", "DirectReference");
+        config.put("signaturePropFile", "wsstest.properties");
+        config.put("encryptionKeyIdentifier", "EmbeddedKeyName");
+        config.put("encryptionSymAlgorithm", "http://www.w3.org/2001/04/xmlenc#tripledes-cbc");
+        config.put("EmbeddedKeyCallbackClass", "org.apache.ws.axis.oasis.PWCallback1");
+        config.put("EmbeddedKeyName", "SessionKey");
+        invokeService (config, 4);
+    }
+    
+    // testScenario5 - Ping5 fails because there is now way in JAXRPC to 
+    // specifiy the parameter signatureKeyIdentifier with different values 
+    // for request and response flows
+/*    public void testScenario5() throws Exception {
+        Map config = new HashMap();
+        config.put("deployment", "client");
+        config.put("action", "Signature NoSerialization");
+        config.put("user", "alice");
+        config.put("passwordCallbackClass", "org.apache.ws.axis.oasis.PWCallback1");
+        config.put("signatureKeyIdentifier", "DirectReference");
+        config.put("signaturePropFile", "wsstest.properties");
+        config.put("signatureParts", "{}{http://xmlsoap.org/Ping}ticket");
+        invokeService (config, 5);
+    }
+*/    public void testScenario6() throws Exception {
+        Map config = new HashMap();
+        config.put("deployment", "client");
+        config.put("action", "Encrypt Signature Timestamp");
+        config.put("user", "alice");
+        config.put("passwordCallbackClass", "org.apache.ws.axis.oasis.PWCallback1");
+        config.put("signatureKeyIdentifier", "DirectReference");
+        config.put("signaturePropFile", "wsstest.properties");
+        config.put("encryptionKeyIdentifier", "SKIKeyIdentifier");
+        config.put("encryptionUser", "bob");
+        invokeService (config, 6);
+    }
+    public void testScenario7() throws Exception {
+        Map config = new HashMap();
+        config.put("deployment", "client");
+        config.put("action", "Signature Encrypt Timestamp");
+        config.put("user", "alice");
+        config.put("passwordCallbackClass", "org.apache.ws.axis.oasis.PWCallback1");
+        config.put("signatureKeyIdentifier", "DirectReference");
+        config.put("signaturePropFile", "wsstest.properties");
+        config.put("encryptionKeyIdentifier", "SKIKeyIdentifier");
+        config.put("encryptionUser", "bob");
+        config.put("encryptionPropFile", "wsstest.properties");
+        config.put("signatureParts", "{}{http://schemas.xmlsoap.org/soap/envelope/}Body;STRTransform");
+        invokeService (config, 7);
+    }
+    
+    public void invokeService (Map config, int interopNum) throws Exception {
+        PingServiceLocator service = new PingServiceLocator();
+
+        List handlerChain = new ArrayList();
+        handlerChain.add(new HandlerInfo( WSS4JHandler.class, config, null));
+
+        HandlerRegistry registry = service.getHandlerRegistry();
+        registry.setHandlerChain(new QName("Ping" + interopNum), handlerChain);
+
+        service.getHandlerRegistry().getHandlerChain(new QName("http://xmlsoap.org/Ping", "ticketType"));
+        
+        java.lang.reflect.Method method = service.getClass().getMethod("getPing" + interopNum, new Class[] {URL.class});
+
+        PingPort port = (PingPort) method.invoke (service, new Object[] {new URL("http://localhost:8080/axis/services/Ping" + interopNum)});
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario" + interopNum + " @ [" + new java.util.Date(System.currentTimeMillis()) + "]");
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J" + interopNum), text);
+        System.out.println(text.value);
+    }
+}
diff --git a/trunk/test/interop/TestSTScenario1.java b/trunk/test/interop/TestSTScenario1.java
new file mode 100644
index 0000000..2b052ee
--- /dev/null
+++ b/trunk/test/interop/TestSTScenario1.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.STScenario1;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestSTScenario1 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestSTScenario1(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestSTScenario1.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        STScenario1.main(args);
+    }
+
+    public void testSTScenario1() throws Exception {
+        STScenario1.main(new String[]{"-lhttp://localhost:8080/axis/services/STPing1"});
+    }
+}
diff --git a/trunk/test/interop/TestSTScenario2.java b/trunk/test/interop/TestSTScenario2.java
new file mode 100644
index 0000000..5bcdded
--- /dev/null
+++ b/trunk/test/interop/TestSTScenario2.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.STScenario1;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestSTScenario2 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestSTScenario2(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestSTScenario2.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        STScenario1.main(args);
+    }
+
+    public void testSTScenario1() throws Exception {
+        STScenario1.main(new String[]{"-lhttp://localhost:8080/axis/services/STPing1"});
+    }
+}
diff --git a/trunk/test/interop/TestSTScenario3.java b/trunk/test/interop/TestSTScenario3.java
new file mode 100644
index 0000000..b772e12
--- /dev/null
+++ b/trunk/test/interop/TestSTScenario3.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.STScenario3;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestSTScenario3 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestSTScenario3(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestSTScenario3.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        STScenario3.main(args);
+    }
+
+    public void testSTScenario3() throws Exception {
+        STScenario3.main(new String[]{"-lhttp://localhost:8080/axis/services/STPing3"});
+    }
+}
diff --git a/trunk/test/interop/TestSTScenario4.java b/trunk/test/interop/TestSTScenario4.java
new file mode 100644
index 0000000..96a5e7a
--- /dev/null
+++ b/trunk/test/interop/TestSTScenario4.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.STScenario4;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestSTScenario4 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestSTScenario4(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestSTScenario4.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        STScenario4.main(args);
+    }
+
+    public void testSTScenario4() throws Exception {
+        STScenario4.main(new String[]{"-lhttp://localhost:8080/axis/services/STPing4"});
+    }
+}
diff --git a/trunk/test/interop/TestScenario1.java b/trunk/test/interop/TestScenario1.java
new file mode 100644
index 0000000..f9cd7ed
--- /dev/null
+++ b/trunk/test/interop/TestScenario1.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.Scenario1;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestScenario1 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestScenario1(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestScenario1.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        Scenario1.main(args);
+    }
+
+    public void testScenario1() throws Exception {
+        Scenario1.main(new String[]{"-lhttp://localhost:8080/axis/services/Ping1"});
+    }
+}
diff --git a/trunk/test/interop/TestScenario2.java b/trunk/test/interop/TestScenario2.java
new file mode 100644
index 0000000..d138968
--- /dev/null
+++ b/trunk/test/interop/TestScenario2.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.Scenario2;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestScenario2 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestScenario2(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestScenario2.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        Scenario2.main(args);
+    }
+
+    public void testScenario2() throws Exception {
+        Scenario2.main(new String[]{"-lhttp://localhost:8080/axis/services/Ping2"});
+    }
+}
diff --git a/trunk/test/interop/TestScenario2a.java b/trunk/test/interop/TestScenario2a.java
new file mode 100644
index 0000000..7fd5a84
--- /dev/null
+++ b/trunk/test/interop/TestScenario2a.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.Scenario2a;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestScenario2a extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestScenario2a(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestScenario2a.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        Scenario2a.main(args);
+    }
+
+    public void testScenario2a() throws Exception {
+        Scenario2a.main(new String[]{"-lhttp://localhost:8080/axis/services/Ping2a"});
+    }
+}
diff --git a/trunk/test/interop/TestScenario2b.java b/trunk/test/interop/TestScenario2b.java
new file mode 100644
index 0000000..0824c11
--- /dev/null
+++ b/trunk/test/interop/TestScenario2b.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.Scenario2b;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestScenario2b extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestScenario2b(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestScenario2b.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        Scenario2b.main(args);
+    }
+
+    public void testScenario2b() throws Exception {
+        Scenario2b.main(new String[]{"-lhttp://localhost:8080/axis/services/Ping2b"});
+    }
+}
diff --git a/trunk/test/interop/TestScenario3.java b/trunk/test/interop/TestScenario3.java
new file mode 100644
index 0000000..ba208c0
--- /dev/null
+++ b/trunk/test/interop/TestScenario3.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.Scenario3;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestScenario3 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestScenario3(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestScenario3.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+         Scenario3.main(args);
+    }
+
+    public void testScenario3() throws Exception {
+        Scenario3.main(new String[]{"-lhttp://localhost:8080/axis/services/Ping3"});
+    }
+}
diff --git a/trunk/test/interop/TestScenario4.java b/trunk/test/interop/TestScenario4.java
new file mode 100644
index 0000000..dc2ae07
--- /dev/null
+++ b/trunk/test/interop/TestScenario4.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.Scenario4;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestScenario4 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestScenario4(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestScenario4.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        Scenario4.main(args);
+    }
+
+    public void testScenario4() throws Exception {
+        Scenario4.main(new String[]{"-lhttp://localhost:8080/axis/services/Ping4"});
+    }
+}
diff --git a/trunk/test/interop/TestScenario5.java b/trunk/test/interop/TestScenario5.java
new file mode 100644
index 0000000..c192af8
--- /dev/null
+++ b/trunk/test/interop/TestScenario5.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.Scenario5;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestScenario5 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestScenario5(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestScenario5.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        Scenario5.main(args);
+    }
+
+    public void testScenario5() throws Exception {
+        Scenario5.main(new String[]{"-lhttp://localhost:8080/axis/services/Ping5"});
+    }
+}
diff --git a/trunk/test/interop/TestScenario6.java b/trunk/test/interop/TestScenario6.java
new file mode 100644
index 0000000..77007bc
--- /dev/null
+++ b/trunk/test/interop/TestScenario6.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.Scenario6;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestScenario6 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestScenario6(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestScenario6.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        Scenario6.main(args);
+    }
+
+    public void testScenario6() throws Exception {
+        Scenario6.main(new String[]{"-lhttp://localhost:8080/axis/services/Ping6"});
+    }
+}
diff --git a/trunk/test/interop/TestScenario7.java b/trunk/test/interop/TestScenario7.java
new file mode 100644
index 0000000..c327994
--- /dev/null
+++ b/trunk/test/interop/TestScenario7.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 interop;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.ws.axis.oasis.Scenario7;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestScenario7 extends TestCase {
+    /**
+     * TestScenario1 constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestScenario7(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestScenario7.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) throws Exception {
+        Scenario7.main(args);
+    }
+
+    public void testScenario7() throws Exception {
+        Scenario7.main(new String[]{"-lhttp://localhost:8080/axis/services/Ping7"});
+    }
+}
diff --git a/trunk/test/nofile.properties b/trunk/test/nofile.properties
new file mode 100644
index 0000000..5644422
--- /dev/null
+++ b/trunk/test/nofile.properties
@@ -0,0 +1,5 @@
+org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+org.apache.ws.security.crypto.merlin.keystore.type=pkcs12
+org.apache.ws.security.crypto.merlin.keystore.password=security
+org.apache.ws.security.crypto.merlin.keystore.alias=16c73ab6-b892-458f-abf5-2f875f74882e
+org.apache.ws.security.crypto.merlin.alias.password=security
diff --git a/trunk/test/saml.properties b/trunk/test/saml.properties
new file mode 100644
index 0000000..f4cf83f
--- /dev/null
+++ b/trunk/test/saml.properties
@@ -0,0 +1,12 @@
+org.apache.ws.security.saml.issuerClass=org.apache.ws.security.saml.SAMLIssuerImpl
+org.apache.ws.security.saml.issuer.cryptoProp.file=crypto.properties
+org.apache.ws.security.saml.issuer.key.name=16c73ab6-b892-458f-abf5-2f875f74882e
+org.apache.ws.security.saml.issuer.key.password=security
+org.apache.ws.security.saml.issuer=www.example.com
+org.apache.ws.security.saml.subjectNameId.name=uid=joe,ou=people,ou=saml-demo,o=example.com
+org.apache.ws.security.saml.subjectNameId.qualifier=www.example.com
+org.apache.ws.security.saml.authenticationMethod=password
+org.apache.ws.security.saml.confirmationMethod=senderVouches
+#org.apache.ws.security.saml.confirmationMethod=keyHolder
+#org.apache.ws.security.saml
+#org.apache.ws.security.saml
diff --git a/trunk/test/saml3.properties b/trunk/test/saml3.properties
new file mode 100644
index 0000000..b42c93c
--- /dev/null
+++ b/trunk/test/saml3.properties
@@ -0,0 +1,11 @@
+org.apache.ws.security.saml.issuer.cryptoProp.file=crypto.properties
+org.apache.ws.security.saml.issuer.key.name=16c73ab6-b892-458f-abf5-2f875f74882e
+org.apache.ws.security.saml.issuer.key.password=security
+org.apache.ws.security.saml.issuer=www.example.com
+org.apache.ws.security.saml.subjectNameId.name=uid=joe,ou=people,ou=saml-demo,o=example.com
+org.apache.ws.security.saml.subjectNameId.qualifier=www.example.com
+org.apache.ws.security.saml.authenticationMethod=password
+org.apache.ws.security.saml.confirmationMethod=senderVouches
+#org.apache.ws.security.saml.confirmationMethod=keyHolder
+#org.apache.ws.security.saml
+#org.apache.ws.security.saml
diff --git a/trunk/test/saml4.properties b/trunk/test/saml4.properties
new file mode 100644
index 0000000..3ac8d12
--- /dev/null
+++ b/trunk/test/saml4.properties
@@ -0,0 +1,12 @@
+org.apache.ws.security.saml.issuerClass=org.apache.ws.security.saml.SAMLIssuerImpl
+org.apache.ws.security.saml.issuer.cryptoProp.file=crypto.properties
+org.apache.ws.security.saml.issuer.key.name=16c73ab6-b892-458f-abf5-2f875f74882e
+org.apache.ws.security.saml.issuer.key.password=security
+org.apache.ws.security.saml.issuer=www.example.com
+org.apache.ws.security.saml.subjectNameId.name=uid=joe,ou=people,ou=saml-demo,o=example.com
+org.apache.ws.security.saml.subjectNameId.qualifier=www.example.com
+org.apache.ws.security.saml.authenticationMethod=password
+#org.apache.ws.security.saml.confirmationMethod=senderVouches
+org.apache.ws.security.saml.confirmationMethod=keyHolder
+#org.apache.ws.security.saml
+#org.apache.ws.security.saml
diff --git a/trunk/test/wssec/CustomCrypto.java b/trunk/test/wssec/CustomCrypto.java
new file mode 100644
index 0000000..c241902
--- /dev/null
+++ b/trunk/test/wssec/CustomCrypto.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import org.apache.ws.security.components.crypto.CryptoBase;
+
+public class CustomCrypto extends CryptoBase {
+    
+    java.util.Map config = null;
+    
+    public
+    CustomCrypto(
+        java.util.Map config,
+        java.lang.ClassLoader loader
+    ) {
+        this.config = config;
+    }
+
+    //
+    // org.apache.ws.security.components.crypto.Crypto implementation
+    //
+
+    public String 
+    getDefaultX509Alias() {
+        return null;
+    }
+
+    //
+    // org.apache.ws.security.components.crypto.AbstractCryptoBase
+    // implementation
+    //
+
+    protected String
+    getCryptoProvider() {
+        return null;
+    }
+}
diff --git a/trunk/test/wssec/MyAction.java b/trunk/test/wssec/MyAction.java
new file mode 100644
index 0000000..4729beb
--- /dev/null
+++ b/trunk/test/wssec/MyAction.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import org.apache.ws.security.action.Action;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.WSSecurityException;
+
+/**
+ * a custom action that leaves a breadcumb
+ */
+public class MyAction implements Action {
+    
+    public void 
+    execute(
+        WSHandler handler, 
+        int actionToDo, 
+        org.w3c.dom.Document doc,
+        RequestData reqData
+    ) throws WSSecurityException {
+        //
+        // leave a breadcrumb, if asked...
+        //
+        if (reqData.getMsgContext().equals("bread")) {
+            reqData.setMsgContext("crumb");
+        }
+    }
+}
diff --git a/trunk/test/wssec/MyProcessor.java b/trunk/test/wssec/MyProcessor.java
new file mode 100644
index 0000000..35ad43c
--- /dev/null
+++ b/trunk/test/wssec/MyProcessor.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.SecurityContextToken;
+import org.apache.ws.security.processor.Processor;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDocInfo;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSSecurityException;
+
+/**
+ * a custom processor that inserts itself into the results vector
+ */
+public class MyProcessor implements Processor {
+    
+    public final void 
+    handleToken(
+        final org.w3c.dom.Element elem, 
+        final Crypto crypto, 
+        final Crypto decCrypto,
+        final javax.security.auth.callback.CallbackHandler cb, 
+        final WSDocInfo wsDocInfo, 
+        final java.util.Vector returnResults,
+        final WSSConfig config
+    ) throws WSSecurityException {
+        final java.util.Map result = 
+            new WSSecurityEngineResult(
+                WSConstants.UT_SIGN, 
+                (SecurityContextToken) null
+            );
+        result.put("foo", this);
+        returnResults.add(result);
+    }
+
+    public final String getId() {
+        return getClass().getName();
+    }
+}
diff --git a/trunk/test/wssec/PackageTests.java b/trunk/test/wssec/PackageTests.java
new file mode 100644
index 0000000..d0b5f48
--- /dev/null
+++ b/trunk/test/wssec/PackageTests.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test package for WS-Security tests
+ */
+public class PackageTests extends TestCase {
+
+    public PackageTests(String name) {
+        super(name);
+    }
+
+    public static Test suite() {
+        TestSuite suite = new TestSuite();
+        suite.addTestSuite(TestWSSecurityNew.class);
+        suite.addTestSuite(TestWSSecurityNew2.class);
+        suite.addTestSuite(TestWSSecurityNew3.class);
+//        suite.addTestSuite(TestWSSecurity4.class);
+        suite.addTestSuite(TestWSSecurityNew5.class);
+        suite.addTestSuite(TestWSSecurityNew6.class);
+        suite.addTestSuite(TestWSSecurityNew7.class);
+        suite.addTestSuite(TestWSSecurityNew8.class);
+        suite.addTestSuite(TestWSSecurityNew9.class);
+        suite.addTestSuite(TestWSSecurityNew10.class);
+        suite.addTestSuite(TestWSSecurityNew11.class);
+        suite.addTestSuite(TestWSSecurityNew12.class);
+        suite.addTestSuite(TestWSSecurityNew13.class);
+        suite.addTestSuite(TestWSSecurityNew14.class);
+        suite.addTestSuite(TestWSSecurityNew16.class);
+        suite.addTestSuite(TestWSSecurityNew17.class);
+        suite.addTestSuite(TestWSSecurityNewSOAP12.class);
+        // suite.addTestSuite(TestWSSecurityHooks.class);
+        suite.addTestSuite(TestWSSecurityNewST1.class);
+        suite.addTestSuite(TestWSSecurityNewST2.class);
+        suite.addTestSuite(TestWSSecurityNewST3.class);
+        suite.addTestSuite(TestWSSecurityNewDK.class);
+        suite.addTestSuite(TestWSSecurityNewSCT.class);
+        suite.addTestSuite(TestWSSecurityX509v1.class);
+        suite.addTestSuite(TestWSSecurityUserProcessor.class);
+        suite.addTestSuite(TestWSSecurityFaultCodes.class);
+        suite.addTestSuite(TestWSSecurityUTDK.class);
+        suite.addTestSuite(TestWSSecurityDataRef.class);
+        suite.addTestSuite(TestWSSecurityDataRef1.class);
+        suite.addTestSuite(TestWSSecurityCertError.class);
+        return suite;
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+}
diff --git a/trunk/test/wssec/PrivilegedAccessor.java b/trunk/test/wssec/PrivilegedAccessor.java
new file mode 100644
index 0000000..bd06f52
--- /dev/null
+++ b/trunk/test/wssec/PrivilegedAccessor.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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.
+ *
+ */
+
+/*
+ * This class was taken nearly verbatim from http://junit.sourceforge.net/doc/faq/faq.htm#tests_11 
+ * I did add the setValue(Object, String, Object)
+ * Jason Essington <mailto:jasone@greenrivercomputing.com>
+ */
+package wssec;
+import java.lang.reflect.*;
+
+/**
+ * a.k.a. The "ObjectMolester"
+ * <p>
+ * This class is used to access a method or field of an object no
+ * matter what the access modifier of the method or field.  The syntax
+ * for accessing fields and methods is out of the ordinary because this
+ * class uses reflection to peel away protection.
+ * <p>
+ * Here is an example of using this to access a private member.
+ * <code>resolveName</code> is a private method of <code>Class</code>.
+ *
+ * <pre>
+ * Class c = Class.class;
+ * System.out.println(
+ *      PrivilegedAccessor.invokeMethod( c,
+ *                                       "resolveName",
+ *                                       "/net/iss/common/PrivilegeAccessor" ) );
+ * </pre>
+ *
+ * @author Charlie Hubbard (chubbard@iss.net)
+ * @author Prashant Dhokte (pdhokte@iss.net)
+ */
+
+public class PrivilegedAccessor {
+
+    /**
+     * Gets the value of the named field and returns it as an object.
+     *
+     * @param instance the object instance
+     * @param fieldName the name of the field
+     * @return an object representing the value of the field
+     */
+    public static Object getValue( Object instance, String fieldName ) 
+          throws IllegalAccessException, NoSuchFieldException {
+        Field field = getField(instance.getClass(), fieldName);
+        field.setAccessible(true);
+        return field.get(instance);
+    }
+    
+    /**
+     * Sets the value of the given field on the object instance supplied to the value supplied.
+     * @param instance the object instance
+     * @param fieldName the name of the field
+     * @param value the value to assign to the field
+     * @throws IllegalAccessException
+     * @throws NoSuchFieldException
+     */
+    public static void setValue( Object instance, String fieldName, Object value ) 
+          throws IllegalAccessException, NoSuchFieldException {
+       Field field = getField(instance.getClass(), fieldName);
+       field.setAccessible(true);
+       field.set(instance, value);
+    }
+    
+    /**
+     * Calls a method on the given object instance with the given argument.
+     *
+     * @param instance the object instance
+     * @param methodName the name of the method to invoke
+     * @param arg the argument to pass to the method
+     * @see PrivilegedAccessor#invokeMethod(Object,String,Object[])
+     */
+    public static Object invokeMethod( Object instance, String methodName, Object arg ) throws NoSuchMethodException,
+                                                         IllegalAccessException, InvocationTargetException  {
+        Object[] args = new Object[1];
+        args[0] = arg;
+        return invokeMethod(instance, methodName, args);
+    }
+
+    /**
+     * Calls a method on the given object instance with the given arguments.
+     *
+     * @param instance the object instance
+     * @param methodName the name of the method to invoke
+     * @param args an array of objects to pass as arguments
+     * @see PrivilegedAccessor#invokeMethod(Object,String,Object)
+     */
+    public static Object invokeMethod( Object instance, String methodName, Object[] args ) throws NoSuchMethodException,
+                                                             IllegalAccessException, InvocationTargetException  {
+        Class[] classTypes = null;
+        if( args != null) {
+            classTypes = new Class[args.length];
+            for( int i = 0; i < args.length; i++ ) {
+                if( args[i] != null )
+                    classTypes[i] = args[i].getClass();
+            }
+        }
+        return getMethod(instance,methodName,classTypes).invoke(instance,args);
+    }
+
+    /**
+     *
+     * @param instance the object instance
+     * @param methodName the
+     */
+    public static Method getMethod( Object instance, String methodName, Class[] classTypes ) throws NoSuchMethodException {
+        Method accessMethod = getMethod(instance.getClass(), methodName, classTypes);
+        accessMethod.setAccessible(true);
+        return accessMethod;
+    }
+
+    /**
+     * Return the named field from the given class.
+     */
+    private static Field getField(Class thisClass, String fieldName) throws NoSuchFieldException {
+        if (thisClass == null)
+            throw new NoSuchFieldException("Invalid field : " + fieldName);
+        try {
+            return thisClass.getDeclaredField( fieldName );
+        }
+        catch(NoSuchFieldException e) {
+            return getField(thisClass.getSuperclass(), fieldName);
+        }
+    }
+
+    /**
+     * Return the named method with a method signature matching classTypes
+     * from the given class.
+     */
+    private static Method getMethod(Class thisClass, String methodName, Class[] classTypes) throws NoSuchMethodException {
+        if (thisClass == null)
+            throw new NoSuchMethodException("Invalid method : " + methodName);
+        try {
+            return thisClass.getDeclaredMethod( methodName, classTypes );
+        }
+        catch(NoSuchMethodException e) {
+            return getMethod(thisClass.getSuperclass(), methodName, classTypes);
+        }
+    }
+}
diff --git a/trunk/test/wssec/SOAPUtil.java b/trunk/test/wssec/SOAPUtil.java
new file mode 100644
index 0000000..af793f6
--- /dev/null
+++ b/trunk/test/wssec/SOAPUtil.java
@@ -0,0 +1,64 @@
+package wssec;
+
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.w3c.dom.Document;
+
+import org.apache.axis.Message;
+
+import javax.xml.soap.MessageFactory;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.transform.dom.DOMSource;
+import java.io.ByteArrayInputStream;
+
+public class SOAPUtil {
+
+    /**
+     * Convert a DOM Document into a soap message.
+     * <p/>
+     *
+     * @param doc
+     * @return
+     * @throws Exception
+     */
+    public static SOAPMessage toSOAPMessage(Document doc) throws Exception {
+        Canonicalizer c14n =
+                Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
+        byte[] canonicalMessage = c14n.canonicalizeSubtree(doc);
+        ByteArrayInputStream in = new ByteArrayInputStream(canonicalMessage);
+        MessageFactory factory = MessageFactory.newInstance();
+        return factory.createMessage(null, in);
+    }
+
+    /**
+     * Convert a DOM Document into an Axis message.
+     * <p/>
+     *
+     * @param doc
+     * @return
+     * @throws Exception
+     */
+    public static Message toAxisMessage(Document doc) throws Exception {
+        Canonicalizer c14n =
+                Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
+        byte[] canonicalMessage = c14n.canonicalizeSubtree(doc);
+        ByteArrayInputStream in = new ByteArrayInputStream(canonicalMessage);
+        return new Message(in);
+    }
+
+    /**
+     * Update soap message.
+     * <p/>
+     *
+     * @param doc
+     * @param message
+     * @return
+     * @throws Exception
+     */
+    public static SOAPMessage updateSOAPMessage(Document doc,
+                                                SOAPMessage message)
+            throws Exception {
+        DOMSource domSource = new DOMSource(doc);
+        message.getSOAPPart().setContent(domSource);
+        return message;
+    }
+}
diff --git a/trunk/test/wssec/TestBase64.java b/trunk/test/wssec/TestBase64.java
new file mode 100644
index 0000000..7c257c1
--- /dev/null
+++ b/trunk/test/wssec/TestBase64.java
@@ -0,0 +1,120 @@
+/*
+ * Created on 09.09.2005
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+package wssec;
+
+import java.util.Arrays;
+import junit.framework.TestCase;
+import org.apache.ws.security.util.Base64;
+import org.apache.ws.security.WSSecurityException;
+
+public class TestBase64 extends TestCase {
+
+    private byte[] dataBinary = null;
+    
+    /*
+     * The following String is the value "This is a test\n" encoded
+     * in Base64
+     */
+    private String thisIsATestEnc = "VGhpcyBpcyBhIHRlc3QK";
+    private String thisIsATestClear = "This is a test\n";
+    private String thisIsATestEnc4group = "VGhp\ncyBp\ncyBh\nIHRl\nc3QK";
+    
+    private String encodedBinary;
+    
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(TestBase64.class);
+    }
+
+    public TestBase64(String arg0) {
+        super(arg0);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        dataBinary = new byte[256];
+        for (int i = 0; i < 256; i++) {
+            dataBinary[i] = (byte)i;
+        }
+    }
+
+    /*
+     * Class under test for String encode(byte[])
+     */
+    public void testEncodebyteArray() {
+        String isATestEnc = Base64.encode(thisIsATestClear.getBytes());
+        assertEquals(isATestEnc, thisIsATestEnc);
+
+        encodedBinary = Base64.encode(dataBinary);
+        byte[] outBinary = null;
+        try {
+            outBinary = Base64.decode(encodedBinary);
+        } catch (WSSecurityException ex) {
+
+        }
+        assertTrue(Arrays.equals(outBinary, dataBinary));
+    }
+
+    /*
+     * Class under test for String encode(byte[], int, boolean)
+     */
+    public void testEncodebyteArrayintboolean() {
+        String isATestEnc = Base64.encode(thisIsATestClear.getBytes(), 4, false);
+        assertEquals(isATestEnc, thisIsATestEnc);
+
+        isATestEnc = Base64.encode(thisIsATestClear.getBytes(), 76, false);
+        assertEquals(isATestEnc, thisIsATestEnc);
+
+        isATestEnc = Base64.encode(thisIsATestClear.getBytes(), 4, true);
+        assertEquals(isATestEnc, thisIsATestEnc4group);
+
+        isATestEnc = Base64.encode(thisIsATestClear.getBytes(), 76, true);
+        assertEquals(isATestEnc, thisIsATestEnc);
+        
+        encodedBinary = Base64.encode(dataBinary, 4, false);
+        byte[] outBinary = null;
+        try {
+            outBinary = Base64.decode(encodedBinary);
+        } catch (WSSecurityException ex) {
+        }
+        assertTrue(Arrays.equals(outBinary, dataBinary));   
+        
+        encodedBinary = Base64.encode(dataBinary, 76, false);
+        outBinary = null;
+        try {
+            outBinary = Base64.decode(encodedBinary);
+        } catch (WSSecurityException ex) {
+        }
+        assertTrue(Arrays.equals(outBinary, dataBinary));        
+        
+        encodedBinary = Base64.encode(dataBinary, 4, true);
+        outBinary = null;
+        try {
+            outBinary = Base64.decode(encodedBinary);
+        } catch (WSSecurityException ex) {
+        }
+        assertTrue(Arrays.equals(outBinary, dataBinary));    
+        
+        encodedBinary = Base64.encode(dataBinary, 76, true);
+        outBinary = null;
+        try {
+            outBinary = Base64.decode(encodedBinary);
+        } catch (WSSecurityException ex) {
+        }
+        assertTrue(Arrays.equals(outBinary, dataBinary));        
+    }
+
+    public void testDecode() {
+        byte[] out = null;
+        try {
+            out = Base64.decode(thisIsATestEnc);
+        } catch (WSSecurityException ex) {
+
+        }
+        assertEquals(new String(out), thisIsATestClear);
+    }
+
+}
diff --git a/trunk/test/wssec/TestWSSecurity4.java b/trunk/test/wssec/TestWSSecurity4.java
new file mode 100644
index 0000000..2b0be85
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurity4.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ * @author Werner Dittmann (Werner.Dittmann@t-online.de)
+ */
+public class TestWSSecurity4 extends TestCase {
+    private static Log log = LogFactory.getLog(TestWSSecurity4.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance("cryptoSKI.properties");
+
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurity4(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurity4.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope using SubjectKeyIdentifier.
+     * This test uses the SubjectKeyIdentifier to identify the certificate. It
+     * uses the Direct version, that is it embedds the certificate in the message.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+//    public void testX509SignatureSKIDirect() throws Exception {
+//        SOAPEnvelope envelope = null;
+//        WSSignEnvelope builder = new WSSignEnvelope();
+//        builder.setUserInfo("wss4jcert", "security");
+//        builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER_DIRECT);
+//
+//        // builder.setUserInfo("john", "keypass");
+//        log.info("Before Signing....");
+//        Document doc = unsignedEnvelope.getAsDocument();
+//        Document signedDoc = builder.build(doc, crypto);
+//
+//        /*
+//         * convert the resulting document into a message first. The toSOAPMessage()
+//         * mehtod performs the necessary c14n call to properly set up the signed
+//         * document and convert it into a SOAP message. After that we extract it
+//         * as a document again for further processing.
+//         */
+//
+//        Message signedMsg = (Message) SOAPUtil.toSOAPMessage(signedDoc);
+//        XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+//
+//        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+//        log.info("After Signing....");
+//        verify(signedDoc);
+//    }
+
+    /**
+     * Test that signs (twice) and verifies a WS-Security envelope
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+//    public void testDoubleX509SignatureSKIDirect() throws Exception {
+//        SOAPEnvelope envelope = null;
+//        WSSignEnvelope builder = new WSSignEnvelope();
+//        builder.setUserInfo("wss4jcert", "security");
+//        builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER_DIRECT);
+//
+//        // builder.setUserInfo("john", "keypass");
+//        Document doc = unsignedEnvelope.getAsDocument();
+//        Document signedDoc = builder.build(doc, crypto);
+//        Document signedDoc1 = builder.build(signedDoc, crypto);
+//        verify(signedDoc1);
+//    }
+
+    /**
+     * Verifies the soap envelope
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, null, crypto);
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityCertError.java b/trunk/test/wssec/TestWSSecurityCertError.java
new file mode 100644
index 0000000..cdd7542
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityCertError.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.SOAPPart;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * This class tests for error messages that apply to certificates, e.g. when a bad
+ * "username" is used for encryption or signature. See WSS-137.
+ */
+public class TestWSSecurityCertError extends TestCase {
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityCertError(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew3.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test for when a bad certificate is used for Signature
+     */
+    public void testX509Signature() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("bob", "security");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        try {
+            builder.build(doc, CryptoFactory.getInstance(), secHeader);
+            fail("Expected failure on a bad username");
+        } catch (WSSecurityException ex) {
+            String expectedError = "No certificates for user bob were found for signature";
+            assertTrue(ex.getMessage().indexOf(expectedError) != -1);
+        }
+    }
+    
+    /**
+     * Test for when a bad certificate is used for Encryption
+     */
+    public void testEncryption() throws Exception {
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("alice");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        try {
+            builder.build(doc, CryptoFactory.getInstance(), secHeader);
+            fail("Expected failure on a bad username");
+        } catch (WSSecurityException ex) {
+            String expectedError = "No certificates for user alice were found for encryption";
+            assertTrue(ex.getMessage().indexOf(expectedError) != -1);
+        }
+    }
+
+}
diff --git a/trunk/test/wssec/TestWSSecurityDataRef.java b/trunk/test/wssec/TestWSSecurityDataRef.java
new file mode 100644
index 0000000..56a39da
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityDataRef.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDataRef;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Test that checks for correct WSDataRef which should be returned by 
+ * <code>org.apache.ws.security.processor.ReferenceListProcessor</code> 
+ * 
+ * This test uses the RSA_15 alogrithm to transport (wrap) the symmetric key.
+ * The test case creates a ReferenceList element that references EncryptedData
+ * elements. The ReferencesList element is put into the Security header, not
+ * as child of the EncryptedKey. The EncryptedData elements contain a KeyInfo
+ * that references the EncryptedKey via a STR/Reference structure.
+ * 
+ * WSDataRef object must contain the correct QName of the decrypted element. 
+ * 
+ * 
+ */
+public class TestWSSecurityDataRef extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityDataRef.class);
+
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+            + "   <soapenv:Body>"
+            + "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>"
+            + "   </soapenv:Body>" + "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    static final Crypto crypto = CryptoFactory
+            .getInstance("cryptoSKI.properties");
+
+    MessageContext msgContext;
+
+    Message message;
+
+    /**
+     * TestWSSecurityDataRef constructor <p/>
+     * 
+     * @param name
+     *            name of the test
+     */
+    public TestWSSecurityDataRef(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite( TestWSSecurityDataRef.class);
+    }
+
+    /**
+     * Main method <p/>
+     * 
+     * @param args
+     *            command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception
+     *             if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that check for correct WSDataRef object from ReferenceList Processor 
+     * 
+     * 
+     * @throws Exception
+     *             Thrown when there is an error in encryption or decryption
+     */
+    public void testDataRefReferenceListProcessor() throws Exception {
+      
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("wss4jcert");
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        log.info("Before Encryption Triple DES....");
+
+        /*
+         * Prepare the Encrypt object with the token, setup data structure
+         */
+        builder.prepare(doc, crypto);
+
+        /*
+         * Set up the parts structure to encrypt the body
+         */
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+        Vector parts = new Vector();
+        WSEncryptionPart encP = new WSEncryptionPart("testMethod", "uri:LogTestService2",
+                "Element");
+        parts.add(encP);
+
+        /*
+         * Encrypt the element (testMethod), create EncrypedData elements that reference
+         * the EncryptedKey, and get a ReferenceList that can be put into the
+         * Security header. Be sure that the ReferenceList is after the
+         * EncryptedKey element in the Security header (strict layout)
+         */
+        Element refs = builder.encryptForExternalRef(null, parts);
+        builder.addExternalRefElement(refs, secHeader);
+
+        /*
+         * now add (prepend) the EncryptedKey element, then a
+         * BinarySecurityToken if one was setup during prepare
+         */
+        builder.prependToHeader(secHeader);
+
+        builder.prependBSTElementToHeader(secHeader);
+
+        Document encryptedDoc = doc;
+        log.info("After Encryption Triple DES....");
+
+        checkDataRef(encryptedDoc);
+    }
+
+    /**
+     * Verifies the soap envelope <p/>
+     * 
+     * @param envelope
+     * @throws Exception
+     *             Thrown when there is a problem in verification
+     */
+    private void checkDataRef(Document doc) throws Exception {
+        
+        // Retrieve the wsResults vector 
+        Vector wsResults = secEngine.processSecurityHeader(doc, null, this, crypto);
+        boolean found = false;
+                
+        for (int i = 0; i < wsResults.size(); i++) {
+            
+            WSSecurityEngineResult wsSecEngineResult = 
+                (WSSecurityEngineResult)wsResults.get(i);           
+            int action = ((java.lang.Integer) 
+                wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
+            
+            // We want to filter only encryption results
+            if (action != WSConstants.ENCR) {
+                continue;
+            }
+            ArrayList dataRefs = (ArrayList)wsSecEngineResult
+                .get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
+            
+            //We want check only the DATA_REF_URIS 
+            if (dataRefs != null && dataRefs.size() > 0) {
+                for (int j = 0; j < dataRefs.size(); j++) {
+                    Object obj = dataRefs.get(i);                            
+
+                    // ReferenceList Processor must Return a WSDataRef objects
+                    assertTrue(obj instanceof WSDataRef);
+
+                    WSDataRef dataRef = (WSDataRef) obj;
+
+                    // Check whether dataRef URI is set
+                    assertNotNull(dataRef.getDataref());
+
+                    // Check whether QName is correctly set
+                    assertEquals("testMethod", dataRef.getName().getLocalPart());
+                    assertEquals("uri:LogTestService2", dataRef.getName().getNamespaceURI());
+
+                    // Check whether wsu:Id is set
+                    assertNotNull(dataRef.getWsuId());
+
+                    // flag to indicate the element was found in TAG_DATA_REF_URIS
+                    found = true;
+
+                }
+            }
+        }
+        
+        // Make sure the element is actually found in the decrypted elements
+        assertTrue(found);
+        
+    }
+
+    public void handle(Callback[] callbacks) throws IOException,
+            UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for the
+                 * given identifier (e.g. a user name or keystore alias) e.g.:
+                 * pc.setPassword(passStore.getPassword(pc.getIdentfifier)) for
+                 * Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityDataRef1.java b/trunk/test/wssec/TestWSSecurityDataRef1.java
new file mode 100644
index 0000000..3c07f00
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityDataRef1.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSDataRef;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * Test that checks for correct WSDataRef which should be returned by 
+ * <code>org.apache.ws.security.processor.EncryptedKeyProcessor</code> 
+ * 
+ * This test uses the RSA_15 alogrithm to transport (wrap) the symmetric key.
+ * The test case creates a ReferenceList element that references EncryptedData
+ * elements. The ReferencesList element is put into the EncryptedKey. The 
+ * EncryptedData elements contain a KeyInfo that references the EncryptedKey via 
+ * a STR/Reference structure.
+ * 
+ * WSDataRef object must contain the correct QName of the decrypted element. 
+ * 
+ * 
+ */
+public class TestWSSecurityDataRef1 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityDataRef1.class);
+
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+            + "   <soapenv:Body>"
+            + "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>"
+            + "   </soapenv:Body>" + "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    static final Crypto crypto = CryptoFactory
+            .getInstance("cryptoSKI.properties");
+
+    MessageContext msgContext;
+
+    Message message;
+
+    /**
+     * TestWSSecurityDataRef constructor <p/>
+     * 
+     * @param name
+     *            name of the test
+     */
+    public TestWSSecurityDataRef1(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite( TestWSSecurityDataRef1.class);
+    }
+
+    /**
+     * Main method <p/>
+     * 
+     * @param args
+     *            command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception
+     *             if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that check for correct WSDataRef object from EncryptedKey Processor 
+     * 
+     * 
+     * @throws Exception
+     *             Thrown when there is an error in encryption or decryption
+     */
+    public void testDataRefEncryptedKeyProcessor() throws Exception {
+      
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("wss4jcert");
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        log.info("Before Encryption Triple DES....");
+
+        /*
+         * Prepare the Encrypt object with the token, setup data structure
+         */
+        builder.prepare(doc, crypto);
+
+        /*
+         * Set up the parts structure to encrypt the body
+         */
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+        Vector parts = new Vector();
+        WSEncryptionPart encP = new WSEncryptionPart("testMethod", "uri:LogTestService2",
+                "Element");
+        parts.add(encP);
+
+        /*
+         * Encrypt the element (testMethod), create EncrypedData elements that reference
+         * the EncryptedKey, and get a ReferenceList that can be put into the EncryptedKey
+         * itself as a child.
+         */
+        Element refs = builder.encryptForExternalRef(null, parts);
+        
+        /*
+         * We use this method because we want the reference list to be inside the 
+         * EncryptedKey element
+         */
+        builder.addInternalRefElement(refs);
+
+        /*
+         * now add (prepend) the EncryptedKey element, then a
+         * BinarySecurityToken if one was setup during prepare
+         */
+        builder.prependToHeader(secHeader);
+
+        builder.prependBSTElementToHeader(secHeader);
+
+        Document encryptedDoc = doc;
+        log.info("After Encryption Triple DES....");
+
+        checkDataRef(encryptedDoc);
+    }
+
+    /**
+     * Verifies the soap envelope <p/>
+     * 
+     * @param envelope
+     * @throws Exception
+     *             Thrown when there is a problem in verification
+     */
+    private void checkDataRef(Document doc) throws Exception {
+        
+        // Retrieve the wsResults vector 
+        Vector wsResults = secEngine.processSecurityHeader(doc, null, this, crypto);
+        boolean found = false;
+                
+        for (int i = 0; i < wsResults.size(); i++) {
+            
+            WSSecurityEngineResult wsSecEngineResult = 
+                (WSSecurityEngineResult)wsResults.get(i);           
+            int action = ((java.lang.Integer) 
+                wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION)).intValue();
+            
+            // We want to filter only encryption results
+            if (action != WSConstants.ENCR) {
+                continue;
+            }
+            ArrayList dataRefs = (ArrayList)wsSecEngineResult
+                .get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
+            
+            //We want check only the DATA_REF_URIS 
+            if (dataRefs != null && dataRefs.size() > 0) {
+                for (int j = 0; j < dataRefs.size(); j++) {
+                    Object obj = dataRefs.get(i);                            
+
+                    // ReferenceList Processor must Return a WSDataRef objects
+                    assertTrue(obj instanceof WSDataRef);
+
+                    WSDataRef dataRef = (WSDataRef) obj;
+
+                    // Check whether dataRef URI is set
+                    assertNotNull(dataRef.getDataref());
+
+                    // Check whether QName is correctly set
+                    assertEquals("testMethod", dataRef.getName().getLocalPart());
+                    assertEquals("uri:LogTestService2", dataRef.getName().getNamespaceURI());
+
+                    // Check whether wsu:Id is set
+                    assertNotNull(dataRef.getWsuId());
+
+                    // flag to indicate the element was found in TAG_DATA_REF_URIS
+                    found = true;
+
+                }
+            }
+        }
+        
+        // Make sure the element is actually found in the decrypted elements
+        assertTrue(found);
+        
+    }
+
+    public void handle(Callback[] callbacks) throws IOException,
+            UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for the
+                 * given identifier (e.g. a user name or keystore alias) e.g.:
+                 * pc.setPassword(passStore.getPassword(pc.getIdentfifier)) for
+                 * Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityFaultCodes.java b/trunk/test/wssec/TestWSSecurityFaultCodes.java
new file mode 100644
index 0000000..c3265e8
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityFaultCodes.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecTimestamp;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.xml.namespace.QName;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import java.util.Vector;
+
+/**
+ * WS-Security Test Case for fault codes. The SOAP Message Security specification 1.1 defines
+ * standard fault codes and fault strings for error propagation.
+ */
+public class TestWSSecurityFaultCodes extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityFaultCodes.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityFaultCodes(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityFaultCodes.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    
+    /**
+     * Test for the wsse:FailedCheck faultcode. This will fail due to a bad password in
+     * the callback handler.
+     */
+    public void testFailedCheck() throws Exception {
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);        
+        Document encryptedDoc = builder.build(doc, crypto, secHeader);
+        
+        try {
+            verify(encryptedDoc);
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == 6);
+            assertTrue(ex.getMessage().startsWith("The signature or decryption was invalid"));
+            QName faultCode = new QName(WSConstants.WSSE_NS, "FailedCheck");
+            assertTrue(ex.getFaultCode().equals(faultCode));
+        }
+    }
+    
+    /**
+     * Test for the wsse:UnsupportedAlgorithm faultcode. This will fail due to the argument
+     * passed to getCipherInstance.
+     */
+    public void testUnsupportedAlgorithm() throws Exception {
+        try {
+            WSSecurityUtil.getCipherInstance("Bad Algorithm");
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == 2);
+            assertTrue(ex.getMessage().startsWith(
+                "An unsupported signature or encryption algorithm was used"));
+            QName faultCode = new QName(WSConstants.WSSE_NS, "UnsupportedAlgorithm");
+            assertTrue(ex.getFaultCode().equals(faultCode));
+        }
+    }
+    
+    
+    /**
+     * Test for the wsse:SecurityTokenUnavailable faultcode. This will fail due to the 
+     * argument to loadCertificate.
+     */
+    public void testSecurityTokenUnavailable() throws Exception {
+        try {
+            crypto.loadCertificate(new java.io.ByteArrayInputStream(new byte[]{}));
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == 7);
+            assertTrue(ex.getMessage().startsWith(
+                "Referenced security token could not be retrieved"));
+            QName faultCode = new QName(WSConstants.WSSE_NS, "SecurityTokenUnavailable");
+            assertTrue(ex.getFaultCode().equals(faultCode));
+        }
+    }
+    
+    /**
+     * Test for the wsse:MessageExpired faultcode. This will fail due to the argument
+     * passed to setTimeToLive.
+     */
+    public void testMessageExpired() throws Exception {
+        WSSecTimestamp builder = new WSSecTimestamp();
+        builder.setTimeToLive(-1);
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);        
+        Document timestampedDoc = builder.build(doc, secHeader);
+        
+        try {
+            verify(timestampedDoc);
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == 8);
+            assertTrue(ex.getMessage().startsWith(
+                "The message has expired"));
+            QName faultCode = new QName(WSConstants.WSSE_NS, "MessageExpired");
+            assertTrue(ex.getFaultCode().equals(faultCode));
+        }
+    }
+    
+    /**
+     * Test for the wsse:FailedAuthentication faultcode. This will fail due to a bad password in
+     * the callback handler.
+     */
+    public void testFailedAuthentication() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.addCreated();
+        builder.addNonce();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);        
+        Document timestampedDoc = builder.build(doc, secHeader);
+        
+        try {
+            verify(doc);
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == 5);
+            assertTrue(ex.getMessage().startsWith(
+                "The security token could not be authenticated or authorized"));
+            QName faultCode = new QName(WSConstants.WSSE_NS, "FailedAuthentication");
+            assertTrue(ex.getFaultCode().equals(faultCode));
+        }
+    }
+    
+    /**
+     * Test for the wsse:InvalidSecurityToken faultcode. This will fail due to the fact
+     * that a null username is used.
+     */
+    public void testInvalidSecurityToken() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.addCreated();
+        builder.addNonce();
+        builder.setUserInfo(null, "security");
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);        
+        Document timestampedDoc = builder.build(doc, secHeader);
+        
+        try {
+            new UsernameToken(doc.getDocumentElement());
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == 4);
+            assertTrue(ex.getMessage().startsWith(
+                "An invalid security token was provided"));
+            QName faultCode = new QName(WSConstants.WSSE_NS, "InvalidSecurityToken");
+            assertTrue(ex.getFaultCode().equals(faultCode));
+        }
+    }
+    
+    /**
+     * Test for the wsse:InvalidSecurity faultcode. 
+     */
+    public void testInvalidSecurity() throws Exception {
+        try {
+            new Reference((org.w3c.dom.Element)null);
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == 3);
+            assertTrue(ex.getMessage().startsWith(
+                "An error was discovered processing the <wsse:Security> header"));
+            QName faultCode = new QName(WSConstants.WSSE_NS, "InvalidSecurity");
+            assertTrue(ex.getFaultCode().equals(faultCode));
+        }
+    }
+    
+    
+    /**
+     * Verifies the soap envelope.
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+    }
+    
+    
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                //
+                // Deliberately wrong password
+                //
+                pc.setPassword("securit");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+
+}
diff --git a/trunk/test/wssec/TestWSSecurityGetPassword.java b/trunk/test/wssec/TestWSSecurityGetPassword.java
new file mode 100644
index 0000000..8ca83d5
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityGetPassword.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.action.Action;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoBase;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.processor.Processor;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+
+/**
+ * WS-Security Test Case for the getPassword method in WSHandler.
+ * <p/>
+ */
+public class TestWSSecurityGetPassword extends TestCase {
+    private static Log log = LogFactory.getLog(TestWSSecurityGetPassword.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = 
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 
+        + "<SOAP-ENV:Envelope "
+        +   "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+        +   "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
+        +   "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" 
+        +   "<SOAP-ENV:Body>" 
+        +       "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" 
+        +           "<value xmlns=\"\">15</value>" 
+        +       "</add>" 
+        +   "</SOAP-ENV:Body>" 
+        + "</SOAP-ENV:Envelope>";
+
+    static final Crypto crypto = CryptoFactory.getInstance();
+
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityGetPassword(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityGetPassword.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * A unit test for {@link WSHandler#getPassword(String, int, String, String, RequestData)},
+     * where the password is obtained from the Message Context.
+     */
+    public void
+    testGetPasswordRequestContextUnit() throws Exception {
+        
+        final WSSConfig cfg = WSSConfig.getNewInstance();
+        final RequestData reqData = new RequestData();
+        reqData.setWssConfig(cfg);
+        java.util.Map messageContext = new java.util.TreeMap();
+        messageContext.put("password", "securityPassword");
+        reqData.setMsgContext(messageContext);
+        
+        WSHandler handler = new MyHandler();
+        WSPasswordCallback callback = 
+            handler.getPassword(
+                "bob", 
+                WSConstants.UT, 
+                "SomeCallbackTag", 
+                "SomeCallbackRef",
+                reqData
+            );
+        assertTrue("bob".equals(callback.getIdentifier()));
+        assertTrue("securityPassword".equals(callback.getPassword()));
+        assertTrue(WSPasswordCallback.USERNAME_TOKEN == callback.getUsage());
+    }
+    
+    /**
+     * A WSHandler test for {@link WSHandler#getPassword(String, int, String, String, RequestData)},
+     * where the password is obtained from the Message Context.
+     */
+    public void
+    testGetPasswordRequestContext() throws Exception {
+        
+        final WSSConfig cfg = WSSConfig.getNewInstance();
+        final RequestData reqData = new RequestData();
+        reqData.setWssConfig(cfg);
+        reqData.setUsername("bob");
+        reqData.setPwType(WSConstants.PASSWORD_TEXT);
+        java.util.Map messageContext = new java.util.TreeMap();
+        messageContext.put("password", "securityPassword");
+        reqData.setMsgContext(messageContext);
+        
+        final java.util.Vector actions = new java.util.Vector();
+        actions.add(new Integer(WSConstants.UT));
+        Document doc = unsignedEnvelope.getAsDocument();
+        MyHandler handler = new MyHandler();
+        handler.doit(
+            WSConstants.UT, 
+            doc, 
+            reqData, 
+            actions
+        );
+        
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
+        if (log.isDebugEnabled()) {
+            log.debug(outputString);
+        }
+        assertTrue(outputString.indexOf("bob") != -1);
+        assertTrue(outputString.indexOf("securityPassword") != -1);
+    }
+    
+    /**
+     * A test for {@link WSHandler#getPassword(String, int, String, String, RequestData)},
+     * where the password is obtained from a Callback Handler, which is placed on the 
+     * Message Context using a reference.
+     */
+    public void
+    testGetPasswordCallbackHandlerRef() throws Exception {
+        
+        final WSSConfig cfg = WSSConfig.getNewInstance();
+        final RequestData reqData = new RequestData();
+        reqData.setWssConfig(cfg);
+        reqData.setUsername("bob");
+        reqData.setPwType(WSConstants.PASSWORD_TEXT);
+        java.util.Map messageContext = new java.util.TreeMap();
+        messageContext.put(
+            WSHandlerConstants.PW_CALLBACK_REF, 
+            new MyCallbackHandler()
+        );
+        reqData.setMsgContext(messageContext);
+        
+        final java.util.Vector actions = new java.util.Vector();
+        actions.add(new Integer(WSConstants.UT));
+        Document doc = unsignedEnvelope.getAsDocument();
+        MyHandler handler = new MyHandler();
+        handler.doit(
+            WSConstants.UT, 
+            doc, 
+            reqData, 
+            actions
+        );
+        
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
+        if (log.isDebugEnabled()) {
+            log.debug(outputString);
+        }
+        assertTrue(outputString.indexOf("bob") != -1);
+        assertTrue(outputString.indexOf("securityPassword") != -1);
+    }
+    
+
+    /**
+     * a trivial extension of the WSHandler type
+     */
+    public static class MyHandler extends WSHandler {
+        
+        public Object 
+        getOption(String key) {
+            return null;
+        }
+        
+        public void 
+        setProperty(
+            Object msgContext, 
+            String key, 
+            Object value
+        ) {
+        }
+
+        public Object 
+        getProperty(Object ctx, String key) {
+           return ((java.util.Map)ctx).get(key);
+        }
+    
+        public void 
+        setPassword(Object msgContext, String password) {
+        }
+        
+        public String 
+        getPassword(Object msgContext) {
+            return (String)((java.util.Map)msgContext).get("password");
+        }
+        
+        void doit(
+            int action, 
+            Document doc,
+            RequestData reqData, 
+            java.util.Vector actions
+        ) throws org.apache.ws.security.WSSecurityException {
+            doSenderAction(
+                action, 
+                doc, 
+                reqData, 
+                actions,
+                true
+            );
+        }
+    }
+    
+    public static class MyCallbackHandler implements CallbackHandler {
+        public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+            for (int i = 0; i < callbacks.length; i++) {
+                if (callbacks[i] instanceof WSPasswordCallback) {
+                    WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                    if (pc.getIdentifier() == "bob") {
+                        pc.setPassword("securityPassword");
+                    }
+                } else {
+                    throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+                }
+            }
+        }
+    }
+    
+}
diff --git a/trunk/test/wssec/TestWSSecurityHooks.java b/trunk/test/wssec/TestWSSecurityHooks.java
new file mode 100644
index 0000000..c83228b
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityHooks.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.AxisFault;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.axis.security.WSDoAllReceiver;
+import org.apache.ws.axis.security.WSDoAllSender;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.components.crypto.BouncyCastle;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.handler.WSHandlerConstants;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyStore;
+
+/**
+ * <dl>
+ * <dt><b>Title: </b><dd>WS Security Hooks Test Case</dd>
+ * <p>
+ * <dt><b>Description: </b><dd>Test Case to verify the load...Crypto hooks work properly. 
+ * Also tests the setKeyStore method of Merlin </dd>
+ * </dl>
+ * 
+ * @see org.apache.ws.security.components.crypto.Merlin#setKeyStore
+ * @see org.apache.ws.axis.security.WSDoAllReceiver#loadSignatureCrypto
+ * @see org.apache.ws.axis.security.WSDoAllReceiver#loadDecryptionCrypto
+ * @see org.apache.ws.axis.security.WSDoAllSender#loadSignatureCrypto
+ * @see org.apache.ws.axis.security.WSDoAllSender#loadEncryptionCrypto
+ * 
+ * @author <a href="mailto:jasone@greenrivercomputing.com>Jason Essington</a>
+ * @version $Revision$
+ */
+public class TestWSSecurityHooks extends TestCase implements CallbackHandler
+{
+   private static Log log = LogFactory.getLog(TestWSSecurityHooks.class);
+   private static final String soapMessage = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
+         "<soapenv:Envelope " +
+               "xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\" " +
+               "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
+               "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "<soapenv:Header>" +
+            "</soapenv:Header>" +
+            "<soapenv:Body>" +
+               "<ns1:echo " +
+                     "xmlns:ns1=\"http://org.apache.wss4j.wssec/TESTCASE\" " +
+                     "soapenv:encodingStyle=\"http://www.w3.org/2003/05/soap-encoding\">" +
+                  "<inStr xsi:type=\"xsd:string\">ECHO ECHo ECho Echo echo echO ecHO eCHO ECHO</inStr>" +
+               "</ns1:echo>" +
+            "</soapenv:Body>" +
+         "</soapenv:Envelope>";
+
+   KeyStore keystore = null;
+   MessageContext mc = null;
+   
+   public TestWSSecurityHooks(String name) {
+      super(name);
+   }
+   
+   protected void setUp() throws Exception {
+      AxisClient tmpEngine = new AxisClient(new NullProvider());
+      mc = new MessageContext(tmpEngine);
+      mc.setCurrentMessage(getSOAPMessage(soapMessage));
+      mc.setProperty(WSHandlerConstants.PW_CALLBACK_REF, this);
+      keystore = loadKeyStore();
+   }
+
+   public static Test suite() {
+      return new TestSuite(TestWSSecurityHooks.class);
+   }
+
+   public static void main(String[] args) {
+      junit.textui.TestRunner.run(suite());
+   }
+   
+   //
+   //
+   // Tests
+   //
+   //
+   
+   public void testCryptoHook() throws Exception {
+      assertNotNull("", keystore);
+      Crypto crypto = new TestCryptoImpl(keystore);
+      assertNotNull(PrivilegedAccessor.getValue(crypto, "keystore"));
+   }
+   public void testSenderLoadSignatureHook() throws Exception {
+      TestSenderImpl sender = new TestSenderImpl();
+      // we have to coerce a value into this field or we'll get a bunch of NPEs when calling decodeSignatureParameter
+      PrivilegedAccessor.setValue(sender, "msgContext", mc);
+      PrivilegedAccessor.invokeMethod(sender, "decodeSignatureParameter", new Object[] {});
+      assertNotNull(PrivilegedAccessor.getValue(sender, "sigCrypto"));
+   }
+   public void testSenderLoadEncryptionHook() throws Exception {
+      TestSenderImpl sender = new TestSenderImpl();
+      // decodeEcnryptionParameter() is rather insistant on having a user (anyUser)
+      sender.setOption(WSHandlerConstants.ENCRYPTION_USER, "anyUserWillDo");
+      // we have to coerce a value into this field or we'll get a bunch of NPEs when calling decodeSignatureParameter
+      PrivilegedAccessor.setValue(sender, "msgContext", mc);
+      PrivilegedAccessor.invokeMethod(sender, "decodeEncryptionParameter", new Object[] {});
+      assertNotNull(PrivilegedAccessor.getValue(sender, "encCrypto"));
+   }
+   public void testReceiverLoadSignatureHook() throws Exception {
+      TestReceiverImpl receiver = new TestReceiverImpl();
+      PrivilegedAccessor.invokeMethod(receiver, "decodeSignatureParameter", new Object[] {});
+      assertNotNull(PrivilegedAccessor.getValue(receiver, "sigCrypto"));
+   }
+   public void testReceiverLoadDecryptionHook() throws Exception {
+      TestReceiverImpl receiver = new TestReceiverImpl();
+      PrivilegedAccessor.invokeMethod(receiver, "decodeDecryptionParameter", new Object[] {});
+      assertNotNull(PrivilegedAccessor.getValue(receiver, "decCrypto"));
+   }
+   
+   public void testRoundTripWithHooks() throws Exception {
+      // Setup our sender to Encrypt and Sign a soap message
+      TestSenderImpl sender = new TestSenderImpl();
+      sender.setOption(WSHandlerConstants.ACTOR, "test");
+      sender.setOption(WSHandlerConstants.USER, "16c73ab6-b892-458f-abf5-2f875f74882e");
+      sender.setOption(WSHandlerConstants.ACTION, "Encrypt Signature");
+      sender.setOption(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
+      sender.setOption(WSHandlerConstants.ENC_KEY_ID, "X509KeyIdentifier");
+      sender.invoke(mc);
+      
+      // Make sure that at least SOMETHING happened
+      String soapPart = mc.getCurrentMessage().getSOAPPartAsString();
+      assertNotSame("The message has not been Encrypted or Signed", soapPart, soapMessage);
+      
+      // Prepare the message context for the response
+      Message message = getSOAPMessage(soapPart);
+      mc.setPastPivot(true);
+      mc.setCurrentMessage(message);
+      
+      // Setup our receiver for the decryption / signature validation
+      TestReceiverImpl receiver = new TestReceiverImpl();
+      receiver.setOption(WSHandlerConstants.ACTOR, "test");
+      receiver.setOption(WSHandlerConstants.ACTION, "Encrypt Signature");
+      receiver.invoke(mc);
+   }
+   
+   //
+   //
+   // Test Utility Classes
+   //
+   //
+      
+   /**
+    * This is a subclass of Merlin that uses the setKeyStore() method rather than the 
+    * load(is) method to set the private keystore field.
+    */
+   public class TestCryptoImpl extends BouncyCastle {
+      TestCryptoImpl(KeyStore ks) throws Exception {
+         super(null);
+         assertNotNull(ks);
+         setKeyStore(ks);
+      }
+   }
+   
+   /**
+    * Subclass of WSDoAllReceiver that creates the Crypto's directly
+    */
+   public class TestReceiverImpl extends WSDoAllReceiver
+   {
+      protected Crypto loadDecryptionCrypto() throws AxisFault {
+         try {
+            return new TestCryptoImpl(keystore);
+         } catch(Exception e) {
+            fail("Failed to create a Crypto instance.");
+            throw new AxisFault("Failed to create a Crypto instance.", e);
+         }
+      }
+      protected Crypto loadSignatureCrypto() throws AxisFault {
+         try {
+            return new TestCryptoImpl(keystore);
+         } catch(Exception e) {
+            fail("Failed to create a Crypto instance.");
+            throw new AxisFault("Failed to create a Crypto instance.", e);
+         }
+      }
+   }
+   
+   /**
+    * Subclass of WSDoAllSender that creates the Crypto's directly
+    */
+   public class TestSenderImpl extends WSDoAllSender
+   {
+      protected Crypto loadEncryptionCrypto() throws AxisFault {
+         try {
+            return new TestCryptoImpl(keystore);
+         } catch(Exception e) {
+            fail("Failed to create a Crypto instance.");
+            throw new AxisFault("Failed to create a Crypto instance.", e);
+         }
+      }
+      protected Crypto loadSignatureCrypto() throws AxisFault {
+         try {
+            return new TestCryptoImpl(keystore);
+         } catch(Exception e) {
+            fail("Failed to create a Crypto instance.");
+            throw new AxisFault("Failed to create a Crypto instance.", e);
+         }
+      }
+   }
+   
+   
+   //
+   //
+   // test utility methods
+   //
+   //
+   
+   protected Message getSOAPMessage(String message) throws Exception {
+      InputStream in = new ByteArrayInputStream(message.getBytes());
+      Message msg = new Message(in);
+      msg.setMessageContext(mc);
+      return msg;
+   }
+   
+   protected KeyStore loadKeyStore() throws Exception {
+      KeyStore ks = null;
+      FileInputStream is = null;
+      is = new FileInputStream("keys/x509.PFX.MSFT");
+      ks = KeyStore.getInstance("pkcs12");
+      String password = "security";
+      ks.load(is, password.toCharArray());
+      return ks;
+   }
+   
+   public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+      for (int i = 0; i < callbacks.length; i++) {
+         if (callbacks[i] instanceof WSPasswordCallback) {
+            WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+            pc.setPassword("security");
+            
+         } else {
+            throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+         }
+      }
+   }
+   
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew.java b/trunk/test/wssec/TestWSSecurityNew.java
new file mode 100644
index 0000000..bdb275d
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew extends TestCase {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * The test uses the ThumbprintSHA1 key identifier type.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testX509SignatureIS() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        log.info("Before Signing IS....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with IssuerSerial key identifier:");
+            XMLUtils.PrettyElementToWriter(signedDoc.getDocumentElement(), new PrintWriter(System.out));
+        }
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with IssuerSerial key identifier(1):");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing IS....");
+        verify(signedDoc);
+    }
+
+
+    /**
+     * Test that signs (twice) and verifies a WS-Security envelope.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testDoubleX509SignatureIS() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+        Document signedDoc1 = builder.build(signedDoc, crypto, secHeader);
+        verify(signedDoc1);
+    }
+
+    /**
+     * Verifies the soap envelope.
+     * This method verfies all the signature generated. 
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, null, crypto);
+    }
+    
+    /**
+     * Ensure that we can load a custom crypto implementation using a Map
+     */
+    public void testCustomCrypto() {
+        java.util.Map tmp = new java.util.TreeMap();
+        Crypto crypto = CryptoFactory.getInstance(
+            "wssec.CustomCrypto",
+            tmp
+        );
+        assertNotNull(crypto);
+        assertTrue(crypto instanceof CustomCrypto);
+        CustomCrypto custom = (CustomCrypto)crypto;
+        assertSame(tmp, custom.config);
+    }
+    
+    /**
+     * Test for WSS-149 - "AbstractCrypto requires org.apache.ws.security.crypto.merlin.file
+     * to be set and point to an existing file"
+     */
+    public void testNoKeyStoreFile() {
+        Crypto crypto = CryptoFactory.getInstance(
+            "nofile.properties"
+        );
+        assertNotNull(crypto);
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew10.java b/trunk/test/wssec/TestWSSecurityNew10.java
new file mode 100644
index 0000000..bc018ce
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew10.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.token.Reference;
+import org.apache.ws.security.message.token.SecurityTokenReference;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+/**
+ * TestCase10 for testing HMAC_SHA1 in wss4j. Based on TestCase9.
+ * 
+ * The objective of this TestCase is to test the HMAC_SHA1 signature.
+ * 
+ * @author Dimuthu Leelarathne. (muthulee@yahoo.com)
+ */
+public class TestWSSecurityNew10 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew10.class);
+
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+            + "   <soapenv:Body>"
+            + "      <ns1:testMethod xmlns:ns1=\"http://axis/service/security/test10/LogTestService10\"></ns1:testMethod>"
+            + "   </soapenv:Body>" + "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    static final Crypto crypto = CryptoFactory.getInstance();
+
+    MessageContext msgContext;
+
+    Message message;
+
+    // private byte[] sharedSecret = "SriLankaSriLankaSriLanka".getBytes();
+
+    /**
+     * TestWSSecurity constructor <p/>
+     * 
+     * @param name
+     *            name of the test
+     */
+    public TestWSSecurityNew10(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew10.class);
+    }
+
+    /**
+     * Main method <p/>
+     * 
+     * @param args
+     *            command line args
+     */
+    // public static void main(String[] args) {
+    // junit.textui.TestRunner.run(suite());
+    // }
+    /**
+     * Setup method <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception
+     *             if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that encrypts and signs a WS-Security envelope, then performs
+     * verification and decryption. <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is any problem in signing, encryption,
+     *             decryption, or verification
+     */
+    public void testEMBED_SECURITY_TOKEN_REF() throws Exception {
+
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt wsEncrypt = new WSSecEncrypt();
+
+        // Get the message as document
+        log.info("Before Encryption....");
+        Document doc = unsignedEnvelope.getAsDocument();
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        /*
+         * Step 1 :: Add a UserNameToken. Step 2 :: Add an Id to it. Step 3 ::
+         * Create a Reference to the UserNameToken. Step 4 :: Setting necessary
+         * parameters in WSEncryptBody. Step 5 :: Encrypt using the using the
+         * password of UserNameToken.
+         */
+
+        // Step 1
+        String username = "Dimthu";
+        String password = "Sri Lanka Sri Lanka UOM ";
+        byte[] key = password.getBytes();
+
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setPasswordType(WSConstants.PASSWORD_TEXT);
+        builder.setUserInfo(username, password);
+        builder.build(doc, secHeader);
+
+        // Step 3 ::
+        Reference ref = new Reference(doc);
+        ref.setURI("#" + builder.getId());
+        ref.setValueType("UsernameToken");
+        SecurityTokenReference secRef = new SecurityTokenReference(doc);
+        secRef.setReference(ref);
+
+        // adding the namespace
+        WSSecurityUtil.setNamespace(secRef.getElement(), WSConstants.WSSE_NS,
+                WSConstants.WSSE_PREFIX);
+
+        // Step 4 ::
+        wsEncrypt.setKeyIdentifierType(WSConstants.EMBED_SECURITY_TOKEN_REF);
+        wsEncrypt.setSecurityTokenReference(secRef);
+        wsEncrypt.setKey(key);
+        wsEncrypt.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
+        wsEncrypt.setDocument(doc);
+
+        // Step 4 :: Encrypting using the key.
+        Document encDoc = wsEncrypt.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The
+         * toAxisMessage() mehtod performs the necessary c14n call to properly
+         * set up the signed document and convert it into a SOAP message. After
+         * that we extract it as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(encDoc);
+
+        if (log.isDebugEnabled()) {
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope()
+                    .getAsDOM(), new PrintWriter(System.out));
+        }
+        log.info("Encryption Done\n");
+        // verifyEMBED_SECURITY_TOKEN_REF(signedMsg.getSOAPEnvelope().getAsDocument());
+    }
+
+    /**
+     * Verifies the soap envelope <p/>
+     * 
+     * @param doc
+     * @throws Exception
+     *             Thrown when there is a problem in verification
+     */
+//    private void verifyEMBED_SECURITY_TOKEN_REF(Document doc) throws Exception {
+//        secEngine.processSecurityHeader(doc, "", this, null);
+//        log.info("Success ......");
+//    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
+     */
+    public void handle(Callback[] callbacks) throws IOException,
+            UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN) {
+                    pc.setPassword("Sri Lanka Sri Lanka UOM ");
+                } else if (pc.getUsage() == WSPasswordCallback.DECRYPT) {
+                    pc.setKey("Sri Lanka Sri Lanka UOM ".getBytes());
+
+                }
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        junit.textui.TestRunner.run(suite());
+    }
+
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew11.java b/trunk/test/wssec/TestWSSecurityNew11.java
new file mode 100644
index 0000000..5f3f18b
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew11.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecTimestamp;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.util.Vector;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew11 extends TestCase {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew11.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance("cryptoSKI.properties");
+
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew11(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew11.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope.
+     * This test uses the direct reference key identifier (certificate included
+     * as a BinarySecurityToken (BST) in the message). The test signs the message
+     * body (SOAP Body) and uses the STRTransform to sign the embedded certificate
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testX509SignatureDirectSTR() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("wss4jcert", "security");
+        // builder.setUserInfo("john", "keypass");
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(unsignedEnvelope.getAsDOM());
+        Vector parts = new Vector();
+        
+        /*
+         * Set up to sign body and use STRTransorm to sign
+         * the signature token (e.g. X.509 certificate)
+         */
+        WSEncryptionPart encP =
+            new WSEncryptionPart(
+                soapConstants.getBodyQName().getLocalPart(),
+                soapConstants.getEnvelopeURI(),
+                "Content");
+        parts.add(encP);
+        encP =
+            new WSEncryptionPart(
+                "STRTransform",
+                soapConstants.getEnvelopeURI(),
+                "Content");
+        parts.add(encP);
+
+        builder.setParts(parts);
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+
+        log.info("Before Signing STR DirectReference....");
+        Document doc = unsignedEnvelope.getAsDocument();
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with STR DirectReference key identifier:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing STR DirectReference....");
+        verify(signedDoc);
+    }
+    
+    /**
+     * This is a test for WSS-96:
+     * "Error when making a signature when containing a WSSecTimestamp"
+     * A timestamp is added to the document and signed.
+     */
+    public void testWSS96() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("wss4jcert", "security");
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(unsignedEnvelope.getAsDOM());
+        Vector parts = new Vector();
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        /*
+         * Set up to sign body and use STRTransorm to sign
+         * the signature token (e.g. X.509 certificate)
+         */
+        WSEncryptionPart encP =
+            new WSEncryptionPart(
+                soapConstants.getBodyQName().getLocalPart(),
+                soapConstants.getEnvelopeURI(),
+                "Content");
+        parts.add(encP);
+        encP =
+            new WSEncryptionPart(
+                "STRTransform",
+                soapConstants.getEnvelopeURI(),
+                "Content");
+        parts.add(encP);
+        
+        WSSecTimestamp timestamp = new WSSecTimestamp();
+        timestamp.setTimeToLive(600);
+        timestamp.build(doc, secHeader);
+        parts.add(new WSEncryptionPart(timestamp.getId()));
+
+        builder.setParts(parts);
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+
+        log.info("Before Signing STR DirectReference....");
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with STR DirectReference key identifier:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing STR DirectReference....");
+        verify(signedDoc);
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope.
+     * This test uses the IssuerSerialDirect reference key identifier (certificate included
+     * as a BinarySecurityToken (BST) in the message) but identified with IssuerSerialNumber
+     * and <b>not</b> with a Reference (relative URI). The test signs the message
+     * body (SOAP Body) and uses the STRTransform to sign the embedded certificate
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+//    public void testX509SignatureISDirectSTR() throws Exception {
+//        SOAPEnvelope envelope = null;
+//        WSSignEnvelope builder = new WSSignEnvelope();
+//        builder.setUserInfo("wss4jcert", "security");
+//        // builder.setUserInfo("john", "keypass");
+//        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(unsignedEnvelope);
+//        Vector parts = new Vector();
+//        
+//        /*
+//         * Set up to sign body and use STRTransorm to sign
+//         * the signature token (e.g. X.509 certificate)
+//         */
+//        WSEncryptionPart encP =
+//            new WSEncryptionPart(
+//                soapConstants.getBodyQName().getLocalPart(),    // define the body
+//                soapConstants.getEnvelopeURI(),
+//                "Content");
+//        parts.add(encP);
+//        encP =
+//            new WSEncryptionPart(
+//                "STRTransform",                // reserved word to use STRTransform
+//                soapConstants.getEnvelopeURI(),
+//                "Content");
+//        parts.add(encP);
+//
+//        builder.setParts(parts);
+//        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL_DIRECT);
+//
+//        log.info("Before Signing STR ISDirect....");
+//        Document doc = unsignedEnvelope.getAsDocument();
+//        Document signedDoc = builder.build(doc, crypto);
+//
+//        Message signedMsg = (Message) SOAPUtil.toSOAPMessage(signedDoc);
+//        if (log.isDebugEnabled()) {
+//            log.debug("Signed message with STR IssuerSerialDirect key identifier:");
+//            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+//        }
+//        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+//        log.info("After Signing STR ISDirect....");
+//        verify(signedDoc);
+//    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope.
+     * This test uses the IssuerSerial reference key identifier (certificate not included
+     * in the message)and reads the certificate from a keystore using IssuerSerialNumber
+     * to identify it.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    
+
+    public void testX509SignatureISSTR() throws Exception {
+        SOAPEnvelope envelope = null;
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("wss4jcert", "security");
+        // builder.setUserInfo("john", "keypass");
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(unsignedEnvelope.getAsDOM());
+        Vector parts = new Vector();
+        
+        /*
+         * Set up to sign body and use STRTransorm to sign
+         * the signature token (e.g. X.509 certificate)
+         */
+        WSEncryptionPart encP =
+            new WSEncryptionPart(
+                soapConstants.getBodyQName().getLocalPart(),    // define the body
+                soapConstants.getEnvelopeURI(),
+                "Content");
+        parts.add(encP);
+        encP =
+            new WSEncryptionPart(
+                "STRTransform",                // reserved word to use STRTransform
+                soapConstants.getEnvelopeURI(),
+                "Content");
+        parts.add(encP);
+
+        builder.setParts(parts);
+        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+
+        log.info("Before Signing STR IS....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        Message signedMsg = (Message) SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with STR IssuerSerial key identifier:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing STR IS....");
+        verify(signedDoc);
+    }
+    
+    /**
+     * Test that signs and verifies a WS-Security envelope.
+     * This test uses the SubjectKeyIdentifier key identifier (certificate not included
+     * in the message) and reads the certificate from a keystore using SKI
+     * to identify it.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    
+
+    public void testX509SignatureSKISTR() throws Exception {
+        SOAPEnvelope envelope = null;
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("wss4jcert", "security");
+        // builder.setUserInfo("john", "keypass");
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(unsignedEnvelope.getAsDOM());
+        Vector parts = new Vector();
+        
+        /*
+         * Set up to sign body and use STRTransorm to sign
+         * the signature token (e.g. X.509 certificate)
+         */
+        WSEncryptionPart encP =
+            new WSEncryptionPart(
+                soapConstants.getBodyQName().getLocalPart(),    // define the body
+                soapConstants.getEnvelopeURI(),
+                "Content");
+        parts.add(encP);
+        encP =
+            new WSEncryptionPart(
+                "STRTransform",                // reserved word to use STRTransform
+                soapConstants.getEnvelopeURI(),
+                "Content");
+        parts.add(encP);
+
+        builder.setParts(parts);
+        builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
+
+        log.info("Before Signing STR SKI....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        Message signedMsg = (Message) SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with STR SKI key identifier:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing STR SKI....");
+        verify(signedDoc);
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope.
+     * This test uses the SubjectKeyIdentifierDirect key identifier (certificate included
+     * in the message).
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    
+
+//    public void testX509SignatureSKIDirectSTR() throws Exception {
+//        SOAPEnvelope envelope = null;
+//        WSSignEnvelope builder = new WSSignEnvelope();
+//        builder.setUserInfo("wss4jcert", "security");
+//        // builder.setUserInfo("john", "keypass");
+//        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(unsignedEnvelope);
+//        Vector parts = new Vector();
+//        
+//        /*
+//         * Set up to sign body and use STRTransorm to sign
+//         * the signature token (e.g. X.509 certificate)
+//         */
+//        WSEncryptionPart encP =
+//            new WSEncryptionPart(
+//                soapConstants.getBodyQName().getLocalPart(),    // define the body
+//                soapConstants.getEnvelopeURI(),
+//                "Content");
+//        parts.add(encP);
+//        encP =
+//            new WSEncryptionPart(
+//                "STRTransform",                // reserved word to use STRTransform
+//                soapConstants.getEnvelopeURI(),
+//                "Content");
+//        parts.add(encP);
+//
+//        builder.setParts(parts);
+//        builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER_DIRECT);
+//
+//        log.info("Before Signing STR SKIDirect....");
+//        Document doc = unsignedEnvelope.getAsDocument();
+//        Document signedDoc = builder.build(doc, crypto);
+//
+//        Message signedMsg = (Message) SOAPUtil.toSOAPMessage(signedDoc);
+//        if (log.isDebugEnabled()) {
+//            log.debug("Signed message with STR SKIDirect key identifier:");
+//            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+//        }
+//        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+//        log.info("After Signing STR SKIDirect....");
+//        verify(signedDoc);
+//    }
+
+
+    /**
+     * Verifies the soap envelope
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, null, crypto);
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew12.java b/trunk/test/wssec/TestWSSecurityNew12.java
new file mode 100644
index 0000000..3c85989
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew12.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import org.apache.xml.security.signature.XMLSignature;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ * @author Werner Dittmann (Werner.Dittmann@siemens.com)
+ */
+public class TestWSSecurityNew12 extends TestCase {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew12.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance("cryptoSKI.properties");
+
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew12(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew12.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope using SubjectKeyIdentifier.
+     * This test uses the SubjectKeyIdentifier to identify the certificate. It
+     * uses the Direct version, that is it embedds the certificate in the message.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testX509SignatureDSA_SKI() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("wss4jcertDSA", "security");
+        builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
+        builder.setSignatureAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_DSA);
+        
+        // builder.setUserInfo("john", "keypass");
+        log.info("Before SigningDSA_SKIDirect....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with DSA_SKI key identifier:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After SigningDSA_SKIDirect....");
+        verify(signedDoc);
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope using SubjectKeyIdentifier.
+     * This test uses the SubjectKeyIdentifier to identify the certificate. 
+     * It gets a certificate with a DSA public key algo to sign, WSSignEnvelope shall
+     * detect the algo and set the signature algo accordingly.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testX509SignatureDSA_Autodetect() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("wss4jcertDSA", "security");
+        builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
+        
+        // builder.setUserInfo("john", "keypass");
+        log.info("Before SigningDSA_Autodetect....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with DSA_Autodetect:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After SigningDSA_Autodetect....");
+        verify(signedDoc);
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope using SubjectKeyIdentifier.
+     * This test uses the SubjectKeyIdentifier to identify the certificate. 
+     * It gets a certificate with a RSA public key algo to sign, WSSignEnvelope shall
+     * detect the algo and set the signature algo accordingly.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testX509SignatureRSA_Autodetect() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("wss4jcert", "security");
+        builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
+        
+        // builder.setUserInfo("john", "keypass");
+        log.info("Before SigningRSA_Autodetect....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with RSA Autodetect:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After SigningRSA_Autodetect....");
+        verify(signedDoc);
+    }
+    
+    /**
+     * Verifies the soap envelope
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, null, crypto);
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew13.java b/trunk/test/wssec/TestWSSecurityNew13.java
new file mode 100644
index 0000000..21a37a2
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew13.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+
+import org.apache.xml.security.signature.XMLSignature;
+
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Werner Dittmann (Wern.erDittmann@siemens.com)
+ */
+public class TestWSSecurityNew13 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew13.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew13(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew13.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+ 
+    /**
+     * Test the specific signing mehtod that use UsernameToken values
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testUsernameTokenSigning() throws Exception {
+        Document doc = unsignedEnvelope.getAsDocument();
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setPasswordType(WSConstants.PASSWORD_TEXT);
+        builder.setUserInfo("wernerd", "verySecret");
+        builder.addCreated();
+        builder.addNonce();
+        builder.prepare(doc);
+        
+        WSSecSignature sign = new WSSecSignature();
+        sign.setUsernameToken(builder);
+        sign.setKeyIdentifierType(WSConstants.UT_SIGNING);
+        sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+        log.info("Before signing with UT text....");
+        sign.build(doc, null, secHeader);
+        log.info("Before adding UsernameToken PW Text....");
+        builder.prependToHeader(secHeader);
+        Document signedDoc = doc;
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Message with UserNameToken PW Text:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After adding UsernameToken PW Text....");
+        verify(signedDoc);
+    }
+    
+    /**
+     * Test the specific signing mehtod that use UsernameToken values
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testUsernameTokenSigningDigest() throws Exception {
+        Document doc = unsignedEnvelope.getAsDocument();
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setPasswordType(WSConstants.PASSWORD_DIGEST);
+        builder.setUserInfo("wernerd", "verySecret");
+        builder.addCreated();
+        builder.addNonce();
+        builder.prepare(doc);
+        
+        WSSecSignature sign = new WSSecSignature();
+        sign.setUsernameToken(builder);
+        sign.setKeyIdentifierType(WSConstants.UT_SIGNING);
+        sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+        log.info("Before signing with UT digest....");
+        sign.build(doc, null, secHeader);
+        log.info("Before adding UsernameToken PW Digest....");
+        builder.prependToHeader(secHeader);
+        Document signedDoc = doc;
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Message with UserNameToken PW Digest:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After adding UsernameToken PW Digest....");
+        verify(signedDoc);
+    }
+
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        log.info("Before verifying UsernameToken....");
+        secEngine.processSecurityHeader(doc, null, this, null);
+        log.info("After verifying UsernameToken....");
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("verySecret");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew14.java b/trunk/test/wssec/TestWSSecurityNew14.java
new file mode 100644
index 0000000..1d837bf
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew14.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+
+/**
+ * WS-Security Test Case for using the ThumbprintSHA1 key identifier for
+ * signature and encryption, and the EncryptedKeySHA1 key identifier for encryption.
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew14 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew14.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew14(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew14.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope.
+     * The test uses the ThumbprintSHA1 key identifier type. 
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testX509SignatureThumb() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        builder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+        // builder.setUserInfo("john", "keypass");
+        log.info("Before Signing ThumbprintSHA1....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with ThumbprintSHA1 key identifier:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing ThumbprintSHA1....");
+        verify(signedDoc);
+    }
+
+    /**
+     * Test that signs (twice) and verifies a WS-Security envelope.
+     * The test uses the ThumbprintSHA1 key identifier type.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testDoubleX509SignatureThumb() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        // builder.setUserInfo("john", "keypass");
+        builder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);        
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+        Document signedDoc1 = builder.build(signedDoc, crypto, secHeader);
+        verify(signedDoc1);
+    }
+    
+    /**
+     * Test that encrypts and decrypts a WS-Security envelope.
+     * The test uses the ThumbprintSHA1 key identifier type. 
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in encryption or decryption
+     */
+    public void testX509EncryptionThumb() throws Exception {
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        builder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+        
+        log.info("Before Encrypting ThumbprintSHA1....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);        
+        Document encryptedDoc = builder.build(doc, crypto, secHeader);
+        
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message with THUMBPRINT_IDENTIFIER:");
+            log.debug(outputString);
+        }
+        assertTrue(outputString.indexOf("#ThumbprintSHA1") != -1);
+    
+        log.info("After Encrypting ThumbprintSHA1....");
+        verify(encryptedDoc);
+    }
+        
+    /**
+     * Test that encrypts and decrypts a WS-Security envelope.
+     * The test uses the EncryptedKeySHA1 key identifier type. 
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in encryption or decryption
+     */
+    public void testX509EncryptionSHA1() throws Exception {
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        builder.setKeyIdentifierType(WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER);
+        builder.setUseKeyIdentifier(true);
+     
+        log.info("Before Encrypting EncryptedKeySHA1....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);        
+        Document encryptedDoc = builder.build(doc, crypto, secHeader);
+     
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message with ENCRYPTED_KEY_SHA1_IDENTIFIER:");
+            log.debug(outputString);
+        }
+        assertTrue(outputString.indexOf("#EncryptedKeySHA1") != -1);
+     
+        log.info("After Encrypting EncryptedKeySHA1....");
+        verify(encryptedDoc);
+    }
+
+    /**
+     * Verifies the soap envelope.
+     * This method verfies all the signature generated. 
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+    }
+    
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew15.java b/trunk/test/wssec/TestWSSecurityNew15.java
new file mode 100644
index 0000000..c9a9205
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew15.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.SOAPConstants;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import java.util.Vector;
+
+/**
+ * Test that encrypt and decrypt a WS-Security envelope.
+ * 
+ * This test uses the RSA_15 alogrithm to transport (wrap) the symmetric key.
+ * The test case creates a ReferenceList element that references EncryptedData
+ * elements. The ReferencesList element is put into the Security header, not
+ * as child of the EncryptedKey. The EncryptedData elements contain a KeyInfo
+ * that references the EncryptedKey via a STR/Reference structure.
+ * 
+ * <p/>
+ * 
+ * Refer to OASIS WS Security spec 1.1, chap 7.7
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ * @author Werner Dittmann (werner@apache.org)
+ */
+public class TestWSSecurityNew15 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew15.class);
+
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+            + "   <soapenv:Body>"
+            + "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>"
+            + "   </soapenv:Body>" + "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    static final Crypto crypto = CryptoFactory
+            .getInstance("cryptoSKI.properties");
+
+    MessageContext msgContext;
+
+    Message message;
+
+    /**
+     * TestWSSecurity constructor <p/>
+     * 
+     * @param name
+     *            name of the test
+     */
+    public TestWSSecurityNew15(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew15.class);
+    }
+
+    /**
+     * Main method <p/>
+     * 
+     * @param args
+     *            command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception
+     *             if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that encrypt and decrypt a WS-Security envelope.
+     * 
+     * This test uses the RSA_15 alogrithm to transport (wrap) the symmetric
+     * key.
+     * 
+     * @throws Exception
+     *             Thrown when there is any problem in signing or verification
+     */
+    public void testEncryptionDecryptionRSA15() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("wss4jcert");
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        log.info("Before Encryption Triple DES....");
+
+        /*
+         * Prepare the Encrypt object with the token, setup data structure
+         */
+        builder.prepare(doc, crypto);
+
+        /*
+         * Set up the parts structure to encrypt the body
+         */
+        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
+                .getDocumentElement());
+        Vector parts = new Vector();
+        WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+                .getBodyQName().getLocalPart(), soapConstants.getEnvelopeURI(),
+                "Content");
+        parts.add(encP);
+
+        /*
+         * Encrypt the parts (Body), create EncrypedData elements that reference
+         * the EncryptedKey, and get a ReferenceList that can be put into the
+         * Security header. Be sure that the ReferenceList is after the
+         * EncryptedKey element in the Security header (strict layout)
+         */
+        Element refs = builder.encryptForExternalRef(null, parts);
+        builder.addExternalRefElement(refs, secHeader);
+
+        /*
+         * now add (prepend) the EncryptedKey element, then a
+         * BinarySecurityToken if one was setup during prepare
+         */
+        builder.prependToHeader(secHeader);
+
+        builder.prependBSTElementToHeader(secHeader);
+
+        Document encryptedDoc = doc;
+        log.info("After Encryption Triple DES....");
+
+        /*
+         * convert the resulting document into a message first. The
+         * toAxisMessage() method performs the necessary c14n call to properly
+         * set up the signed document and convert it into a SOAP message. Check
+         * that the contents can't be read (checking if we can find a specific
+         * substring). After that we extract it as a document again for further
+         * processing.
+         */
+
+        Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message, RSA-15 keytransport, 3DES:");
+            XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope()
+                    .getAsDOM(), new PrintWriter(System.out));
+        }
+        String encryptedString = encryptedMsg.getSOAPPartAsString();
+        assertTrue(encryptedString.indexOf("LogTestService2") == -1 ? true
+                : false);
+        encryptedDoc = encryptedMsg.getSOAPEnvelope().getAsDocument();
+        verify(encryptedDoc);
+    }
+
+    /**
+     * Verifies the soap envelope <p/>
+     * 
+     * @param envelope
+     * @throws Exception
+     *             Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        String decryptedString = message.getSOAPPartAsString();
+        if (log.isDebugEnabled()) {
+            System.out.println("\n" + decryptedString + "\n");
+        }
+        assertTrue(decryptedString.indexOf("LogTestService2") > 0 ? true
+                : false);
+    }
+
+    public void handle(Callback[] callbacks) throws IOException,
+            UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for the
+                 * given identifier (e.g. a user name or keystore alias) e.g.:
+                 * pc.setPassword(passStore.getPassword(pc.getIdentfifier)) for
+                 * Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew16.java b/trunk/test/wssec/TestWSSecurityNew16.java
new file mode 100644
index 0000000..a998799
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew16.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.xml.crypto.dsig.SignatureMethod;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.SOAPPart;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecEncryptedKey;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSignature;
+import org.w3c.dom.Document;
+
+
+/**
+ * Test signature created using an encrypted key
+ * SOAP Body is signed and encrypted. In the encryption, The ReferencesList element is 
+ * put into the Encrypted Key, as a child of the EncryptedKey. Signature is created 
+ * using the encrypted key. 
+ */
+public class TestWSSecurityNew16 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew16.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"http://axis/service/security/test6/LogTestService8\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+    MessageContext msgContext;
+    Message message;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew16(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew16.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that first signs, then encrypts a WS-Security envelope.
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is any problem in signing, encryption,
+     *                   decryption, or verification
+     */
+    public void testEncryptedKeySignature() throws Exception {
+        
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        log.info("Before Sign/Encryption....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        WSSecEncryptedKey encrKey = new WSSecEncryptedKey();
+        encrKey.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        encrKey.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        encrKey.setKeySize(192);
+        encrKey.prepare(doc, crypto);   
+        
+        WSSecEncrypt encrypt = new WSSecEncrypt();
+        encrypt.setEncKeyId(encrKey.getId());
+        encrypt.setEphemeralKey(encrKey.getEphemeralKey());
+        encrypt.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
+        encrypt.setEncryptSymmKey(false);
+        encrypt.setEncryptedKeyElement(encrKey.getEncryptedKeyElement());
+
+        WSSecSignature sign = new WSSecSignature();
+        sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
+        sign.setCustomTokenId(encrKey.getId());
+        sign.setSecretKey(encrKey.getEphemeralKey());
+        sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
+
+        Document signedDoc = sign.build(doc, crypto, secHeader);
+        Document encryptedSignedDoc = encrypt.build(signedDoc, crypto, secHeader);
+        /*
+         * convert the resulting document into a message first. The toAxisPMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedSignedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed and encrypted message with IssuerSerial key identifier (both), 3DES:");
+            XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        
+        String s = encryptedMsg.getSOAPPartAsString();
+        ((SOAPPart)message.getSOAPPart()).setCurrentMessage(s, SOAPPart.FORM_STRING);
+                
+        Document encryptedSignedDoc1 = message.getSOAPEnvelope().getAsDocument();
+        log.info("After Sign/Encryption....");
+        verify(encryptedSignedDoc1);
+    }
+
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param doc 
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        if (log.isDebugEnabled()) {
+            log.debug("Verfied and decrypted message:");
+            XMLUtils.PrettyElementToWriter(message.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew17.java b/trunk/test/wssec/TestWSSecurityNew17.java
new file mode 100644
index 0000000..ee5073d
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew17.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.xml.crypto.dsig.SignatureMethod;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.SOAPPart;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecEncryptedKey;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSignature;
+import org.w3c.dom.Document;
+
+
+/**
+ * Test symmetric key signature created using an encrypted key
+ * Demonstrates that Signature Crypto object can have null values when 
+ * calling processSecurityHeader method of WSSecurityEngine.
+ */
+public class TestWSSecurityNew17 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew17.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"http://axis/service/security/test6/LogTestService8\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+    MessageContext msgContext;
+    Message message;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew17(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew17.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that first signs, then encrypts a WS-Security envelope.
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is any problem in signing, encryption,
+     *                   decryption, or verification
+     */
+    public void testEncryptedKeySignature() throws Exception {
+        
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        log.info("Before Sign/Encryption....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        WSSecEncryptedKey encrKey = new WSSecEncryptedKey();
+        encrKey.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        encrKey.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        encrKey.setKeySize(192);
+        encrKey.prepare(doc, crypto);   
+        
+        WSSecEncrypt encrypt = new WSSecEncrypt();
+        encrypt.setEncKeyId(encrKey.getId());
+        encrypt.setEphemeralKey(encrKey.getEphemeralKey());
+        encrypt.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
+        encrypt.setEncryptSymmKey(false);
+        encrypt.setEncryptedKeyElement(encrKey.getEncryptedKeyElement());
+
+        WSSecSignature sign = new WSSecSignature();
+        sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
+        sign.setCustomTokenId(encrKey.getId());
+        sign.setSecretKey(encrKey.getEphemeralKey());
+        sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
+
+        Document signedDoc = sign.build(doc, crypto, secHeader);
+        Document encryptedSignedDoc = encrypt.build(signedDoc, crypto, secHeader);
+        /*
+         * convert the resulting document into a message first. The toAxisPMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedSignedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed and encrypted message with IssuerSerial key identifier (both), 3DES:");
+            XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        
+        String s = encryptedMsg.getSOAPPartAsString();
+        ((SOAPPart)message.getSOAPPart()).setCurrentMessage(s, SOAPPart.FORM_STRING);
+                
+        Document encryptedSignedDoc1 = message.getSOAPEnvelope().getAsDocument();
+        log.info("After Sign/Encryption....");
+        verify(encryptedSignedDoc1);
+    }
+
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param doc 
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, null, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        if (log.isDebugEnabled()) {
+            log.debug("Verfied and decrypted message:");
+            XMLUtils.PrettyElementToWriter(message.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew18.java b/trunk/test/wssec/TestWSSecurityNew18.java
new file mode 100644
index 0000000..7756524
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew18.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew18 extends TestCase {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew18.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew18(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew18.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * The test uses the ThumbprintSHA1 key identifier type.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testX509SignatureIS() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        builder.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
+        builder.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
+        log.info("Before Signing IS....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with IssuerSerial key identifier:");
+            XMLUtils.PrettyElementToWriter(signedDoc.getDocumentElement(), new PrintWriter(System.out));
+        }
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with IssuerSerial key identifier(1):");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing IS....");
+        verify(signedDoc);
+    }
+
+
+    /**
+     * Test that signs (twice) and verifies a WS-Security envelope.
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testDoubleX509SignatureIS() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+        Document signedDoc1 = builder.build(signedDoc, crypto, secHeader);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with IssuerSerial key identifier (Doc1):");
+            XMLUtils.PrettyElementToWriter(signedDoc1.getDocumentElement(), new PrintWriter(System.out));
+        }
+
+        verify(signedDoc1);
+    }
+
+    /**
+     * Verifies the soap envelope.
+     * This method verfies all the signature generated. 
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, null, crypto);
+    }
+    
+    /**
+     * Ensure that we can load a custom crypto implementation using a Map
+     */
+    public void testCustomCrypto() {
+        java.util.Map tmp = new java.util.TreeMap();
+        Crypto crypto = CryptoFactory.getInstance(
+            "wssec.CustomCrypto",
+            tmp
+        );
+        assertNotNull(crypto);
+        assertTrue(crypto instanceof CustomCrypto);
+        CustomCrypto custom = (CustomCrypto)crypto;
+        assertSame(tmp, custom.config);
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew2.java b/trunk/test/wssec/TestWSSecurityNew2.java
new file mode 100644
index 0000000..a73ccd2
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew2.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.WSDataRef;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import java.util.Vector;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew2 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew2.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance("cryptoSKI.properties");
+    static final javax.xml.namespace.QName SOAP_BODY =
+        new javax.xml.namespace.QName(
+            WSConstants.URI_SOAP11_ENV,
+            "Body"
+        );
+    MessageContext msgContext;
+    Message message;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew2(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew2.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that encrypt and decrypt a WS-Security envelope.
+     * This test uses the RSA_15 alogrithm to transport (wrap) the symmetric
+     * key.
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is any problem in signing or verification
+     */
+    public void testEncryptionDecryptionRSA15() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("wss4jcert");
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        log.info("Before Encryption Triple DES....");
+        Document encryptedDoc = builder.build(doc, crypto, secHeader);
+        log.info("After Encryption Triple DES....");
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. Check that the contents can't
+          * be read (cheching if we can find a specific substring). After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message, RSA-15 keytransport, 3DES:");
+            XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        String encryptedString = encryptedMsg.getSOAPPartAsString();
+        assertTrue(encryptedString.indexOf("LogTestService2") == -1 ? true : false);
+        encryptedDoc = encryptedMsg.getSOAPEnvelope().getAsDocument();
+        verify(encryptedDoc, SOAP_BODY);
+
+        /*
+         * second run, same Junit set up, but change encryption method, 
+         * key identification, encryption mode (Element now), and data to encrypt.
+         * This tests if several runs of different algorithms on same builder/cipher 
+         * setup are ok.
+         */
+        message = getSOAPMessage(); // create fresh message envrionment
+        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        builder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+        Vector parts = new Vector();
+        WSEncryptionPart encP =
+            new WSEncryptionPart("testMethod", "uri:LogTestService2", "Element");
+        parts.add(encP);
+        builder.setParts(parts);
+        unsignedEnvelope = message.getSOAPEnvelope();
+        doc = unsignedEnvelope.getAsDocument();
+        secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);        
+        log.info("Before Encryption AES 128/RSA-15....");
+        encryptedDoc = builder.build(doc, crypto, secHeader);
+        log.info("After Encryption AES 128/RSA-15....");
+        encryptedMsg = (Message) SOAPUtil.toAxisMessage(encryptedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message, RSA-15 keytransport, AES 128:");
+            XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        encryptedString = encryptedMsg.getSOAPPartAsString();
+        assertTrue(encryptedString.indexOf("LogTestService2") == -1 ? true : false);
+        encryptedDoc = encryptedMsg.getSOAPEnvelope().getAsDocument();
+        verify(
+            encryptedDoc,
+            new javax.xml.namespace.QName(
+                "uri:LogTestService2",
+                "testMethod"
+            )
+        );
+    }
+
+    /**
+     * Test that encrypt and decrypt a WS-Security envelope.
+     * This test uses the RSA OAEP alogrithm to transport (wrap) the symmetric
+     * key.
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is any problem in signing or verification
+     */
+     public void testEncryptionDecryptionOAEP() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("wss4jcert");
+        builder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
+        builder.setKeyEnc(WSConstants.KEYTRANSPORT_RSAOEP);
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);        
+        log.info("Before Encryption Triple DES/RSA-OAEP....");
+        Document encryptedDoc = builder.build(doc, crypto, secHeader);
+        log.info("After Encryption Triple DES/RSA-OAEP....");
+
+        Message encryptedMsg = (Message) SOAPUtil.toAxisMessage(encryptedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message, RSA-OAEP keytransport, 3DES:");
+            XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        String encryptedString = encryptedMsg.getSOAPPartAsString();
+        assertTrue(encryptedString.indexOf("LogTestService2") == -1 ? true : false);
+        encryptedDoc = encryptedMsg.getSOAPEnvelope().getAsDocument();
+        verify(encryptedDoc, SOAP_BODY);
+
+    }
+    
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param envelope 
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private void verify(
+        Document doc,
+        javax.xml.namespace.QName expectedEncryptedElement
+    ) throws Exception {
+        final java.util.List results = secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        String decryptedString = message.getSOAPPartAsString();
+        assertTrue(decryptedString.indexOf("LogTestService2") > 0 ? true : false);
+        //
+        // walk through the results, and make sure there is an encrytion [sic] 
+        // action, together with a reference to the decrypted element 
+        // (as a QName)
+        //
+        boolean encrypted = false;
+        for (java.util.Iterator ipos = results.iterator(); ipos.hasNext();) {
+            final java.util.Map result = (java.util.Map) ipos.next();
+            final Integer action = (Integer) result.get(WSSecurityEngineResult.TAG_ACTION);
+            assertNotNull(action);
+            if ((action.intValue() & WSConstants.ENCR) != 0) {
+                final java.util.List refs =
+                    (java.util.List) result.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
+                assertNotNull(refs);
+                encrypted = true;
+                for (java.util.Iterator jpos = refs.iterator(); jpos.hasNext();) {
+                    final WSDataRef ref = (WSDataRef) jpos.next();
+                    assertNotNull(ref);
+                    assertNotNull(ref.getName());
+                    assertEquals(
+                        expectedEncryptedElement,
+                        ref.getName()
+                    );
+                }
+            }
+        }
+        assertTrue(encrypted);
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew3.java b/trunk/test/wssec/TestWSSecurityNew3.java
new file mode 100644
index 0000000..030c604
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew3.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew3 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew3.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew3(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew3.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testX509Signature() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        log.info("Before Signing....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, CryptoFactory.getInstance(), secHeader);
+
+         /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing....");
+        verify(signedDoc);
+    }
+
+    /**
+     * Test that signs (twice) and verifies a WS-Security envelope
+     * <p>
+     * @throws  java.lang.Exception  Thrown when there is any problem in signing or verification
+     public void testDoubleX509Signature() throws Exception {
+     SOAPEnvelope envelope = null;
+     WSSignEnvelope builder = new WSSignEnvelope();
+     Document doc = unsignedEnvelope.getAsDocument();
+     Document signedDoc = builder.build(doc);
+     signedDoc =  builder.build(signedDoc);
+     verify(signedDoc);
+     }
+     */
+
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("password");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew5.java b/trunk/test/wssec/TestWSSecurityNew5.java
new file mode 100644
index 0000000..0f35959
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew5.java
@@ -0,0 +1,468 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+
+/**
+ * WS-Security Test Case for UsernameTokens.
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew5 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew5.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew5(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew5.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test that adds a UserNameToken with password Digest to a WS-Security envelope
+     * <p/>
+     */
+    public void testUsernameTokenDigest() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setUserInfo("wernerd", "verySecret");
+        log.info("Before adding UsernameToken PW Digest....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Message with UserNameToken PW Digest:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After adding UsernameToken PW Digest....");
+        verify(signedDoc);
+    }
+    
+    /**
+     * Test that a bad username with password digest does not leak whether the username
+     * is valid or not - see WSS-141.
+     */
+    public void testUsernameTokenBadUsername() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setUserInfo("badusername", "verySecret");
+        log.info("Before adding UsernameToken PW Digest....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Message with UserNameToken PW Digest:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After adding UsernameToken PW Digest....");
+        try {
+            verify(signedDoc);
+            throw new Exception("Failure expected on a bad username");
+        } catch (WSSecurityException ex) {
+            String message = ex.getMessage();
+            assertTrue(message.indexOf("badusername") == -1);
+            assertTrue(ex.getErrorCode() == WSSecurityException.FAILED_AUTHENTICATION);
+            // expected
+        }
+    }
+    
+    /**
+     * Test that adds a UserNameToken with a bad password Digest to a WS-Security envelope
+     * <p/>
+     */
+    public void testUsernameTokenBadDigest() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setUserInfo("wernerd", "verySecre");
+        log.info("Before adding UsernameToken PW Digest....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Message with UserNameToken PW Digest:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After adding UsernameToken PW Digest....");
+        try {
+            verify(signedDoc);
+            throw new Exception("Failure expected on a bad password digest");
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == WSSecurityException.FAILED_AUTHENTICATION);
+            // expected
+        }
+    }
+
+    /**
+     * Test that adds a UserNameToken with password text to a WS-Security envelope
+     * <p/>
+     */
+    public void testUsernameTokenText() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setPasswordType(WSConstants.PASSWORD_TEXT);
+        builder.setUserInfo("wernerd", "verySecret");
+        log.info("Before adding UsernameToken PW Text....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, secHeader);
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Message with UserNameToken PW Text:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After adding UsernameToken PW Text....");
+        verify(signedDoc);
+    }
+    
+    /**
+     * Test that adds a UserNameToken with (bad) password text to a WS-Security envelope
+     * <p/>
+     */
+    public void testUsernameTokenBadText() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setPasswordType(WSConstants.PASSWORD_TEXT);
+        builder.setUserInfo("wernerd", "verySecre");
+        log.info("Before adding UsernameToken PW Text....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, secHeader);
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Message with UserNameToken PW Text:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After adding UsernameToken PW Text....");
+        
+        try {
+            verify(signedDoc);
+            throw new Exception("Failure expected on a bad password text");
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == WSSecurityException.FAILED_AUTHENTICATION);
+            // expected
+        }
+    }
+    
+    /**
+     * Test with a null token type. This will fail as the default is to reject custom
+     * token types.
+     * <p/>
+     */
+    public void testUsernameTokenCustomFail() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setPasswordType(null);
+        builder.setUserInfo("wernerd", null);
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, secHeader);
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        
+        if (log.isDebugEnabled()) {
+            log.debug("Message with UserNameToken PW Text:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        try {
+            verify(signedDoc);
+            throw new Exception("Custom token types are not permitted");
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == WSSecurityException.FAILED_AUTHENTICATION);
+            // expected
+        }
+    }
+    
+    /**
+     * Test with a null password type. This will pass as the WSSConfig is configured to 
+     * handle custom token types.
+     * <p/>
+     */
+    public void testUsernameTokenCustomPass() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setPasswordType(null);
+        builder.setUserInfo("customUser", null);
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, secHeader);
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        
+        if (log.isDebugEnabled()) {
+            log.debug("Message with UserNameToken PW Text:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        
+        //
+        // Configure so that custom token types are accepted
+        //
+        WSSConfig cfg = WSSConfig.getNewInstance();
+        cfg.setHandleCustomPasswordTypes(true);
+        secEngine.setWssConfig(cfg);
+        verify(signedDoc);
+        
+        //
+        // Go back to default for other tests
+        //
+        cfg.setHandleCustomPasswordTypes(false);
+        secEngine.setWssConfig(cfg);
+    }
+    
+    
+    /**
+     * A test for WSS-66 - the nonce string is null
+     * http://issues.apache.org/jira/browse/WSS-66
+     * "Possible security hole when PasswordDigest is used by client."
+     */
+    public void testNullNonce() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setPasswordType(WSConstants.PASSWORD_DIGEST);
+        builder.setUserInfo("wernerd", "BAD_PASSWORD");
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document utDoc = builder.build(doc, secHeader);
+        
+        //
+        // Manually find the Nonce node and set the content to null
+        //
+        org.w3c.dom.Element elem = builder.getUsernameTokenElement();
+        org.w3c.dom.NodeList list = elem.getElementsByTagName("wsse:Nonce");
+        org.w3c.dom.Node nonceNode = list.item(0);
+        org.w3c.dom.Node childNode = nonceNode.getFirstChild();
+        childNode.setNodeValue("");
+        
+        if (log.isDebugEnabled()) {
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(utDoc);
+            log.debug(outputString);
+        }
+        
+        try {
+            //
+            // Verification should fail as the password is bad
+            //
+            verify(utDoc);
+            throw new Exception("Expected failure due to a bad password");
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == WSSecurityException.FAILED_AUTHENTICATION);
+            // expected
+        }
+    }
+    
+    /**
+     * A test for WSS-66 - the created string is null
+     * http://issues.apache.org/jira/browse/WSS-66
+     * "Possible security hole when PasswordDigest is used by client."
+     */
+    public void testNullCreated() throws Exception {
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setPasswordType(WSConstants.PASSWORD_DIGEST);
+        builder.setUserInfo("wernerd", "BAD_PASSWORD");
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document utDoc = builder.build(doc, secHeader);
+        
+        //
+        // Manually find the Created node and set the content to null
+        //
+        org.w3c.dom.Element elem = builder.getUsernameTokenElement();
+        org.w3c.dom.NodeList list = elem.getElementsByTagName("wsu:Created");
+        org.w3c.dom.Node nonceNode = list.item(0);
+        org.w3c.dom.Node childNode = nonceNode.getFirstChild();
+        childNode.setNodeValue("");
+        
+        if (log.isDebugEnabled()) {
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(utDoc);
+            log.debug(outputString);
+        }
+        
+        try {
+            //
+            // Verification should fail as the password is bad
+            //
+            verify(utDoc);
+            throw new Exception("Expected failure due to a bad password");
+        } catch (WSSecurityException ex) {
+            assertTrue(ex.getErrorCode() == WSSecurityException.FAILED_AUTHENTICATION);
+            // expected
+        }
+    }
+    
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        log.info("Before verifying UsernameToken....");
+        secEngine.processSecurityHeader(doc, null, this, null);
+        log.info("After verifying UsernameToken....");
+    }
+
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN
+                    && "wernerd".equals(pc.getIdentifier())) {
+                    pc.setPassword("verySecret");
+                } else if (
+                    pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN
+                ) {
+                    if ("wernerd".equals(pc.getIdentifier())
+                        && "verySecret".equals(pc.getPassword())) {
+                        return;
+                    } else if ("customUser".equals(pc.getIdentifier())) {
+                        return;
+                    } else {
+                        throw new IOException("Authentication failed");
+                    }
+                }
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew6.java b/trunk/test/wssec/TestWSSecurityNew6.java
new file mode 100644
index 0000000..4ddce33
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew6.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.SOAPPart;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+/**
+ * WS-Security Test Case <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew6 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew6.class);
+
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+            + "   <soapenv:Body>"
+            + "      <ns1:testMethod xmlns:ns1=\"http://axis/service/security/test6/LogTestService6\"></ns1:testMethod>"
+            + "   </soapenv:Body>" + "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    static final Crypto crypto = CryptoFactory.getInstance();
+
+    MessageContext msgContext;
+
+    Message message;
+
+    /**
+     * TestWSSecurity constructor <p/>
+     * 
+     * @param name
+     *            name of the test
+     */
+    public TestWSSecurityNew6(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew6.class);
+    }
+
+    /**
+     * Main method <p/>
+     * 
+     * @param args
+     *            command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception
+     *             if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that encrypts and signs a WS-Security envelope, then performs
+     * verification and decryption <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is any problem in signing, encryption,
+     *             decryption, or verification
+     */
+    public void testEncryptionSigning() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt encrypt = new WSSecEncrypt();
+        WSSecSignature sign = new WSSecSignature();
+        encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
+        sign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        log.info("Before Encryption....");
+        Document doc = unsignedEnvelope.getAsDocument();
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document encryptedDoc = encrypt.build(doc, crypto, secHeader);
+        Document encryptedSignedDoc = sign.build(encryptedDoc, crypto,
+                secHeader);
+        /*
+         * convert the resulting document into a message first. The
+         * toAxisMessage() mehtod performs the necessary c14n call to properly
+         * set up the signed document and convert it into a SOAP message. After
+         * that we extract it as a document again for further processing.
+         */
+
+        Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedSignedDoc);
+        String s = encryptedMsg.getSOAPPartAsString();
+        ((SOAPPart) message.getSOAPPart()).setCurrentMessage(s,
+                SOAPPart.FORM_STRING);
+
+        Document encryptedSignedDoc1 = message.getSOAPEnvelope()
+                .getAsDocument();
+        log.info("After Encryption....");
+        verify(encryptedSignedDoc1);
+    }
+
+    /**
+     * Verifies the soap envelope <p/>
+     * 
+     * @param envelope
+     * @throws Exception
+     *             Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        if (log.isDebugEnabled()) {
+            XMLUtils.PrettyElementToWriter(
+                    message.getSOAPEnvelope().getAsDOM(), new PrintWriter(
+                            System.out));
+        }
+    }
+
+    public void handle(Callback[] callbacks) throws IOException,
+            UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for the
+                 * given identifier (e.g. a user name or keystore alias) e.g.:
+                 * pc.setPassword(passStore.getPassword(pc.getIdentfifier)) for
+                 * Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew7.java b/trunk/test/wssec/TestWSSecurityNew7.java
new file mode 100644
index 0000000..af8bcd8
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew7.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+/**
+ * WS-Security Test Case <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew7 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew7.class);
+
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+            + "   <soapenv:Body>"
+            + "      <ns1:testMethod xmlns:ns1=\"urn:LogTestService7\"></ns1:testMethod>"
+            + "   </soapenv:Body>" + "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    static final Crypto crypto = CryptoFactory.getInstance();
+
+    MessageContext msgContext;
+
+    Message message;
+
+    /**
+     * TestWSSecurity constructor <p/>
+     * 
+     * @param name
+     *            name of the test
+     */
+    public TestWSSecurityNew7(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew7.class);
+    }
+
+    /**
+     * Main method <p/>
+     * 
+     * @param args
+     *            command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception
+     *             if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that encrypt and then again encrypts (Super encryption) WS-Security
+     * envelope and then verifies ist <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is any problem in encryption or
+     *             verification
+     */
+    public void testEncryptionEncryption() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt encrypt = new WSSecEncrypt();
+        encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
+        log.info("Before Encryption....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        Document encryptedDoc = encrypt.build(doc, crypto, secHeader);
+        Document encryptedEncryptedDoc = encrypt.build(encryptedDoc, crypto,
+                secHeader);
+
+        /*
+         * convert the resulting document into a message first. The
+         * toAxisMessage() mehtod performs the necessary c14n call to properly
+         * set up the signed document and convert it into a SOAP message. After
+         * that we extract it as a document again for further processing.
+         */
+
+        Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedEncryptedDoc);
+        encryptedEncryptedDoc = encryptedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Encryption....");
+        verify(encryptedEncryptedDoc);
+    }
+
+    /**
+     * Verifies the soap envelope <p/>
+     * 
+     * @param envelope
+     * @throws Exception
+     *             Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        if (log.isDebugEnabled()) {
+            XMLUtils.PrettyElementToWriter(
+                    message.getSOAPEnvelope().getAsDOM(), new PrintWriter(
+                            System.out));
+        }
+    }
+
+    public void handle(Callback[] callbacks) throws IOException,
+            UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for the
+                 * given identifier (e.g. a user name or keystore alias) e.g.:
+                 * pc.setPassword(passStore.getPassword(pc.getIdentfifier)) for
+                 * Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew8.java b/trunk/test/wssec/TestWSSecurityNew8.java
new file mode 100644
index 0000000..5a75add
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew8.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.SOAPPart;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew8 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew8.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"http://axis/service/security/test6/LogTestService8\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+    MessageContext msgContext;
+    Message message;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew8(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew8.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that first signs, then encrypts a WS-Security envelope.
+     * The test uses the IssuerSerial key identifier to get the keys for
+     * signature and encryption. Encryption uses 3DES.
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is any problem in signing, encryption,
+     *                   decryption, or verification
+     */
+    public void testSigningEncryptionIS3DES() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        
+        WSSecEncrypt encrypt = new WSSecEncrypt();
+        encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
+        encrypt.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        encrypt.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
+
+        WSSecSignature sign = new WSSecSignature();
+        sign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        sign.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+
+        log.info("Before Sign/Encryption....");
+        Document doc = unsignedEnvelope.getAsDocument();
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        Document signedDoc = sign.build(doc, crypto, secHeader);
+        Document encryptedSignedDoc = encrypt.build(signedDoc, crypto, secHeader);
+        /*
+         * convert the resulting document into a message first. The toAxisPMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedSignedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed and encrypted message with IssuerSerial key identifier (both), 3DES:");
+            XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        
+        String s = encryptedMsg.getSOAPPartAsString();
+        ((SOAPPart)message.getSOAPPart()).setCurrentMessage(s, SOAPPart.FORM_STRING);
+                
+        Document encryptedSignedDoc1 = message.getSOAPEnvelope().getAsDocument();
+        log.info("After Sign/Encryption....");
+        verify(encryptedSignedDoc1);
+    }
+
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param doc 
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        if (log.isDebugEnabled()) {
+            log.debug("Verfied and decrypted message:");
+            XMLUtils.PrettyElementToWriter(message.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNew9.java b/trunk/test/wssec/TestWSSecurityNew9.java
new file mode 100644
index 0000000..b1dd7e3
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNew9.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.SOAPPart;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSignature;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+// import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNew9 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNew9.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"http://axis/service/security/test9/LogTestService9\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+    MessageContext msgContext;
+    Message message;
+
+    private static final byte[] key = {
+        (byte)0x31, (byte)0xfd,
+        (byte)0xcb, (byte)0xda,
+        (byte)0xfb, (byte)0xcd,
+        (byte)0x6b, (byte)0xa8,
+        (byte)0xe6, (byte)0x19,
+        (byte)0xa7, (byte)0xbf,
+        (byte)0x51, (byte)0xf7,
+        (byte)0xc7, (byte)0x3e,
+        (byte)0x80, (byte)0xae,
+        (byte)0x98, (byte)0x51,
+        (byte)0xc8, (byte)0x51,
+        (byte)0x34, (byte)0x04,
+    };
+
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNew9(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNew9.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that encrypts and signs a WS-Security envelope, then performs
+     * verification and decryption.
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is any problem in signing, encryption,
+     *                   decryption, or verification
+     */
+    public void testSigningEncryptionEmbedded() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        WSSecEncrypt encrypt = new WSSecEncrypt();
+        WSSecSignature sign = new WSSecSignature();
+        
+        encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
+        encrypt.setKeyIdentifierType(WSConstants.EMBEDDED_KEYNAME);
+        encrypt.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);        
+        encrypt.setKey(key);
+
+        sign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        log.info("Before Encryption....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        encrypt.setDocument(doc);
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);                
+        Document signedDoc = sign.build(doc, crypto, secHeader);
+        Document encryptedSignedDoc = encrypt.build(signedDoc, crypto, secHeader);
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedSignedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message, RSA-OAEP keytransport, 3DES:");
+            XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        String s = encryptedMsg.getSOAPPartAsString();
+        ((SOAPPart)message.getSOAPPart()).setCurrentMessage(s, SOAPPart.FORM_STRING);
+                
+        Document encryptedSignedDoc1 = message.getSOAPEnvelope().getAsDocument();
+        log.info("After Encryption....");
+        verify(encryptedSignedDoc1);
+    }
+
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param doc 
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+    }
+    
+    /* (non-Javadoc)
+     * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
+     */
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                if (pc.getUsage() == WSPasswordCallback.KEY_NAME) {
+                    pc.setKey(key);
+                }
+                else {
+                    pc.setPassword("security");
+                }
+            } else {
+                throw new UnsupportedCallbackException(
+                    callbacks[i],
+                    "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNewDK.java b/trunk/test/wssec/TestWSSecurityNewDK.java
new file mode 100644
index 0000000..d9dbd46
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNewDK.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecDKEncrypt;
+import org.apache.ws.security.message.WSSecDKSign;
+import org.apache.ws.security.message.WSSecEncryptedKey;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.xml.security.signature.XMLSignature;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TestWSSecurityNewDK extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNewDK.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance("cryptoSKI.properties");
+    MessageContext msgContext;
+    Message message;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNewDK(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNewDK.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test encryption using a DerivedKeyToken using TRIPLEDES
+     * @throws Exception Thrown when there is any problem in signing or 
+     * verification
+     */
+    public void testEncryptionDecryptionTRIPLEDES() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        //EncryptedKey
+        WSSecEncryptedKey encrKeyBuilder = new WSSecEncryptedKey();
+        encrKeyBuilder.setUserInfo("wss4jcert");
+        encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+        encrKeyBuilder.prepare(doc, crypto);
+
+        //Key information from the EncryptedKey
+        byte[] ek = encrKeyBuilder.getEphemeralKey();
+        String tokenIdentifier = encrKeyBuilder.getId();  
+        
+        //Derived key encryption
+        WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
+        encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+        encrBuilder.setExternalKey(ek, tokenIdentifier);
+        Document encryptedDoc = encrBuilder.build(doc, secHeader);
+        
+        encrKeyBuilder.prependToHeader(secHeader);
+        encrKeyBuilder.prependBSTElementToHeader(secHeader);
+
+        
+       Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedDoc);
+       if (log.isDebugEnabled()) {
+           log.debug("Encrypted message: 3DES  + DerivedKeys");
+           XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope()
+                    .getAsDOM(), new PrintWriter(System.out));
+       }
+//       String out = org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
+//       System.out.println(out);
+       verify(doc);
+    }
+
+    /**
+     * Test encryption using a DerivedKeyToken using AES128 
+     * @throws Exception Thrown when there is any problem in signing or verification
+     */
+     public void testEncryptionDecryptionAES128() throws Exception {
+         SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+         Document doc = unsignedEnvelope.getAsDocument();
+         WSSecHeader secHeader = new WSSecHeader();
+         secHeader.insertSecurityHeader(doc);
+
+         //EncryptedKey
+         WSSecEncryptedKey encrKeyBuilder = new WSSecEncryptedKey();
+         encrKeyBuilder.setUserInfo("wss4jcert");
+         encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+         encrKeyBuilder.prepare(doc, crypto);
+
+         //Key information from the EncryptedKey
+         byte[] ek = encrKeyBuilder.getEphemeralKey();
+         String tokenIdentifier = encrKeyBuilder.getId();  
+         
+         //Derived key encryption
+         WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
+         encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+         encrBuilder.setExternalKey(ek, tokenIdentifier);
+         Document encryptedDoc = encrBuilder.build(doc, secHeader);
+         
+         encrKeyBuilder.prependToHeader(secHeader);
+         encrKeyBuilder.prependBSTElementToHeader(secHeader);
+         
+        Message encryptedMsg = SOAPUtil.toAxisMessage(encryptedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message: 3DES  + DerivedKeys");
+            XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope()
+                    .getAsDOM(), new PrintWriter(System.out));
+        }
+//        String out = org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
+//        System.out.println(out);
+        verify(doc);
+     }
+     
+     public void testSignature() throws Exception {
+         SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+         Document doc = unsignedEnvelope.getAsDocument();
+         WSSecHeader secHeader = new WSSecHeader();
+         secHeader.insertSecurityHeader(doc);
+
+         //EncryptedKey
+         WSSecEncryptedKey encrKeyBuilder = new WSSecEncryptedKey();
+         encrKeyBuilder.setUserInfo("wss4jcert");
+         encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+         encrKeyBuilder.prepare(doc, crypto);
+
+         //Key information from the EncryptedKey
+         byte[] ek = encrKeyBuilder.getEphemeralKey();
+         String tokenIdentifier = encrKeyBuilder.getId();         
+         
+         //Derived key encryption
+         WSSecDKSign sigBuilder = new WSSecDKSign();
+         sigBuilder.setExternalKey(ek, tokenIdentifier);
+         sigBuilder.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+         /* Document signedDoc = */ sigBuilder.build(doc, secHeader);
+         
+         encrKeyBuilder.prependToHeader(secHeader);
+         encrKeyBuilder.prependBSTElementToHeader(secHeader);
+         
+         Message signedMessage = SOAPUtil.toAxisMessage(doc);
+         if (log.isDebugEnabled()) {
+             log.debug("Encrypted message: 3DES  + DerivedKeys");
+             XMLUtils.PrettyElementToWriter(signedMessage.getSOAPEnvelope()
+                    .getAsDOM(), new PrintWriter(System.out));
+         }
+//         String out = org.apache.ws.security.util.XMLUtils
+//                .PrettyDocumentToString(signedDoc);
+//        System.out.println(out);
+         verify(doc);
+     }
+     
+     public void testSignatureEncrypt() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        //EncryptedKey
+        WSSecEncryptedKey encrKeyBuilder = new WSSecEncryptedKey();
+        encrKeyBuilder.setUserInfo("wss4jcert");
+        encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+        encrKeyBuilder.prepare(doc, crypto);
+
+        //Key information from the EncryptedKey
+        byte[] ek = encrKeyBuilder.getEphemeralKey();
+        String tokenIdentifier = encrKeyBuilder.getId();
+
+        //Derived key encryption
+        WSSecDKSign sigBuilder = new WSSecDKSign();
+        sigBuilder.setExternalKey(ek, tokenIdentifier);
+        sigBuilder.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+        log.info("Before HMAC-SHA1 signature");
+        Document signedDoc = sigBuilder.build(doc, secHeader);
+
+        //Derived key signature
+        WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
+        encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+        encrBuilder.setExternalKey(ek, tokenIdentifier);
+        Document signedEncryptedDoc = encrBuilder.build(signedDoc, secHeader);
+
+        encrKeyBuilder.prependToHeader(secHeader);
+        encrKeyBuilder.prependBSTElementToHeader(secHeader);
+
+        Message signedMessage = SOAPUtil.toAxisMessage(signedEncryptedDoc);
+
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message: 3DES  + DerivedKeys");
+            XMLUtils.PrettyElementToWriter(signedMessage.getSOAPEnvelope()
+                    .getAsDOM(), new PrintWriter(System.out));
+        }
+//        String out = org.apache.ws.security.util.XMLUtils
+//                .PrettyDocumentToString(signedEncryptedDoc);
+//        System.out.println(out);
+        verify(signedEncryptedDoc);
+    }
+     
+     public void testEncryptSignature() throws Exception {
+         SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+         Document doc = unsignedEnvelope.getAsDocument();
+         WSSecHeader secHeader = new WSSecHeader();
+         secHeader.insertSecurityHeader(doc);
+
+         //EncryptedKey
+         WSSecEncryptedKey encrKeyBuilder = new WSSecEncryptedKey();
+         encrKeyBuilder.setUserInfo("wss4jcert");
+         encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
+         encrKeyBuilder.prepare(doc, crypto);
+         
+         //Key information from the EncryptedKey
+         byte[] ek = encrKeyBuilder.getEphemeralKey();
+         String tokenIdentifier = encrKeyBuilder.getId();
+         
+         //Derived key encryption
+         WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
+         encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+         encrBuilder.setExternalKey(ek, tokenIdentifier);
+         encrBuilder.build(doc, secHeader);
+         
+         //Derived key signature
+         WSSecDKSign sigBuilder = new WSSecDKSign();
+         sigBuilder.setExternalKey(ek, tokenIdentifier);
+         sigBuilder.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+         log.info("Before HMAC-SHA1 signature");
+         Document encryptedSignedDoc = sigBuilder.build(doc, secHeader);
+         
+         encrKeyBuilder.prependToHeader(secHeader);
+         encrKeyBuilder.prependBSTElementToHeader(secHeader);
+         
+         Message signedMessage = SOAPUtil.toAxisMessage(encryptedSignedDoc);
+         
+         if (log.isDebugEnabled()) {
+            log.debug("Encrypted message: 3DES  + DerivedKeys");
+            XMLUtils.PrettyElementToWriter(signedMessage.getSOAPEnvelope()
+                    .getAsDOM(), new PrintWriter(System.out));
+        }
+        
+//         String out = org.apache.ws.security.util.XMLUtils
+//                .PrettyDocumentToString(encryptedSignedDoc);
+//         System.out.println(out);
+         verify(encryptedSignedDoc);
+     }
+    
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param envelope 
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        String decryptedString = message.getSOAPPartAsString();
+        assertTrue(decryptedString.indexOf("LogTestService2") > 0 ? true : false);
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNewSCT.java b/trunk/test/wssec/TestWSSecurityNewSCT.java
new file mode 100644
index 0000000..c43f85e
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNewSCT.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2004,2005 The Apache Software Foundation.
+ *
+ * Licensed 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 wssec;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.SecureRandom;
+import java.util.Hashtable;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import junit.framework.TestCase;
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.conversation.ConversationConstants;
+import org.apache.ws.security.message.WSSecDKEncrypt;
+import org.apache.ws.security.message.WSSecDKSign;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSecurityContextToken;
+import org.apache.xml.security.signature.XMLSignature;
+import org.w3c.dom.Document;
+
+/**
+ * Testcase to test WSSecSecurityContextToken
+ * 
+ * @see org.apache.ws.security.message.WSSecSecurityContextToken
+ * 
+ * @author Ruchith Fernando (ruchith.fernando@gmail.com)
+ */
+public class TestWSSecurityNewSCT extends TestCase implements CallbackHandler {
+
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            + "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+            + "   <soapenv:Body>"
+            + "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>"
+            + "   </soapenv:Body>" + "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    static final Crypto crypto = CryptoFactory
+            .getInstance("cryptoSKI.properties");
+
+    MessageContext msgContext;
+
+    Message message;
+
+    /**
+     * Table of secrets idexd by the sct identifiers
+     */
+    private Hashtable secrets = new Hashtable();
+
+    /**
+     * @param arg0
+     */
+    public TestWSSecurityNewSCT(String arg0) {
+        super(arg0);
+    }
+
+    /**
+     * Setup method <p/>
+     * 
+     * @throws Exception
+     *             Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    public void testBuild() {
+        try {
+            SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+            Document doc = unsignedEnvelope.getAsDocument();
+            WSSecHeader secHeader = new WSSecHeader();
+            secHeader.insertSecurityHeader(doc);
+
+            WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken();
+            sctBuilder.prepare(doc, crypto);
+            
+            sctBuilder.prependSCTElementToHeader(doc, secHeader);
+
+            String out = org.apache.ws.security.util.XMLUtils
+                    .PrettyDocumentToString(doc);
+
+            assertTrue(
+                    "SecurityContextToken missing",
+                    out
+                            .indexOf(ConversationConstants.SECURITY_CONTEXT_TOKEN_LN) > 0);
+            assertTrue("wsc:Identifier missing", out
+                    .indexOf(ConversationConstants.IDENTIFIER_LN) > 0);
+
+            // System.out.println(out);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+
+    /**
+     * Test encryption using a derived key which is based on a secret associated
+     * with a security context token
+     */
+    public void testSCTDKTEncrypt() {
+        try {
+            SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+            Document doc = unsignedEnvelope.getAsDocument();
+            WSSecHeader secHeader = new WSSecHeader();
+            secHeader.insertSecurityHeader(doc);
+
+            WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken();
+            sctBuilder.prepare(doc, crypto);
+
+            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+            byte[] tempSecret = new byte[16];
+            random.nextBytes(tempSecret);
+
+            // Store the secret
+            this.secrets.put(sctBuilder.getIdentifier(), tempSecret);
+
+            String tokenId = sctBuilder.getSctId();
+
+            // Derived key encryption
+            WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
+            encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+            encrBuilder.setExternalKey(tempSecret, tokenId);
+            encrBuilder.build(doc, secHeader);
+
+            sctBuilder.prependSCTElementToHeader(doc, secHeader);
+
+            // String out = org.apache.ws.security.util.XMLUtils
+            //          .PrettyDocumentToString(doc);
+            // System.out.println(out);
+
+            verify(doc);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+
+    public void testSCTKDKTSign() {
+        try {
+            SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+            Document doc = unsignedEnvelope.getAsDocument();
+            WSSecHeader secHeader = new WSSecHeader();
+            secHeader.insertSecurityHeader(doc);
+
+            WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken();
+            sctBuilder.prepare(doc, crypto);
+
+            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+            byte[] tempSecret = new byte[16];
+            random.nextBytes(tempSecret);
+
+            // Store the secret
+            this.secrets.put(sctBuilder.getIdentifier(), tempSecret);
+
+            String tokenId = sctBuilder.getSctId();
+
+            // Derived key signature
+            WSSecDKSign sigBuilder = new WSSecDKSign();
+            sigBuilder.setExternalKey(tempSecret, tokenId);
+            sigBuilder.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+            sigBuilder.build(doc, secHeader);
+            
+            sctBuilder.prependSCTElementToHeader(doc, secHeader);
+
+//            String out = org.apache.ws.security.util.XMLUtils
+//                     .PrettyDocumentToString(doc);
+//            System.out.println(out);
+
+            verify(doc);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+    
+    public void testSCTKDKTSignEncrypt() {
+        try {
+            SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+            Document doc = unsignedEnvelope.getAsDocument();
+            WSSecHeader secHeader = new WSSecHeader();
+            secHeader.insertSecurityHeader(doc);
+
+            WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken();
+            sctBuilder.prepare(doc, crypto);
+
+            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+            byte[] tempSecret = new byte[16];
+            random.nextBytes(tempSecret);
+
+            // Store the secret
+            this.secrets.put(sctBuilder.getIdentifier(), tempSecret);
+
+            String tokenId = sctBuilder.getSctId();
+
+            // Derived key signature
+            WSSecDKSign sigBuilder = new WSSecDKSign();
+            sigBuilder.setExternalKey(tempSecret, tokenId);
+            sigBuilder.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+            sigBuilder.build(doc, secHeader);
+
+            // Derived key encryption
+            WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
+            encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+            encrBuilder.setExternalKey(tempSecret, tokenId);
+            encrBuilder.build(doc, secHeader);
+
+            sctBuilder.prependSCTElementToHeader(doc, secHeader);
+
+//            String out = org.apache.ws.security.util.XMLUtils
+//                     .PrettyDocumentToString(doc);
+
+//            System.out.println(out);
+
+            verify(doc);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+
+    public void testSCTKDKTEncryptSign() {
+        try {
+            SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+            Document doc = unsignedEnvelope.getAsDocument();
+            WSSecHeader secHeader = new WSSecHeader();
+            secHeader.insertSecurityHeader(doc);
+
+            WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken();
+            sctBuilder.prepare(doc, crypto);
+
+            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+            byte[] tempSecret = new byte[16];
+            random.nextBytes(tempSecret);
+
+            // Store the secret
+            this.secrets.put(sctBuilder.getIdentifier(), tempSecret);
+
+            String tokenId = sctBuilder.getSctId();
+
+            // Derived key encryption
+            WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
+            encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+            encrBuilder.setExternalKey(tempSecret, tokenId);
+            encrBuilder.build(doc, secHeader);
+
+            // Derived key signature
+            WSSecDKSign sigBuilder = new WSSecDKSign();
+            sigBuilder.setExternalKey(tempSecret, tokenId);
+            sigBuilder.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+            sigBuilder.build(doc, secHeader);
+
+            sctBuilder.prependSCTElementToHeader(doc, secHeader);
+
+//            String out = org.apache.ws.security.util.XMLUtils
+//                     .PrettyDocumentToString(doc);
+//            System.out.println(out);
+
+            verify(doc);
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail(e.getMessage());
+        }
+    }
+    
+    /**
+     * Verifies the soap envelope <p/>
+     * 
+     * @param envelope
+     * @throws Exception
+     *             Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        String decryptedString = message.getSOAPPartAsString();
+        assertTrue(decryptedString.indexOf("LogTestService2") > 0 ? true
+                : false);
+    }
+
+    /**
+     * Constructs a soap envelope <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception
+     *             if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    public void handle(Callback[] callbacks) throws IOException,
+            UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                byte[] secret = (byte[]) this.secrets.get(pc.getIdentifier());
+                pc.setKey(secret);
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i],
+                        "Unrecognized Callback");
+            }
+        }
+    }
+
+}
diff --git a/trunk/test/wssec/TestWSSecurityNewSOAP12.java b/trunk/test/wssec/TestWSSecurityNewSOAP12.java
new file mode 100644
index 0000000..437a0df
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNewSOAP12.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNewSOAP12 extends TestCase {
+    private static Log log = LogFactory.getLog(TestWSSecurityNewSOAP12.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<SOAP-ENV:Body>" + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" + "<value xmlns=\"\">15</value>" + "</add>" + "</SOAP-ENV:Body>\r\n       \r\n" + "</SOAP-ENV:Envelope>";
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNewSOAP12(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNewSOAP12.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test that signs and verifies a WS-Security envelope
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testX509Signature() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        // builder.setUserInfo("john", "keypass");
+        log.info("Before Signing....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);                
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message SOAP 1.2:");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing....");
+        verify(signedDoc);
+    }
+
+    /**
+     * Test that signs (twice) and verifies a WS-Security envelope
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is any problem in signing or verification
+     */
+    public void testDoubleX509Signature() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        // builder.setUserInfo("john", "keypass");
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);                
+
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+        Document signedDoc1 = builder.build(signedDoc, crypto, secHeader);
+        verify(signedDoc1);
+    }
+
+    /**
+     * Verifies the soap envelope
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, null, crypto);
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNewST1.java b/trunk/test/wssec/TestWSSecurityNewST1.java
new file mode 100644
index 0000000..a1003f6
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNewST1.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.ws.security.saml.SAMLIssuerFactory;
+import org.apache.ws.security.saml.SAMLIssuer;
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSAMLToken;
+import org.w3c.dom.Document;
+
+import org.opensaml.SAMLAssertion;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNewST1 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNewST1.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    // static final Crypto crypto = CryptoFactory.getInstance("crypto.properties");
+    MessageContext msgContext;
+    Message message;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNewST1(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNewST1.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that encrypt and decrypt a WS-Security envelope.
+     * This test uses the RSA_15 alogrithm to transport (wrap) the symmetric
+     * key.
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is any problem in signing or verification
+     */
+    public void testSAMLUnsignedSenderVouches() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        SAMLIssuer saml = SAMLIssuerFactory.getInstance("saml.properties");
+
+        SAMLAssertion assertion = saml.newAssertion();
+
+        WSSecSAMLToken wsSign = new WSSecSAMLToken();
+
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        log.info("Before SAMLUnsignedSenderVouches....");
+        
+        Document signedDoc = wsSign.build(doc, assertion, secHeader);
+        log.info("After SAMLUnsignedSenderVouches....");
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. Check that the contents can't
+          * be read (cheching if we can find a specific substring). After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Unsigned SAML message (sender vouches):");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        // String encryptedString = signedMsg.getSOAPPartAsString();
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        verify(signedDoc);
+
+    }
+
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param envelope 
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, null);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        String decryptedString = message.getSOAPPartAsString();
+        assertTrue(decryptedString.indexOf("LogTestService2") > 0 ? true : false);
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNewST2.java b/trunk/test/wssec/TestWSSecurityNewST2.java
new file mode 100644
index 0000000..32e0dd7
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNewST2.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.ws.security.saml.SAMLIssuerFactory;
+import org.apache.ws.security.saml.SAMLIssuer;
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.saml.WSSecSignatureSAML;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import org.opensaml.SAMLAssertion;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNewST2 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNewST2.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    static final Crypto crypto = CryptoFactory.getInstance("crypto.properties");
+    MessageContext msgContext;
+    Message message;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNewST2(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNewST2.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that encrypt and decrypt a WS-Security envelope.
+     * This test uses the RSA_15 alogrithm to transport (wrap) the symmetric
+     * key.
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is any problem in signing or verification
+     */
+    public void testSAMLSignedSenderVouches() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        SAMLIssuer saml = SAMLIssuerFactory.getInstance("saml.properties");
+
+        SAMLAssertion assertion = saml.newAssertion();
+
+        String issuerKeyName = saml.getIssuerKeyName();
+        String issuerKeyPW = saml.getIssuerKeyPassword();
+        Crypto issuerCrypto = saml.getIssuerCrypto();
+        WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
+        wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        
+        log.info("Before SAMLSignedSenderVouches....");
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        Document signedDoc = wsSign.build(doc, null, assertion, issuerCrypto, issuerKeyName, issuerKeyPW, secHeader);
+        log.info("After SAMLSignedSenderVouches....");
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. Check that the contents can't
+         * be read (checking if we can find a specific substring). After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed SAML message (sender vouches):");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        // String encryptedString = signedMsg.getSOAPPartAsString();
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        verify(signedDoc);
+
+    }
+    
+    
+    /**
+     * Test the default issuer class as specified in SAMLIssuerFactory. The configuration
+     * file "saml3.properties" has no "org.apache.ws.security.saml.issuerClass" property,
+     * and so the default value is used (A bad value was previously used for the default
+     * value).
+     */
+    public void testDefaultIssuerClass() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+        SAMLIssuer saml = SAMLIssuerFactory.getInstance("saml3.properties");
+
+        SAMLAssertion assertion = saml.newAssertion();
+
+        String issuerKeyName = saml.getIssuerKeyName();
+        String issuerKeyPW = saml.getIssuerKeyPassword();
+        Crypto issuerCrypto = saml.getIssuerCrypto();
+        WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
+        wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        
+        log.info("Before SAMLSignedSenderVouches....");
+        
+        Document doc = unsignedEnvelope.getAsDocument();
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        Document signedDoc = wsSign.build(doc, null, assertion, issuerCrypto, issuerKeyName, issuerKeyPW, secHeader);
+        log.info("After SAMLSignedSenderVouches....");
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. Check that the contents can't
+         * be read (checking if we can find a specific substring). After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed SAML message (sender vouches):");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        // String encryptedString = signedMsg.getSOAPPartAsString();
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        verify(signedDoc);
+    }
+
+    
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param doc
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        String decryptedString = message.getSOAPPartAsString();
+        assertTrue(decryptedString.indexOf("LogTestService2") > 0 ? true : false);
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityNewST3.java b/trunk/test/wssec/TestWSSecurityNewST3.java
new file mode 100644
index 0000000..c2cd20c
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityNewST3.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.ws.security.saml.SAMLIssuerFactory;
+import org.apache.ws.security.saml.SAMLIssuer;
+import org.apache.ws.security.saml.WSSecSignatureSAML;
+
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecHeader;
+
+import org.w3c.dom.Document;
+
+import org.opensaml.SAMLAssertion;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ * 
+ * @author Davanum Srinivas (dims@yahoo.com)
+ */
+public class TestWSSecurityNewST3 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityNewST3.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+
+    static final Crypto crypto = CryptoFactory.getInstance("crypto.properties");
+    MessageContext msgContext;
+    Message message;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityNewST3(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityNewST3.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        message = getSOAPMessage();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws Exception if there is any problem constructing the soap envelope
+     */
+    protected Message getSOAPMessage() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg;
+    }
+
+    /**
+     * Test that encrypt and decrypt a WS-Security envelope.
+     * This test uses the RSA_15 alogrithm to transport (wrap) the symmetric
+     * key.
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is any problem in signing or verification
+     */
+    public void testSAMLSignedKeyHolder() throws Exception {
+        SOAPEnvelope unsignedEnvelope = message.getSOAPEnvelope();
+
+        Document doc = unsignedEnvelope.getAsDocument();
+        
+        SAMLIssuer saml = SAMLIssuerFactory.getInstance("saml4.properties");
+        // Provide info to SAML issuer that it can construct a Holder-of-key
+        // SAML token.
+        saml.setInstanceDoc(doc);
+        saml.setUserCrypto(crypto);
+        saml.setUsername("16c73ab6-b892-458f-abf5-2f875f74882e");
+        SAMLAssertion assertion = saml.newAssertion();
+
+        WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
+        wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        wsSign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+
+        log.info("Before SAMLSignedKeyHolder....");
+        
+        /*
+         * set up for keyHolder
+         */
+        Document signedDoc = wsSign.build(doc, crypto, assertion, null, null, null, secHeader);
+        log.info("After SAMLSignedKeyHolder....");
+
+        /*
+         * convert the resulting document into a message first. The toAxisMessage()
+         * method performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. Check that the contents can't
+          * be read (cheching if we can find a specific substring). After that we extract it
+         * as a document again for further processing.
+         */
+
+        Message signedMsg = SOAPUtil.toAxisMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed SAML message (key holder):");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        // String encryptedString = signedMsg.getSOAPPartAsString();
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        verify(signedDoc);
+
+    }
+
+    
+    /**
+     * Verifies the soap envelope
+     * <p/>
+     * 
+     * @param envelope 
+     * @throws Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+        SOAPUtil.updateSOAPMessage(doc, message);
+        String decryptedString = message.getSOAPPartAsString();
+        assertTrue(decryptedString.indexOf("LogTestService2") > 0 ? true : false);
+    }
+
+    public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityUTDK.java b/trunk/test/wssec/TestWSSecurityUTDK.java
new file mode 100644
index 0000000..93218df
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityUTDK.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecDKEncrypt;
+import org.apache.ws.security.message.WSSecDKSign;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.processor.Processor;
+import org.apache.ws.security.processor.UsernameTokenProcessor;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.signature.XMLSignature;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import java.util.Vector;
+
+/**
+ * WS-Security Test Case for UsernameToken Key Derivation, as defined in the 
+ * UsernameTokenProfile 1.1 specification. Note that the processing of UsernameTokens
+ * with derived keys is not yet supported.
+ */
+public class TestWSSecurityUTDK extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityUTDK.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto crypto = CryptoFactory.getInstance();
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityUTDK(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityUTDK.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Unit test for the UsernameToken derived key functionality 
+     */
+    public void testUsernameTokenUnit() throws Exception {
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        UsernameToken usernameToken = new UsernameToken(true, doc, null);
+        usernameToken.setName("bob");
+        
+        byte[] salt = usernameToken.addSalt(doc, null, false);
+        assertTrue(salt.length == 16);
+        assertTrue(salt[15] == 0x02);
+        byte[] utSalt = usernameToken.getSalt();
+        assertTrue(salt.length == utSalt.length);
+        for (int i = 0; i < salt.length; i++) {
+            assertTrue(salt[i] == utSalt[i]);
+        }
+        
+        usernameToken.addIteration(doc, 500);
+        assertTrue(usernameToken.getIteration() == 500);
+        
+        WSSecurityUtil.prependChildElement(
+            doc, secHeader.getSecurityHeader(), usernameToken.getElement(), false
+        );
+        
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
+        assertTrue(outputString.indexOf("wsse:Username") != -1);
+        assertTrue(outputString.indexOf("wsse:Password") == -1);
+        assertTrue(outputString.indexOf("wsse11:Salt") != -1);
+        assertTrue(outputString.indexOf("wsse11:Iteration") != -1);
+        
+        byte[] derivedKey = UsernameToken.generateDerivedKey("security", salt, 500);
+        assertTrue(derivedKey.length == 20);
+        
+    }
+    
+
+    /**
+     * Test using a UsernameToken derived key for encrypting a SOAP body
+     */
+    public void testDerivedKeyEncryption() throws Exception {
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setUserInfo("bob", "security");
+        builder.addDerivedKey(false, null, 1000);
+        builder.prepare(doc);
+        
+        byte[] derivedKey = builder.getDerivedKey();
+        assertTrue(derivedKey.length == 20);
+        
+        String tokenIdentifier = builder.getId();
+        
+        //
+        // Derived key encryption
+        //
+        WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
+        encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
+        encrBuilder.setExternalKey(derivedKey, tokenIdentifier);
+        Document encryptedDoc = encrBuilder.build(doc, secHeader);
+        
+        builder.prependToHeader(secHeader);
+        
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
+        assertTrue(outputString.indexOf("wsse:Username") != -1);
+        assertTrue(outputString.indexOf("wsse:Password") == -1);
+        assertTrue(outputString.indexOf("wsse11:Salt") != -1);
+        assertTrue(outputString.indexOf("wsse11:Iteration") != -1);
+        if (log.isDebugEnabled()) {
+            log.debug(outputString);
+        }
+        
+        // verify(encryptedDoc);
+    }
+    
+    /**
+     * Test using a UsernameToken derived key for signing a SOAP body
+     */
+    public void testDerivedKeySignature() throws Exception {
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        
+        WSSecUsernameToken builder = new WSSecUsernameToken();
+        builder.setUserInfo("bob", "security");
+        builder.addDerivedKey(true, null, 1000);
+        builder.prepare(doc);
+        
+        byte[] derivedKey = builder.getDerivedKey();
+        assertTrue(derivedKey.length == 20);
+        
+        String tokenIdentifier = builder.getId();
+        
+        //
+        // Derived key encryption
+        //
+        WSSecDKSign sigBuilder = new WSSecDKSign();
+        sigBuilder.setExternalKey(derivedKey, tokenIdentifier);
+        sigBuilder.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+        Document signedDoc = sigBuilder.build(doc, secHeader);
+        
+        builder.prependToHeader(secHeader);
+        
+        String outputString = 
+            org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+        assertTrue(outputString.indexOf("wsse:Username") != -1);
+        assertTrue(outputString.indexOf("wsse:Password") == -1);
+        assertTrue(outputString.indexOf("wsse11:Salt") != -1);
+        assertTrue(outputString.indexOf("wsse11:Iteration") != -1);
+        if (log.isDebugEnabled()) {
+            log.debug(outputString);
+        }
+        
+        // verify(signedDoc);
+    }
+    
+    /**
+     * Verifies the soap envelope.
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, crypto);
+    }
+    
+    
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                //
+                // Do nothing
+                //
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+
+}
diff --git a/trunk/test/wssec/TestWSSecurityUserProcessor.java b/trunk/test/wssec/TestWSSecurityUserProcessor.java
new file mode 100644
index 0000000..09d322c
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityUserProcessor.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.action.Action;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoBase;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.handler.WSHandler;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.message.WSSecSignature;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.processor.Processor;
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+
+/**
+ * WS-Security Test Case
+ * <p/>
+ */
+public class TestWSSecurityUserProcessor extends TestCase {
+    private static Log log = LogFactory.getLog(TestWSSecurityUserProcessor.class);
+    static final String NS = "http://www.w3.org/2000/09/xmldsig#";
+    static final String soapMsg = 
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 
+        + "<SOAP-ENV:Envelope "
+        +   "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+        +   "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
+        +   "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" 
+        +   "<SOAP-ENV:Body>" 
+        +       "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">" 
+        +           "<value xmlns=\"\">15</value>" 
+        +       "</add>" 
+        +   "</SOAP-ENV:Body>" 
+        + "</SOAP-ENV:Envelope>";
+
+    static final Crypto crypto = CryptoFactory.getInstance();
+
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityUserProcessor(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityUserProcessor.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws java.lang.Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test to see that a custom processor configured through a
+     * WSSConfig instance is called
+     */
+    public void 
+    testCustomUserProcessor() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
+        builder.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
+        log.info("Before Signing IS....");
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, crypto, secHeader);
+
+        /*
+         * convert the resulting document into a message first. The toSOAPMessage()
+         * mehtod performs the necessary c14n call to properly set up the signed
+         * document and convert it into a SOAP message. After that we extract it
+         * as a document again for further processing.
+         */
+
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with IssuerSerial key identifier:");
+            XMLUtils.PrettyElementToWriter(signedDoc.getDocumentElement(), new PrintWriter(System.out));
+        }
+        Message signedMsg = (Message) SOAPUtil.toSOAPMessage(signedDoc);
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with IssuerSerial key identifier(1):");
+            XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
+        }
+        signedDoc = signedMsg.getSOAPEnvelope().getAsDocument();
+        log.info("After Signing IS....");
+        //
+        // Check to make sure we can install/replace and use our own processor
+        //
+        WSSConfig cfg = WSSConfig.getNewInstance();
+        String p = "wssec.MyProcessor";
+        cfg.setProcessor(
+            WSSecurityEngine.SIGNATURE,
+            p
+        );
+        final WSSecurityEngine engine = new WSSecurityEngine();
+        engine.setWssConfig(cfg);
+        final java.util.List results = 
+            engine.processSecurityHeader(doc, null, null, crypto);
+        boolean found = false;
+        for (final java.util.Iterator pos = results.iterator();  pos.hasNext(); ) {
+            final java.util.Map result = (java.util.Map) pos.next();
+            Object obj = result.get("foo");
+            if (obj != null) {
+                if (obj.getClass().getName().equals(p)) {
+                    found = true;
+                }
+            }
+        }
+        assertTrue("Unable to find result from MyProcessor", found);
+    }
+    
+    /**
+     * Test to see that a custom action configured through a
+     * WSSConfig instance is called
+     */
+    public void
+    testCustomAction() throws Exception {
+        
+        final WSSConfig cfg = WSSConfig.getNewInstance();
+        final int action = 0xDEADF000;
+        cfg.setAction(action, "wssec.MyAction");
+        final RequestData reqData = new RequestData();
+        reqData.setWssConfig(cfg);
+        reqData.setMsgContext(new java.util.TreeMap());
+        
+        final java.util.Vector actions = new java.util.Vector();
+        actions.add(new Integer(action));
+        final Document doc = unsignedEnvelope.getAsDocument();
+        MyHandler handler = new MyHandler();
+        reqData.setMsgContext("bread");
+        assertEquals(reqData.getMsgContext(), "bread");
+        handler.doit(
+            action, 
+            doc, 
+            reqData, 
+            actions
+        );
+        assertEquals(reqData.getMsgContext(), "crumb");
+    }
+    
+    /**
+     * a trivial extension of the WSHandler type
+     */
+    public static class MyHandler extends WSHandler {
+        
+        public Object 
+        getOption(String key) {
+            return null;
+        }
+        
+        public void 
+        setProperty(
+            Object msgContext, 
+            String key, 
+            Object value
+        ) {
+        }
+
+        public Object 
+        getProperty(Object ctx, String key) {
+            return null;
+        }
+    
+        public void 
+        setPassword(Object msgContext, String password) {
+        }
+        
+        public String 
+        getPassword(Object msgContext) {
+            return null;
+        }
+
+        void doit(
+            int action, 
+            Document doc,
+            RequestData reqData, 
+            java.util.Vector actions
+        ) throws org.apache.ws.security.WSSecurityException {
+            doSenderAction(
+                action, 
+                doc, 
+                reqData, 
+                actions,
+                true
+            );
+        }
+    }
+}
diff --git a/trunk/test/wssec/TestWSSecurityX509v1.java b/trunk/test/wssec/TestWSSecurityX509v1.java
new file mode 100644
index 0000000..d719844
--- /dev/null
+++ b/trunk/test/wssec/TestWSSecurityX509v1.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright  2003-2004 The Apache Software Foundation.
+ *
+ *  Licensed 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.client.AxisClient;
+import org.apache.axis.configuration.NullProvider;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSEncryptionPart;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.message.WSSecEncrypt;
+import org.apache.ws.security.message.WSSecHeader;
+import org.apache.ws.security.message.WSSecSignature;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+
+import java.util.Vector;
+
+/**
+ * WS-Security Test Case for X509v1 certificates. The WS-Security 1.1 X.509 specification adds 
+ * support for X.509 V1 certificates. This test code verifies that the ValueType attribute gets 
+ * set correctly in the BinarySecurityToken and Reference elements.
+ */
+public class TestWSSecurityX509v1 extends TestCase implements CallbackHandler {
+    private static Log log = LogFactory.getLog(TestWSSecurityX509v1.class);
+    static final String soapMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
+            "   <soapenv:Body>" +
+            "      <ns1:testMethod xmlns:ns1=\"uri:LogTestService2\"></ns1:testMethod>" +
+            "   </soapenv:Body>" +
+            "</soapenv:Envelope>";
+
+    static final WSSecurityEngine secEngine = new WSSecurityEngine();
+    static final Crypto v1Crypto = CryptoFactory.getInstance("x509v1.properties");
+    MessageContext msgContext;
+    SOAPEnvelope unsignedEnvelope;
+
+    /**
+     * TestWSSecurity constructor
+     * <p/>
+     * 
+     * @param name name of the test
+     */
+    public TestWSSecurityX509v1(String name) {
+        super(name);
+    }
+
+    /**
+     * JUnit suite
+     * <p/>
+     * 
+     * @return a junit test suite
+     */
+    public static Test suite() {
+        return new TestSuite(TestWSSecurityX509v1.class);
+    }
+
+    /**
+     * Main method
+     * <p/>
+     * 
+     * @param args command line args
+     */
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(suite());
+    }
+
+    /**
+     * Setup method
+     * <p/>
+     * 
+     * @throws Exception Thrown when there is a problem in setup
+     */
+    protected void setUp() throws Exception {
+        AxisClient tmpEngine = new AxisClient(new NullProvider());
+        msgContext = new MessageContext(tmpEngine);
+        unsignedEnvelope = getSOAPEnvelope();
+    }
+
+    /**
+     * Constructs a soap envelope
+     * <p/>
+     * 
+     * @return soap envelope
+     * @throws java.lang.Exception if there is any problem constructing the soap envelope
+     */
+    protected SOAPEnvelope getSOAPEnvelope() throws Exception {
+        InputStream in = new ByteArrayInputStream(soapMsg.getBytes());
+        Message msg = new Message(in);
+        msg.setMessageContext(msgContext);
+        return msg.getSOAPEnvelope();
+    }
+
+    /**
+     * Test for a X509 V1 certificate used for signature/verification.
+     */
+    public void testX509v1Signature() throws Exception {
+        WSSecSignature builder = new WSSecSignature();
+        builder.setUserInfo("x509v1cert", "security");
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);
+        Document signedDoc = builder.build(doc, v1Crypto, secHeader);
+        
+        if (log.isDebugEnabled()) {
+            log.debug("Signed message with BST_DIRECT_REFERENCE:");
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+            log.debug(outputString);
+            assertTrue(outputString.indexOf("#X509v1") != -1);
+            assertTrue(outputString.indexOf("#X509v3") == -1);
+        }
+        
+        verify(signedDoc);
+    }
+    
+    /**
+     * Test for a X509 V1 certificate used for encryption/decryption
+     */
+    public void testX509v1Encryption() throws Exception {
+        WSSecEncrypt builder = new WSSecEncrypt();
+        builder.setUserInfo("x509v1cert");
+        builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+        Document doc = unsignedEnvelope.getAsDocument();
+        WSSecHeader secHeader = new WSSecHeader();
+        secHeader.insertSecurityHeader(doc);        
+        Document encryptedDoc = builder.build(doc, v1Crypto, secHeader);
+        
+        if (log.isDebugEnabled()) {
+            log.debug("Encrypted message with BST_DIRECT_REFERENCE:");
+            String outputString = 
+                org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(encryptedDoc);
+            log.debug(outputString);
+            assertTrue(outputString.indexOf("#X509v1") != -1);
+            assertTrue(outputString.indexOf("#X509v3") == -1);
+        }
+        
+        verify(encryptedDoc);
+    }
+    
+    /**
+     * Test for a X509 V1 certificate used for encryption/decryption.
+     * This time a KeyIdentifier is used. This test should fail as the
+     * X.509 1.1 specification states that a KeyIdentifier should only
+     * reference a V3 certificate.
+     */
+    public void testX509v1KeyIdentifier() throws Exception {
+        try {
+            WSSecEncrypt builder = new WSSecEncrypt();
+            builder.setUserInfo("x509v1cert");
+            builder.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
+            Document doc = unsignedEnvelope.getAsDocument();
+            WSSecHeader secHeader = new WSSecHeader();
+            secHeader.insertSecurityHeader(doc);        
+            Document encryptedDoc = builder.build(doc, v1Crypto, secHeader);
+            fail("Expected failure when using an X509#v1 certificate with SKI");
+        } catch (WSSecurityException ex) {
+            // expected
+            assertTrue(ex.getMessage().indexOf(
+                "An X509 certificate with version 3 must be used for SKI")
+                != -1
+            );
+        }
+    }
+    
+    
+    /**
+     * Verifies the soap envelope.
+     * 
+     * @param env soap envelope
+     * @throws java.lang.Exception Thrown when there is a problem in verification
+     */
+    private void verify(Document doc) throws Exception {
+        secEngine.processSecurityHeader(doc, null, this, v1Crypto);
+    }
+    
+    
+    public void handle(Callback[] callbacks)
+        throws IOException, UnsupportedCallbackException {
+        for (int i = 0; i < callbacks.length; i++) {
+            if (callbacks[i] instanceof WSPasswordCallback) {
+                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+                /*
+                 * here call a function/method to lookup the password for
+                 * the given identifier (e.g. a user name or keystore alias)
+                 * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+                 * for Testing we supply a fixed name here.
+                 */
+                pc.setPassword("security");
+            } else {
+                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+            }
+        }
+    }
+
+}
diff --git a/trunk/test/x509v1.properties b/trunk/test/x509v1.properties
new file mode 100644
index 0000000..d1bef40
--- /dev/null
+++ b/trunk/test/x509v1.properties
@@ -0,0 +1,4 @@
+org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+org.apache.ws.security.crypto.merlin.keystore.type=jks
+org.apache.ws.security.crypto.merlin.keystore.password=security
+org.apache.ws.security.crypto.merlin.file=keys/x509v1.keystore
diff --git a/trunk/tools/changelog.xsl b/trunk/tools/changelog.xsl
new file mode 100644
index 0000000..c96073c
--- /dev/null
+++ b/trunk/tools/changelog.xsl
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<xsl:stylesheet
+    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+    version='1.0'>
+
+<!--
+ The Apache Software License, Version 1.1
+
+ Copyright (c) 2002 The Apache Software Foundation.  All rights
+ reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+ 3. The end-user documentation included with the redistribution, if
+    any, must include the following acknowlegement:
+       "This product includes software developed by the
+        Apache Software Foundation (http://www.apache.org/)."
+    Alternately, this acknowlegement may appear in the software itself,
+    if and wherever such third-party acknowlegements normally appear.
+
+ 4. The names "The Jakarta Project", "Ant", and "Apache Software
+    Foundation" must not be used to endorse or promote products derived
+    from this software without prior written permission. For written
+    permission, please contact apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache"
+    nor may "Apache" appear in their names without prior written
+    permission of the Apache Group.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+ ====================================================================
+
+ This software consists of voluntary contributions made by many
+ individuals on behalf of the Apache Software Foundation.  For more
+ information on the Apache Software Foundation, please see
+ <http://www.apache.org/>.
+ -->
+  <xsl:param name="title"/>
+  <xsl:param name="module"/>
+  <xsl:param name="cvsweb"/>
+
+  <xsl:output method="html" indent="yes"  encoding="US-ASCII"/>
+
+  <!-- Copy standard document elements.  Elements that
+       should be ignored must be filtered by apply-templates
+       tags. -->
+  <xsl:template match="*">
+    <xsl:copy>
+      <xsl:copy-of select="attribute::*[. != '']"/>
+      <xsl:apply-templates/>
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="changelog">
+    <HTML>
+      <HEAD>
+        <TITLE><xsl:value-of select="$title"/></TITLE>
+        <link href="axis.css" rel="stylesheet" type="text/css"></link>
+      </HEAD>
+      <BODY link="#000000" alink="#000000" vlink="#000000" text="#000000">
+          <h1>
+            <a name="top"><xsl:value-of select="$title"/></a>
+          </h1>
+          <p align="right">Designed for use with <a href="http://jakarta.apache.org">Ant</a>.</p>
+          <hr size="2"/>
+        <TABLE BORDER="0" WIDTH="100%" CELLPADDING="3" CELLSPACING="1">
+          
+          <xsl:apply-templates select=".//entry">
+            <xsl:sort select="date" data-type="text" order="descending"/>
+            <xsl:sort select="time" data-type="text" order="descending"/>
+          </xsl:apply-templates>
+          
+        </TABLE>
+        
+      </BODY>
+    </HTML>
+  </xsl:template>
+  
+  <xsl:template match="entry">
+    <TR>
+      <TD colspan="2" class="dateAndAuthor">
+        <xsl:value-of select="date"/><xsl:text> </xsl:text><xsl:value-of select="time"/><xsl:text> </xsl:text><xsl:value-of select="author"/>
+      </TD>
+    </TR>
+    <TR>
+      <TD width="20">
+        <xsl:text>    </xsl:text>
+      </TD>
+      <TD>
+        <pre>
+<xsl:apply-templates select="msg"/></pre>
+        <ul>
+          <xsl:apply-templates select="file"/>
+        </ul>
+      </TD>
+    </TR>
+  </xsl:template>
+
+  <xsl:template match="date">
+    <i><xsl:value-of select="."/></i>
+  </xsl:template>
+
+  <xsl:template match="time">
+    <i><xsl:value-of select="."/></i>
+  </xsl:template>
+
+  <xsl:template match="author">
+    <i>
+      <a>
+        <xsl:attribute name="href">mailto:<xsl:value-of select="."/></xsl:attribute>
+        <xsl:value-of select="."/>
+      </a>
+    </i>
+  </xsl:template>
+
+  <xsl:template match="file">
+    <li>
+      <a>
+        <xsl:choose>
+          <xsl:when test="string-length(prevrevision) = 0 ">
+            <xsl:attribute name="href"><xsl:value-of select="$cvsweb"/><xsl:value-of select="$module" />/<xsl:value-of select="name" />?rev=<xsl:value-of select="revision" />&amp;content-type=text/x-cvsweb-markup</xsl:attribute>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:attribute name="href"><xsl:value-of select="$cvsweb"/><xsl:value-of select="$module" />/<xsl:value-of select="name" />?r1=<xsl:value-of select="revision" />&amp;r2=<xsl:value-of select="prevrevision"/></xsl:attribute>
+          </xsl:otherwise>
+        </xsl:choose>
+        <xsl:value-of select="name" /> (<xsl:value-of select="revision"/>)
+      </a>
+    </li>
+  </xsl:template>
+
+  <!-- Any elements within a msg are processed,
+       so that we can preserve HTML tags. -->
+  <xsl:template match="msg">
+    <b><xsl:apply-templates/></b>
+  </xsl:template>
+  
+</xsl:stylesheet>
+
diff --git a/trunk/webapps/axis/EchoHeaders.jws b/trunk/webapps/axis/EchoHeaders.jws
new file mode 100644
index 0000000..aa394af
--- /dev/null
+++ b/trunk/webapps/axis/EchoHeaders.jws
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2002,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.
+ */
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.MessageContext;
+import org.apache.axis.transport.http.HTTPConstants;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Enumeration;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * class to list headers sent in request as a string array
+ */
+public class EchoHeaders {
+
+    /**
+     * demo message context stuff
+     * @return list of request headers
+     */
+    public String[] list() {
+        HttpServletRequest request = getRequest();
+        Enumeration headers=request.getHeaderNames();
+        ArrayList list=new ArrayList();
+        while (headers.hasMoreElements()) {
+            String h = (String) headers.nextElement();
+            String header=h+':'+request.getHeader(h);
+            list.add(header);
+        }
+        String[] results=new String[list.size()];
+        for(int i=0;i<list.size();i++) {
+            results[i]=(String) list.get(i);
+        }
+        return results;
+    }
+
+    /**
+     * get the caller; may involve reverse DNS
+     * @return
+     */
+    public String whoami() {
+        HttpServletRequest request = getRequest();
+        String remote=request.getRemoteHost();
+        return "Hello caller from "+remote;
+    }
+
+    /**
+     * very simple method to echo the param.
+     * @param param
+     * @return
+     */
+    public String echo(String param) {
+        return param;
+    }
+    
+    /**
+     * throw an axis fault with the text included
+     */
+    public void throwAxisFault(String param) throws AxisFault {
+        throw new AxisFault(param);
+    }
+    
+    public void throwException(String param) throws Exception { 
+        throw new Exception(param);
+    }
+
+    /**
+     * thow a runtime exception
+     */
+    public void throwRuntimeException(String param) { 
+        throw new RuntimeException(param);
+    }
+    
+    /**
+     * helper
+     * @return
+     */
+    private HttpServletRequest getRequest() {
+        MessageContext context = MessageContext.getCurrentContext();
+        HttpServletRequest req = (HttpServletRequest) context.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
+        return req;
+    }
+
+}
\ No newline at end of file
diff --git a/trunk/webapps/axis/SOAPMonitorApplet.java b/trunk/webapps/axis/SOAPMonitorApplet.java
new file mode 100644
index 0000000..08b0ce1
--- /dev/null
+++ b/trunk/webapps/axis/SOAPMonitorApplet.java
@@ -0,0 +1,1482 @@
+/*
+ * Copyright 2001,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.net.*;
+import java.text.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import javax.swing.table.*;
+
+import org.apache.axis.monitor.SOAPMonitorConstants;
+
+/**
+ * This is a SOAP Mointor Applet class.  This class provides
+ * the user interface for displaying data from the SOAP
+ * monitor service.
+ *
+ * @author Brian Price (pricebe@us.ibm.com)
+ *
+ */
+public class SOAPMonitorApplet extends JApplet {
+
+    /**
+     * Private data
+     */
+    private JPanel      main_panel = null;
+    private JTabbedPane tabbed_pane = null;
+    private int         port = 0;
+    private Vector      pages = null;
+
+    /**
+     * Constructor
+     */
+    public SOAPMonitorApplet() {
+    }
+
+    /**
+     * Applet initialization
+     */
+    public void init() {
+        // Get the port to be used
+        String port_str = getParameter("port");
+        if (port_str != null) {
+            port = Integer.parseInt(port_str);
+        }
+        // Try to use the system look and feel
+        try {
+           UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+        } catch (Exception e){
+        }
+        // Create main panel to hold notebook
+        main_panel = new JPanel();
+        main_panel.setBackground(Color.white);
+        main_panel.setLayout(new BorderLayout());
+        setContentPane(main_panel);
+        // Create the notebook
+        tabbed_pane = new JTabbedPane(JTabbedPane.TOP);
+        main_panel.add(tabbed_pane,BorderLayout.CENTER);
+        // Add notebook page for default host connection
+        pages = new Vector();
+        addPage(new SOAPMonitorPage(getCodeBase().getHost()));
+    }
+
+    /**
+     * Add a page to the notebook
+     */
+    private void addPage(SOAPMonitorPage pg) {
+        tabbed_pane.addTab("  "+pg.getHost()+"  ", pg);
+        pages.addElement(pg);
+    }
+
+    /** 
+     * Applet is being displayed 
+     */
+    public void start() {
+        // Tell all pages to start talking to the server
+        Enumeration e = pages.elements();
+        while (e.hasMoreElements()) {
+            SOAPMonitorPage pg = (SOAPMonitorPage) e.nextElement();
+            if (pg != null) {
+                pg.start();
+            }
+        }
+    }
+
+    /*
+     * Applet is no longer displayed
+     */
+    public void stop() {
+        // Tell all pages to stop talking to the server
+        Enumeration e = pages.elements();
+        while (e.hasMoreElements()) {
+            SOAPMonitorPage pg = (SOAPMonitorPage) e.nextElement();
+            if (pg != null) {
+                pg.stop();
+            }
+        }
+    }
+
+    /**
+     * Applet cleanup
+     */
+    public void destroy() {
+        tabbed_pane = null;
+        main_panel = null;
+    }
+
+    /**
+     * This class provides the contents of a notebook page
+     * representing a server connection.
+     */
+    class SOAPMonitorPage extends JPanel 
+                          implements Runnable,
+                                     ListSelectionListener,
+                                     ActionListener {
+
+        /**
+         * Status Strings
+         */
+        private final String STATUS_ACTIVE    = "The SOAP Monitor is started.";
+        private final String STATUS_STOPPED   = "The SOAP Monitor is stopped.";
+        private final String STATUS_CLOSED    = "The server communication has been terminated.";
+        private final String STATUS_NOCONNECT = "The SOAP Monitor is unable to communcate with the server.";
+
+        /**
+         * Private data
+         */
+        private String                host = null;
+        private Socket                socket = null;
+        private ObjectInputStream     in = null;
+        private ObjectOutputStream    out = null;
+        private SOAPMonitorTableModel model = null;
+        private JTable                table = null;
+        private JScrollPane           scroll = null;
+        private JPanel                list_panel = null;
+        private JPanel                list_buttons = null;
+        private JButton               remove_button = null;
+        private JButton               remove_all_button = null;
+        private JButton               filter_button = null;
+        private JPanel                details_panel = null;
+        private JPanel                details_header = null;
+        private JSplitPane            details_soap = null;
+        private JPanel                details_buttons = null;
+        private JLabel                details_time = null;
+        private JLabel                details_target = null;
+        private JLabel                details_status = null;
+        private JLabel                details_time_value = null;
+        private JLabel                details_target_value = null;
+        private JLabel                details_status_value = null;
+        private EmptyBorder           empty_border = null;
+        private EtchedBorder          etched_border = null;
+        private JPanel                request_panel = null;
+        private JPanel                response_panel = null;
+        private JLabel                request_label = null;
+        private JLabel                response_label = null;
+        private SOAPMonitorTextArea   request_text = null;
+        private SOAPMonitorTextArea   response_text = null;
+        private JScrollPane           request_scroll = null;
+        private JScrollPane           response_scroll = null;
+        private JButton               layout_button = null;
+        private JSplitPane            split = null;
+        private JPanel                status_area = null;
+        private JPanel                status_buttons = null;
+        private JButton               start_button = null;
+        private JButton               stop_button = null;
+        private JLabel                status_text = null;
+        private JPanel                status_text_panel = null;
+        private SOAPMonitorFilter     filter = null;
+        private GridBagLayout         details_header_layout = null;
+        private GridBagConstraints    details_header_constraints = null;
+        private JCheckBox             reflow_xml = null;
+
+        /**
+         * Constructor (create and layout page)
+         */
+        public SOAPMonitorPage(String host_name) {
+            host = host_name;
+            // Set up default filter (show all messages)
+            filter = new SOAPMonitorFilter();
+            // Use borders to help improve appearance
+            etched_border = new EtchedBorder();
+            // Build top portion of split (list panel) 
+            model = new SOAPMonitorTableModel();
+            table = new JTable(model);
+            table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+            table.setRowSelectionInterval(0,0);
+            table.setPreferredScrollableViewportSize(new Dimension(600, 96));
+            table.getSelectionModel().addListSelectionListener(this);
+            scroll = new JScrollPane(table);
+            remove_button = new JButton("Remove");
+            remove_button.addActionListener(this);
+            remove_button.setEnabled(false);
+            remove_all_button = new JButton("Remove All");
+            remove_all_button.addActionListener(this);
+            filter_button = new JButton("Filter ...");
+            filter_button.addActionListener(this);
+            list_buttons = new JPanel();
+            list_buttons.setLayout(new FlowLayout());
+            list_buttons.add(remove_button);
+            list_buttons.add(remove_all_button);
+            list_buttons.add(filter_button);
+            list_panel = new JPanel();
+            list_panel.setLayout(new BorderLayout());
+            list_panel.add(scroll,BorderLayout.CENTER);
+            list_panel.add(list_buttons, BorderLayout.SOUTH);
+            list_panel.setBorder(empty_border);
+            // Build bottom portion of split (message details) 
+            details_time = new JLabel("Time: ", SwingConstants.RIGHT);
+            details_target = new JLabel("Target Service: ", SwingConstants.RIGHT);
+            details_status = new JLabel("Status: ", SwingConstants.RIGHT);
+            details_time_value = new JLabel();
+            details_target_value = new JLabel();
+            details_status_value = new JLabel();
+            Dimension preferred_size = details_time.getPreferredSize();
+            preferred_size.width = 1;
+            details_time.setPreferredSize(preferred_size); 
+            details_target.setPreferredSize(preferred_size); 
+            details_status.setPreferredSize(preferred_size); 
+            details_time_value.setPreferredSize(preferred_size); 
+            details_target_value.setPreferredSize(preferred_size); 
+            details_status_value.setPreferredSize(preferred_size);
+            details_header = new JPanel();
+            details_header_layout = new GridBagLayout();
+            details_header.setLayout(details_header_layout);
+            details_header_constraints = new GridBagConstraints();
+            details_header_constraints.fill=GridBagConstraints.BOTH;
+            details_header_constraints.weightx=0.5;
+            details_header_layout.setConstraints(details_time,details_header_constraints);
+            details_header.add(details_time);
+            details_header_layout.setConstraints(details_time_value,details_header_constraints);
+            details_header.add(details_time_value);
+            details_header_layout.setConstraints(details_target,details_header_constraints);
+            details_header.add(details_target);
+            details_header_constraints.weightx=1.0;
+            details_header_layout.setConstraints(details_target_value,details_header_constraints);
+            details_header.add(details_target_value);
+            details_header_constraints.weightx=.5;
+            details_header_layout.setConstraints(details_status,details_header_constraints);
+            details_header.add(details_status);
+            details_header_layout.setConstraints(details_status_value,details_header_constraints);
+            details_header.add(details_status_value);
+            details_header.setBorder(etched_border);
+            request_label = new JLabel("SOAP Request", SwingConstants.CENTER);
+            request_text = new SOAPMonitorTextArea();
+            request_text.setEditable(false);
+            request_scroll = new JScrollPane(request_text);
+            request_panel = new JPanel();
+            request_panel.setLayout(new BorderLayout());
+            request_panel.add(request_label, BorderLayout.NORTH);
+            request_panel.add(request_scroll, BorderLayout.CENTER);
+            response_label = new JLabel("SOAP Response", SwingConstants.CENTER);
+            response_text = new SOAPMonitorTextArea();
+            response_text.setEditable(false);
+            response_scroll = new JScrollPane(response_text);
+            response_panel = new JPanel();
+            response_panel.setLayout(new BorderLayout());
+            response_panel.add(response_label, BorderLayout.NORTH);
+            response_panel.add(response_scroll, BorderLayout.CENTER);
+            details_soap = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+            details_soap.setTopComponent(request_panel);
+            details_soap.setRightComponent(response_panel);
+            details_soap.setResizeWeight(.5);
+            details_panel = new JPanel();
+            layout_button = new JButton("Switch Layout");
+            layout_button.addActionListener(this);
+            reflow_xml = new JCheckBox("Reflow XML text");
+            reflow_xml.addActionListener(this);
+            details_buttons = new JPanel();
+            details_buttons.setLayout(new FlowLayout());
+            details_buttons.add(reflow_xml);
+            details_buttons.add(layout_button);
+            details_panel.setLayout(new BorderLayout());
+            details_panel.add(details_header,BorderLayout.NORTH);
+            details_panel.add(details_soap,BorderLayout.CENTER);
+            details_panel.add(details_buttons,BorderLayout.SOUTH);
+            details_panel.setBorder(empty_border);
+            // Add the two parts to the age split pane
+            split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+            split.setTopComponent(list_panel);
+            split.setRightComponent(details_panel);
+            // Build status area
+            start_button = new JButton("Start");
+            start_button.addActionListener(this);
+            stop_button = new JButton("Stop");
+            stop_button.addActionListener(this);
+            status_buttons = new JPanel();
+            status_buttons.setLayout(new FlowLayout());
+            status_buttons.add(start_button);
+            status_buttons.add(stop_button);
+            status_text = new JLabel();
+            status_text.setBorder(new BevelBorder(BevelBorder.LOWERED));
+            status_text_panel = new JPanel();
+            status_text_panel.setLayout(new BorderLayout());
+            status_text_panel.add(status_text, BorderLayout.CENTER);
+            status_text_panel.setBorder(empty_border);
+            status_area = new JPanel();
+            status_area.setLayout(new BorderLayout());
+            status_area.add(status_buttons, BorderLayout.WEST);
+            status_area.add(status_text_panel, BorderLayout.CENTER);
+            status_area.setBorder(etched_border);
+            // Add the split and status area to page
+            setLayout(new BorderLayout());
+            add(split, BorderLayout.CENTER);
+            add(status_area, BorderLayout.SOUTH);
+        }
+
+        /**
+         * Get the name of the host we are displaying
+         */
+        public String getHost() {
+            return host;
+        }
+
+        /**
+         * Set the status text
+         */
+        public void setStatus(String txt) {
+            status_text.setForeground(Color.black);
+            status_text.setText("  "+txt);
+        }
+
+        /**
+         * Set the status text to an error
+         */
+        public void setErrorStatus(String txt) {
+            status_text.setForeground(Color.red);
+            status_text.setText("  "+txt);
+        }
+
+        /**
+         * Start talking to the server
+         */
+        public void start() {
+            String codehost = getCodeBase().getHost();
+            if (socket == null) {
+                try {
+                    // Open the socket to the server
+                    socket = new Socket(codehost, port);
+                    // Create output stream
+                    out = new ObjectOutputStream(socket.getOutputStream());
+                    out.flush();
+                    // Create input stream and start background
+                    // thread to read data from the server
+                    in = new ObjectInputStream(socket.getInputStream());
+                    new Thread(this).start();
+                } catch (Exception e) {
+                    // Exceptions here are unexpected, but we can't
+                    // really do anything (so just write it to stdout
+                    // in case someone cares and then ignore it)
+                    System.out.println("Exception! "+e.toString());
+                    e.printStackTrace();
+                    setErrorStatus(STATUS_NOCONNECT);
+                    socket = null;
+                }
+            } else {
+                // Already started
+            }
+            if (socket != null) {
+                // Make sure the right buttons are enabled
+                start_button.setEnabled(false);
+                stop_button.setEnabled(true);
+                setStatus(STATUS_ACTIVE);
+            }
+        }
+
+        /**
+         * Stop talking to the server
+         */
+        public void stop() {
+            if (socket != null) {
+                // Close all the streams and socket
+                if (out != null) {
+                    try {
+                        out.close();
+                    } catch (IOException ioe) {
+                    }
+                    out = null;
+                }
+                if (in != null) {
+                    try {
+                        in.close();
+                    } catch (IOException ioe) {
+                    }
+                    in = null;
+                }
+                if (socket != null) {
+                    try {
+                        socket.close();
+                    } catch (IOException ioe) {
+                    }
+                    socket = null;
+                }
+            } else {
+                // Already stopped
+            }
+            // Make sure the right buttons are enabled
+            start_button.setEnabled(true);
+            stop_button.setEnabled(false);
+            setStatus(STATUS_STOPPED);
+        }
+
+        /**
+         * Background thread used to receive data from
+         * the server.
+         */
+        public void run() {
+            Long            id;
+            Integer         message_type;
+            String          target;
+            String          soap;
+            SOAPMonitorData data;
+            int             selected;
+            int             row;
+            boolean         update_needed;
+            while (socket != null) {
+                try {
+                    // Get the data from the server
+                    message_type = (Integer) in.readObject();
+                    // Process the data depending on its type
+                    switch (message_type.intValue()) {
+                        case SOAPMonitorConstants.SOAP_MONITOR_REQUEST:
+                            // Get the id, target and soap info
+                            id = (Long) in.readObject();
+                            target = (String) in.readObject();
+                            soap = (String) in.readObject();
+                            // Add new request data to the table
+                            data = new SOAPMonitorData(id,target,soap);
+                            model.addData(data);
+                            // If "most recent" selected then update
+                            // the details area if needed
+                            selected = table.getSelectedRow();
+                            if ((selected == 0) && model.filterMatch(data)) {
+                                valueChanged(null);
+                            }
+                            break;
+                        case SOAPMonitorConstants.SOAP_MONITOR_RESPONSE:
+                            // Get the id and soap info
+                            id = (Long) in.readObject();
+                            soap = (String) in.readObject();
+                            data = model.findData(id);
+                            if (data != null) {
+                                update_needed = false;
+                                // Get the selected row
+                                selected = table.getSelectedRow();
+                                // If "most recent", then always
+                                // update details area
+                                if (selected == 0) {
+                                    update_needed = true;
+                                }
+                                // If the data being updated is
+                                // selected then update details
+                                row = model.findRow(data);
+                                if ((row != -1) && (row == selected)) {
+                                    update_needed = true;
+                                }
+                                // Set the response and update table
+                                data.setSOAPResponse(soap);
+                                model.updateData(data);
+                                // Refresh details area (if needed)
+                                if (update_needed) {
+                                    valueChanged(null);
+                                }
+                            }
+                            break;
+                    }
+
+                } catch (Exception e) {
+                    // Exceptions are expected here when the
+                    // server communication has been terminated.
+                    if (stop_button.isEnabled()) {
+                        stop();
+                        setErrorStatus(STATUS_CLOSED);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Listener to handle table selection changes
+         */
+        public void valueChanged(ListSelectionEvent e) {
+            int row = table.getSelectedRow();
+            // Check if they selected a specific row
+            if (row > 0) {
+                remove_button.setEnabled(true);
+            } else {
+                remove_button.setEnabled(false);
+            }
+            // Check for "most recent" selection
+            if (row == 0) {
+                row = model.getRowCount() - 1;
+                if (row == 0) {
+                    row = -1;
+                }
+            }
+            if (row == -1) {
+                // Clear the details panel
+                details_time_value.setText("");
+                details_target_value.setText("");
+                details_status_value.setText("");
+                request_text.setText("");
+                response_text.setText("");
+            } else {
+                // Show the details for the row
+                SOAPMonitorData soap = model.getData(row);
+                details_time_value.setText(soap.getTime());
+                details_target_value.setText(soap.getTargetService());
+                details_status_value.setText(soap.getStatus());
+                if (soap.getSOAPRequest() == null) {
+                    request_text.setText("");
+                } else {
+                    request_text.setText(soap.getSOAPRequest());
+                    request_text.setCaretPosition(0);
+                }
+                if (soap.getSOAPResponse() == null) {
+                    response_text.setText("");
+                } else {
+                    response_text.setText(soap.getSOAPResponse());
+                    response_text.setCaretPosition(0);
+                }
+            }
+        }
+
+        /**
+         * Listener to handle button actions
+         */
+        public void actionPerformed(ActionEvent e) {
+            // Check if the user pressed the remove button
+            if (e.getSource() == remove_button) {
+                int row = table.getSelectedRow();
+                model.removeRow(row);
+                table.clearSelection();
+                table.repaint();
+                valueChanged(null);
+            }
+            // Check if the user pressed the remove all button
+            if (e.getSource() == remove_all_button) {
+                model.clearAll();
+                table.setRowSelectionInterval(0,0);
+                table.repaint();
+                valueChanged(null);
+            }
+            // Check if the user pressed the filter button
+            if (e.getSource() == filter_button) {
+                filter.showDialog();
+                if (filter.okPressed()) {
+                    // Update the display with new filter
+                    model.setFilter(filter);
+                    table.repaint();
+                }
+            }
+            // Check if the user pressed the start button
+            if (e.getSource() == start_button) {
+                start();
+            }
+            // Check if the user pressed the stop button
+            if (e.getSource() == stop_button) {
+                stop();
+            }
+            // Check if the user wants to switch layout
+            if (e.getSource() == layout_button) {
+                details_panel.remove(details_soap);
+                details_soap.removeAll();
+                if (details_soap.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) {
+                    details_soap = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+                } else {
+                    details_soap = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+                }
+                details_soap.setTopComponent(request_panel);
+                details_soap.setRightComponent(response_panel);
+                details_soap.setResizeWeight(.5);
+                details_panel.add(details_soap, BorderLayout.CENTER);
+                details_panel.validate();
+                details_panel.repaint();
+            }
+            // Check if the user is changing the reflow option
+            if (e.getSource() == reflow_xml) {
+                request_text.setReflowXML(reflow_xml.isSelected());
+                response_text.setReflowXML(reflow_xml.isSelected());
+            }
+        }
+    }
+
+    /**
+     * This class represend the data for a SOAP request/response pair
+     */
+    class SOAPMonitorData {
+
+        /**
+         * Private data
+         */
+        private Long    id;
+        private String  time;
+        private String  target;
+        private String  soap_request;
+        private String  soap_response;
+
+        /**
+         * Constructor
+         */
+        public SOAPMonitorData(Long id, String target, String soap_request) {
+            this.id = id;
+            // A null id is used to signal that the "most recent" entry
+            // is being created.
+            if (id == null) {
+                this.time = "Most Recent";
+                this.target = "---";
+                this.soap_request = null;
+                this.soap_response = null;
+            } else {
+                this.time = DateFormat.getTimeInstance().format(new Date());
+                this.target = target;
+                this.soap_request = soap_request;
+                this.soap_response = null;
+            }
+        }
+
+        /**
+         * Get the id for the SOAP message
+         */
+        public Long getId() {
+            return id;
+        }
+
+        /**
+         * Get the time the SOAP request was received by the applet
+         */
+        public String getTime() {
+            return time;
+        }
+
+        /**
+         * Get the SOAP request target service name
+         */
+        public String getTargetService() {
+            return target;
+        }
+
+        /**
+         * Get the status of the request
+         */
+        public String getStatus() {
+            String status = "---";
+            if (id != null) {
+                status = "Complete";
+                if (soap_response == null) {
+                    status = "Active";
+                }
+            }
+            return status;
+        }
+
+        /**
+         * Get the request SOAP contents
+         */
+        public String getSOAPRequest() {
+            return soap_request;
+        }
+
+        /**
+         * Set the resposne SOAP contents
+         */
+        public void setSOAPResponse(String response) {
+            soap_response = response;
+        }
+
+        /**
+         * Get the response SOAP contents
+         */
+        public String getSOAPResponse() {
+            return soap_response;
+        }
+    }
+
+    /**
+     * This table model is used to manage the table displayed
+     * at the top of the page to show all the SOAP messages
+     * we have received and to control which message details are
+     * to be displayed on the bottom of the page.
+     */
+    class SOAPMonitorTableModel extends AbstractTableModel {
+
+        /**
+         * Column titles
+         */
+        private final String[] column_names = { "Time",
+                                                "Target Service",
+                                                "Status" };
+        /**                                        
+         * Private data
+         */
+        private Vector  data;
+        private Vector  filter_include;
+        private Vector  filter_exclude;
+        private boolean filter_active;
+        private boolean filter_complete;
+        private Vector  filter_data;
+
+        /**
+         * Constructor
+         */
+        public SOAPMonitorTableModel() {
+            data = new Vector();
+            // Add "most recent" entry to top of table
+            SOAPMonitorData soap = new SOAPMonitorData(null,null,null);
+            data.addElement(soap);
+            filter_include = null;
+            filter_exclude = null;
+            filter_active = false;
+            filter_complete = false;
+            filter_data = null;
+            // By default, exclude NotificationService and
+            // EventViewerService messages
+            filter_exclude = new Vector();
+            filter_exclude.addElement("NotificationService");
+            filter_exclude.addElement("EventViewerService");
+            filter_data = new Vector();
+            filter_data.addElement(soap);
+        }
+
+        /**
+         * Get column count (part of table model interface)
+         */
+        public int getColumnCount() {
+            return column_names.length;
+        }
+        
+        /**
+         * Get row count (part of table model interface)
+         */
+        public int getRowCount() {
+            int count = data.size();
+            if (filter_data != null) {
+                count = filter_data.size();
+            }
+            return count;
+        }
+
+        /**
+         * Get column name (part of table model interface)
+         */
+        public String getColumnName(int col) {
+            return column_names[col];
+        }
+
+        /**
+         * Get value at (part of table model interface)
+         */
+        public Object getValueAt(int row, int col) {
+            SOAPMonitorData soap;
+            String          value = null;
+            soap = (SOAPMonitorData) data.elementAt(row);
+            if (filter_data != null) {
+                soap = (SOAPMonitorData) filter_data.elementAt(row);
+            }
+            switch (col) {
+                case 0:
+                    value = soap.getTime();
+                    break;
+                case 1:
+                    value = soap.getTargetService();
+                    break;
+                case 2:
+                    value = soap.getStatus();
+                    break;
+            }
+            return value;
+        }
+
+        /**
+         * Check if soap data matches filter 
+         */
+        public boolean filterMatch(SOAPMonitorData soap) {
+            boolean match = true;
+            if (filter_include != null) {
+                // Check for service match
+                Enumeration e = filter_include.elements();
+                match = false;
+                while (e.hasMoreElements() && !match) {
+                    String service = (String) e.nextElement();
+                    if (service.equals(soap.getTargetService())) {
+                        match = true;
+                    }
+                }
+            }
+            if (filter_exclude != null) {
+                // Check for service match
+                Enumeration e = filter_exclude.elements();
+                while (e.hasMoreElements() && match) {
+                    String service = (String) e.nextElement();
+                    if (service.equals(soap.getTargetService())) {
+                        match = false;
+                    }
+                }
+            }
+            if (filter_active) {
+                // Check for active status match
+                if (soap.getSOAPResponse() != null) {
+                    match = false;
+                }
+            }
+            if (filter_complete) {
+                // Check for complete status match
+                if (soap.getSOAPResponse() == null) {
+                    match = false;
+                }
+            }
+            // The "most recent" is always a match
+            if (soap.getId() == null) {
+                match = true;
+            }
+            return match;
+        }
+
+        /**
+         * Add data to the table as a new row
+         */
+        public void addData(SOAPMonitorData soap) {
+            int row = data.size();
+            data.addElement(soap);
+            if (filter_data != null) {
+                if (filterMatch(soap)) {
+                    row = filter_data.size();
+                    filter_data.addElement(soap);
+                    fireTableRowsInserted(row,row);
+                }
+            } else {
+                fireTableRowsInserted(row,row);
+            }
+        }
+
+        /**
+         * Find the data for a given id
+         */
+        public SOAPMonitorData findData(Long id) {
+            SOAPMonitorData soap = null;
+            for (int row=data.size(); (row > 0) && (soap == null); row--) {
+                soap = (SOAPMonitorData) data.elementAt(row-1);
+                if (soap.getId().longValue() != id.longValue()) {
+                    soap = null;
+                }
+            }
+            return soap;
+        }
+
+        /**
+         * Find the row in the table for a given message id
+         */
+        public int findRow(SOAPMonitorData soap) {
+            int row = -1;
+            if (filter_data != null) {
+                row = filter_data.indexOf(soap);
+            } else {
+                row = data.indexOf(soap);
+            }
+            return row;
+        }
+
+        /**
+         * Remove all messages from the table (but leave "most recent")
+         */
+        public void clearAll() {
+            int last_row = data.size() - 1;
+            if (last_row > 0) {
+                data.removeAllElements();
+                SOAPMonitorData soap = new SOAPMonitorData(null,null,null);
+                data.addElement(soap);
+                if (filter_data != null) {
+                    filter_data.removeAllElements();
+                    filter_data.addElement(soap);
+                }
+                fireTableDataChanged();
+            }
+        }
+
+        /**
+         * Remove a message from the table
+         */
+        public void removeRow(int row) {
+            SOAPMonitorData soap = null;
+            if (filter_data == null) {
+                soap = (SOAPMonitorData) data.elementAt(row);
+                data.remove(soap);
+            } else {
+                soap = (SOAPMonitorData) filter_data.elementAt(row);
+                filter_data.remove(soap);
+                data.remove(soap);
+            }         
+            fireTableRowsDeleted(row,row);
+        }
+
+        /**
+         * Set a new filter
+         */
+        public void setFilter(SOAPMonitorFilter filter) {
+            // Save new filter criteria
+            filter_include = filter.getFilterIncludeList();
+            filter_exclude = filter.getFilterExcludeList();
+            filter_active = filter.getFilterActive();
+            filter_complete = filter.getFilterComplete();
+            applyFilter();
+        }
+
+        /**
+         * Refilter the list of messages
+         */
+        public void applyFilter() {
+            // Re-filter using new criteria
+            filter_data = null;
+            if ((filter_include != null) || 
+                (filter_exclude != null) ||
+                 filter_active || filter_complete ) {
+                filter_data = new Vector();
+                Enumeration e = data.elements();
+                SOAPMonitorData soap;
+                while (e.hasMoreElements()) {
+                    soap = (SOAPMonitorData) e.nextElement();
+                    if (filterMatch(soap)) {
+                        filter_data.addElement(soap);
+                    }
+                }
+            }
+            fireTableDataChanged();
+        }
+
+        /**
+         * Get the data for a row
+         */
+        public SOAPMonitorData getData(int row) {
+            SOAPMonitorData soap = null;
+            if (filter_data == null) {
+                soap = (SOAPMonitorData) data.elementAt(row);
+            } else {
+                soap = (SOAPMonitorData) filter_data.elementAt(row);
+            }
+            return soap;
+        }
+
+        /**
+         * Update a message
+         */
+        public void updateData (SOAPMonitorData soap) {
+           int row;
+           if (filter_data == null) {
+               // No filter, so just fire table updated
+               row = data.indexOf(soap);
+               if (row != -1) {
+                   fireTableRowsUpdated(row,row);
+               }
+           } else {
+               // Check if the row was being displayed
+               row = filter_data.indexOf(soap);
+               if (row == -1) {
+                   // Row was not displayed, so check for if it
+                   // now needs to be displayed
+                   if (filterMatch(soap)) {
+                       int index = -1;
+                       row = data.indexOf(soap) + 1;
+                       while ((row < data.size()) && (index == -1)) {
+                           index = filter_data.indexOf(data.elementAt(row));
+                           if (index != -1) {                   
+                               // Insert at this location
+                               filter_data.add(index,soap);
+                           }
+                           row++;
+                       }
+                       if (index == -1) {
+                           // Insert at end
+                           index = filter_data.size();
+                           filter_data.addElement(soap);
+                       }
+                       fireTableRowsInserted(index,index);
+                   }
+               } else {
+                   // Row was displayed, so check if it needs to
+                   // be updated or removed
+                   if (filterMatch(soap)) {
+                       fireTableRowsUpdated(row,row);
+                   } else {
+                       filter_data.remove(soap);
+                       fireTableRowsDeleted(row,row);
+                   }
+               }
+           }
+        }
+
+    }
+
+    /**
+     * Panel with checkbox and list
+     */
+    class ServiceFilterPanel extends JPanel 
+                             implements ActionListener,
+                                        ListSelectionListener,
+                                        DocumentListener {
+
+        private JCheckBox    service_box = null;
+        private Vector       filter_list = null;
+        private Vector       service_data = null;
+        private JList        service_list = null;
+        private JScrollPane  service_scroll = null;
+        private JButton      remove_service_button = null;
+        private JPanel       remove_service_panel = null;
+        private EmptyBorder  indent_border = null;
+        private EmptyBorder  empty_border = null;
+        private JPanel       service_area = null;
+        private JPanel       add_service_area = null;
+        private JTextField   add_service_field = null;
+        private JButton      add_service_button = null;
+        private JPanel       add_service_panel = null;
+
+        /**
+         * Constructor
+         */
+        public ServiceFilterPanel(String text, Vector list) {
+            empty_border = new EmptyBorder(5,5,0,5);
+            indent_border = new EmptyBorder(5,25,5,5);
+            service_box = new JCheckBox(text);
+            service_box.addActionListener(this);
+            service_data = new Vector();
+            if (list != null) {
+                service_box.setSelected(true);
+                service_data = (Vector) list.clone();
+            }
+            service_list = new JList(service_data);
+            service_list.setBorder(new EtchedBorder());
+            service_list.setVisibleRowCount(5);
+            service_list.addListSelectionListener(this);
+            service_list.setEnabled(service_box.isSelected());
+            service_scroll = new JScrollPane(service_list);
+            service_scroll.setBorder(new EtchedBorder());
+            remove_service_button = new JButton("Remove");
+            remove_service_button.addActionListener(this);
+            remove_service_button.setEnabled(false);
+            remove_service_panel = new JPanel();
+            remove_service_panel.setLayout(new FlowLayout());
+            remove_service_panel.add(remove_service_button);
+            service_area = new JPanel();
+            service_area.setLayout(new BorderLayout());
+            service_area.add(service_scroll, BorderLayout.CENTER);
+            service_area.add(remove_service_panel, BorderLayout.EAST);
+            service_area.setBorder(indent_border);
+            add_service_field = new JTextField();
+            add_service_field.addActionListener(this);
+            add_service_field.getDocument().addDocumentListener(this);
+            add_service_field.setEnabled(service_box.isSelected());
+            add_service_button = new JButton("Add");
+            add_service_button.addActionListener(this);
+            add_service_button.setEnabled(false);
+            add_service_panel = new JPanel();
+            add_service_panel.setLayout(new BorderLayout());
+            JPanel dummy = new JPanel();
+            dummy.setBorder(empty_border);
+            add_service_panel.add(dummy, BorderLayout.WEST);
+            add_service_panel.add(add_service_button, BorderLayout.EAST);
+            add_service_area = new JPanel();
+            add_service_area.setLayout(new BorderLayout());
+            add_service_area.add(add_service_field, BorderLayout.CENTER);
+            add_service_area.add(add_service_panel, BorderLayout.EAST);
+            add_service_area.setBorder(indent_border);
+            setLayout(new BorderLayout());
+            add(service_box, BorderLayout.NORTH);
+            add(service_area, BorderLayout.CENTER);
+            add(add_service_area, BorderLayout.SOUTH);
+            setBorder(empty_border);
+        }
+
+        /**
+         * Get the current list of services
+         */
+        public Vector getServiceList() {
+            Vector list = null;
+            if (service_box.isSelected()) {
+                list = service_data;
+            }
+            return list;
+        }
+
+        /**
+         * Listener to handle button actions
+         */
+        public void actionPerformed(ActionEvent e) {
+            // Check if the user changed the service filter option
+            if (e.getSource() == service_box) {
+                service_list.setEnabled(service_box.isSelected());
+                service_list.clearSelection();
+                remove_service_button.setEnabled(false);
+                add_service_field.setEnabled(service_box.isSelected());
+                add_service_field.setText("");
+                add_service_button.setEnabled(false);
+            }
+            // Check if the user pressed the add service button
+            if ((e.getSource() == add_service_button) ||
+                (e.getSource() == add_service_field)) {
+                String text = add_service_field.getText();
+                if ((text != null) && (text.length() > 0)) {
+                    service_data.addElement(text);
+                    service_list.setListData(service_data);
+                }
+                add_service_field.setText("");
+                add_service_field.requestFocus();
+            }
+            // Check if the user pressed the remove service button
+            if (e.getSource() == remove_service_button) {
+                Object[] sels = service_list.getSelectedValues();
+                for (int i=0; i<sels.length; i++) {
+                    service_data.removeElement(sels[i]);
+                }
+                service_list.setListData(service_data);
+                service_list.clearSelection();
+            }
+        }
+
+        /**
+         * Handle changes to the text field
+         */
+        public void changedUpdate(DocumentEvent e) {
+            String text = add_service_field.getText();
+            if ((text != null) && (text.length() > 0)) {
+                add_service_button.setEnabled(true);
+            } else {
+                add_service_button.setEnabled(false);
+            }
+        }
+
+        /**
+         * Handle changes to the text field
+         */
+        public void insertUpdate(DocumentEvent e) {
+            changedUpdate(e);
+        }
+
+        /**
+         * Handle changes to the text field
+         */
+        public void removeUpdate(DocumentEvent e) {
+            changedUpdate(e);
+        }
+
+        /**
+         * Listener to handle service list selection changes
+         */
+        public void valueChanged(ListSelectionEvent e) {
+            if (service_list.getSelectedIndex() == -1) {
+                remove_service_button.setEnabled(false);
+            } else {
+                remove_service_button.setEnabled(true);
+            }
+        }
+    }
+
+    /**
+     * Class for showing the filter dialog
+     */
+    class SOAPMonitorFilter implements ActionListener {
+
+        /**
+         * Private data
+         */
+        private JDialog            dialog = null;
+        private JPanel             panel = null;
+        private JPanel             buttons = null;
+        private JButton            ok_button = null;
+        private JButton            cancel_button = null;
+        private ServiceFilterPanel include_panel = null;
+        private ServiceFilterPanel exclude_panel = null;
+        private JPanel             status_panel = null;
+        private JCheckBox          status_box = null;
+        private EmptyBorder  empty_border = null;
+        private EmptyBorder  indent_border = null;
+        private JPanel             status_options = null;
+        private ButtonGroup        status_group = null;
+        private JRadioButton       status_active = null;
+        private JRadioButton       status_complete = null;
+        private Vector             filter_include_list = null;
+        private Vector             filter_exclude_list = null;
+        private boolean            filter_active = false;
+        private boolean            filter_complete = false;
+        private boolean            ok_pressed = false;
+
+        /**
+         * Constructor
+         */
+        public SOAPMonitorFilter() {
+            // By default, exclude NotificationService and
+            // EventViewerService messages
+            filter_exclude_list = new Vector();
+            filter_exclude_list.addElement("NotificationService");
+            filter_exclude_list.addElement("EventViewerService");
+        }
+
+        /**
+         * Get list of services to be included
+         */
+        public Vector getFilterIncludeList() {
+            return filter_include_list;
+        }
+
+        /**
+         * Get list of services to be excluded
+         */
+        public Vector getFilterExcludeList() {
+            return filter_exclude_list;
+        }
+
+        /**
+         * Check if filter active messages
+         */
+        public boolean getFilterActive() {
+            return filter_active;
+        }
+
+        /**
+         * Check if filter complete messages
+         */
+        public boolean getFilterComplete() {
+            return filter_complete;
+        }
+
+        /**
+         * Show the filter dialog
+         */
+        public void showDialog() {
+            empty_border = new EmptyBorder(5,5,0,5);
+            indent_border = new EmptyBorder(5,25,5,5);
+            include_panel = new ServiceFilterPanel("Include messages based on target service:",
+                                                   filter_include_list);
+            exclude_panel = new ServiceFilterPanel("Exclude messages based on target service:",
+                                                   filter_exclude_list);
+            status_box = new JCheckBox("Filter messages based on status:");
+            status_box.addActionListener(this);
+            status_active = new JRadioButton("Active messages only");
+            status_active.setSelected(true);
+            status_active.setEnabled(false);
+            status_complete = new JRadioButton("Complete messages only");
+            status_complete.setEnabled(false);
+            status_group = new ButtonGroup();
+            status_group.add(status_active);
+            status_group.add(status_complete);
+            if (filter_active || filter_complete) {
+                status_box.setSelected(true);
+                status_active.setEnabled(true);
+                status_complete.setEnabled(true);
+                if (filter_complete) {
+                    status_complete.setSelected(true);
+                }
+            }
+            status_options = new JPanel();
+            status_options.setLayout(new BoxLayout(status_options, BoxLayout.Y_AXIS));
+            status_options.add(status_active);
+            status_options.add(status_complete);
+            status_options.setBorder(indent_border);
+            status_panel = new JPanel();
+            status_panel.setLayout(new BorderLayout());
+            status_panel.add(status_box, BorderLayout.NORTH);
+            status_panel.add(status_options, BorderLayout.CENTER);
+            status_panel.setBorder(empty_border);
+            ok_button = new JButton("Ok");
+            ok_button.addActionListener(this);
+            cancel_button = new JButton("Cancel");
+            cancel_button.addActionListener(this);
+            buttons = new JPanel();
+            buttons.setLayout(new FlowLayout());
+            buttons.add(ok_button);
+            buttons.add(cancel_button);
+            panel = new JPanel();
+            panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+            panel.add(include_panel);
+            panel.add(exclude_panel);
+            panel.add(status_panel);
+            panel.add(buttons);
+            dialog = new JDialog();
+            dialog.setTitle("SOAP Monitor Filter");
+            dialog.setContentPane(panel);
+            dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+            dialog.setModal(true);
+            dialog.pack();
+            Dimension d = dialog.getToolkit().getScreenSize();
+            dialog.setLocation((d.width-dialog.getWidth())/2,
+                               (d.height-dialog.getHeight())/2);
+            ok_pressed = false;
+            dialog.show();
+        }
+
+        /**
+         * Listener to handle button actions
+         */
+        public void actionPerformed(ActionEvent e) {
+            // Check if the user pressed the ok button
+            if (e.getSource() == ok_button) {
+                filter_include_list = include_panel.getServiceList();
+                filter_exclude_list = exclude_panel.getServiceList();
+                if (status_box.isSelected()) {
+                    filter_active = status_active.isSelected();
+                    filter_complete = status_complete.isSelected();
+                } else {
+                    filter_active = false;
+                    filter_complete = false;
+                }
+                ok_pressed = true;
+                dialog.dispose();
+            }
+            // Check if the user pressed the cancel button
+            if (e.getSource() == cancel_button) {
+                dialog.dispose();
+            }
+            // Check if the user changed the status filter option
+            if (e.getSource() == status_box) {
+                status_active.setEnabled(status_box.isSelected());
+                status_complete.setEnabled(status_box.isSelected());
+            }
+        }
+
+        /**
+         * Check if the user pressed the ok button
+         */
+        public boolean okPressed() {
+            return ok_pressed;
+        }
+    }
+
+    /**
+     * Text panel class that supports XML reflow
+     */
+    class SOAPMonitorTextArea extends JTextArea {
+
+        /**
+         * Private data
+         */
+        private boolean format = false;
+        private String  original = "";
+        private String  formatted = null; 
+
+        /**
+         * Constructor
+         */
+        public SOAPMonitorTextArea() {
+        }
+
+        /** 
+         * Override setText to do formatting
+         */
+        public void setText(String text) {
+            original = text;
+            formatted = null;
+            if (format) {
+                doFormat();
+                super.setText(formatted);
+            } else {
+                super.setText(original);
+            }
+        }
+
+        /**
+         * Turn reflow on or off
+         */
+        public void setReflowXML(boolean reflow) {
+            format = reflow;
+            if (format) {
+                if (formatted == null) {
+                    doFormat();
+                }
+                super.setText(formatted);
+            } else {
+                super.setText(original);
+            }
+        }
+
+        /**
+         * Reflow XML
+         */
+        public void doFormat() {
+            Vector       parts = new Vector();
+            char[]       chars = original.toCharArray();
+            int          index = 0;
+            int          first = 0;
+            String       part = null;
+            while (index < chars.length) {
+                // Check for start of tag
+                if (chars[index] == '<') {
+                    // Did we have data before this tag?
+                    if (first < index) {
+                        part = new String(chars,first,index-first);
+                        part = part.trim();
+                        // Save non-whitespace data
+                        if (part.length() > 0) {
+                            parts.addElement(part);
+                        }
+                    }
+                    // Save the start of tag
+                    first = index;
+                }
+                // Check for end of tag
+                if (chars[index] == '>') {
+                    // Save the tag
+                    part = new String(chars,first,index-first+1);
+                    parts.addElement(part);
+                    first = index+1;
+                }
+                // Check for end of line
+                if ((chars[index] == '\n') || (chars[index] == '\r')) {
+                    // Was there data on this line?
+                    if (first < index) {
+                        part = new String(chars,first,index-first);
+                        part = part.trim();
+                        // Save non-whitespace data
+                        if (part.length() > 0) {
+                            parts.addElement(part);
+                        }
+                    }
+                    first = index+1;
+                }
+                index++;
+            }
+            // Reflow as XML
+            StringBuffer buf = new StringBuffer();
+            Object[] list = parts.toArray();
+            int indent = 0;
+            int pad = 0;
+            index = 0;
+            while (index < list.length) {
+                part = (String) list[index];
+                if (buf.length() == 0) {
+                    // Just add first tag (should be XML header)
+                    buf.append(part);
+                } else {
+                    // All other parts need to start on a new line
+                    buf.append('\n');
+                    // If we're at an end tag then decrease indent
+                    if (part.startsWith("</")) {
+                        indent--;
+                    }            
+                    // Add any indent
+                    for (pad = 0; pad < indent; pad++) {
+                        buf.append("  ");
+                    }
+                    // Add the tag or data
+                    buf.append(part);
+                    // If this is a start tag then increase indent
+                    if (part.startsWith("<") &&
+                        !part.startsWith("</") &&
+                        !part.endsWith("/>")) {
+                        indent++;
+                        // Check for special <tag>data</tag> case
+                        if ((index + 2) < list.length) {
+                            part = (String) list[index+2];
+                            if (part.startsWith("</")) {
+                                part = (String) list[index+1];
+                                if (!part.startsWith("<")) {
+                                    buf.append(part);
+                                    part = (String) list[index+2];
+                                    buf.append(part);
+                                    index = index + 2;
+                                    indent--;
+                                }
+                            }
+                        }
+                    }
+                }
+                index++;
+            }
+            formatted = new String(buf);
+        }
+    }
+}
diff --git a/trunk/webapps/axis/StockQuoteService.jws b/trunk/webapps/axis/StockQuoteService.jws
new file mode 100644
index 0000000..8a29a75
--- /dev/null
+++ b/trunk/webapps/axis/StockQuoteService.jws
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2001,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.
+ */
+
+import org.apache.axis.utils.XMLUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * See \samples\stock\readme for info.
+ *
+ * @author Sanjiva Weerawarana (sanjiva@watson.ibm.com)
+ * @author Doug Davis (dug@us.ibm.com)
+ */
+public class StockQuoteService {
+  public float getQuote (String symbol) throws Exception {
+    // get a real (delayed by 20min) stockquote from 
+    // http://www.xmltoday.com/examples/stockquote/. The IP addr 
+    // below came from the host that the above form posts to ..
+
+    if ( symbol.equals("XXX") ) return( (float) 66.25 );
+
+
+    Document doc = null ;
+    
+    doc = XMLUtils.newDocument( "http://www.xmltoday.com/examples/" +
+                                "stockquote/getxmlquote.vep?s="+symbol );
+
+    Element  elem = doc.getDocumentElement();
+    NodeList list = elem.getElementsByTagName("stock_quote");
+
+    elem = (Element) list.item(0);
+    list = elem.getElementsByTagName( "price" );
+    elem = (Element) list.item( 0 );
+    String quoteStr = elem.getAttribute("value");
+    try {
+      return Float.valueOf(quoteStr).floatValue();
+    } catch (NumberFormatException e1) {
+      // maybe its an int?
+      try {
+        return Integer.valueOf(quoteStr).intValue() * 1.0F;
+      } catch (NumberFormatException e2) {
+        return -1.0F;
+      }
+    }
+  }
+}
diff --git a/trunk/webapps/axis/WEB-INF/web.xml b/trunk/webapps/axis/WEB-INF/web.xml
new file mode 100644
index 0000000..67f1ef9
--- /dev/null
+++ b/trunk/webapps/axis/WEB-INF/web.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
+Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+  <display-name>Apache-Axis</display-name>
+    
+    <listener>
+        <listener-class>org.apache.axis.transport.http.AxisHTTPSessionListener</listener-class>
+    </listener>
+    
+  <servlet>
+    <servlet-name>AxisServlet</servlet-name>
+    <display-name>Apache-Axis Servlet</display-name>
+    <servlet-class>
+        org.apache.axis.transport.http.AxisServlet
+    </servlet-class>
+  </servlet>
+
+  <servlet>
+    <servlet-name>AdminServlet</servlet-name>
+    <display-name>Axis Admin Servlet</display-name>
+    <servlet-class>
+        org.apache.axis.transport.http.AdminServlet
+    </servlet-class>
+    <load-on-startup>100</load-on-startup>
+  </servlet>
+
+  <servlet>
+    <servlet-name>SOAPMonitorService</servlet-name>
+    <display-name>SOAPMonitorService</display-name>
+    <servlet-class>
+        org.apache.axis.monitor.SOAPMonitorService
+    </servlet-class>
+    <init-param>
+      <param-name>SOAPMonitorPort</param-name>
+      <param-value>5001</param-value>
+    </init-param>
+    <load-on-startup>100</load-on-startup>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>AxisServlet</servlet-name>
+    <url-pattern>/servlet/AxisServlet</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>AxisServlet</servlet-name>
+    <url-pattern>*.jws</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>AxisServlet</servlet-name>
+    <url-pattern>/services/*</url-pattern>
+  </servlet-mapping>
+
+  <servlet-mapping>
+    <servlet-name>SOAPMonitorService</servlet-name>
+    <url-pattern>/SOAPMonitor</url-pattern>
+  </servlet-mapping>
+
+ <!-- uncomment this if you want the admin servlet -->
+ <!--
+  <servlet-mapping>
+    <servlet-name>AdminServlet</servlet-name>
+    <url-pattern>/servlet/AdminServlet</url-pattern>
+  </servlet-mapping>
+ -->
+
+    <session-config>
+        <!-- Default to 5 minute session timeouts -->
+        <session-timeout>5</session-timeout>
+    </session-config>
+
+    <!-- currently the W3C havent settled on a media type for WSDL;
+    http://www.w3.org/TR/2003/WD-wsdl12-20030303/#ietf-draft
+    for now we go with the basic 'it's XML' response -->
+  <mime-mapping>
+    <extension>wsdl</extension>
+     <mime-type>text/xml</mime-type>
+  </mime-mapping>
+  
+
+  <mime-mapping>
+    <extension>xsd</extension>
+    <mime-type>text/xml</mime-type>
+  </mime-mapping>
+
+  <welcome-file-list id="WelcomeFileList">
+    <welcome-file>index.html</welcome-file>
+    <welcome-file>index.jsp</welcome-file>
+    <welcome-file>index.jws</welcome-file>
+  </welcome-file-list>
+
+</web-app>
diff --git a/trunk/webapps/axis/fingerprint.jsp b/trunk/webapps/axis/fingerprint.jsp
new file mode 100644
index 0000000..644359e
--- /dev/null
+++ b/trunk/webapps/axis/fingerprint.jsp
@@ -0,0 +1,272 @@
+<%@ page import="java.io.File,
+                 java.io.IOException,
+                 java.util.Date"
+    session="false" %>
+<html>
+<head>
+<title>System Fingerprint</title>
+</head>
+<body bgcolor=#ffffff>
+<%!
+
+    /*
+     * Fingerprint the users system. This is mainly for use in
+     * diagnosing classpath problems. It is intended to dump out
+     * a copy of the environment this webapp is running in,
+     * and additionally attempt to identify versions of each jar
+     * in the classpath.
+     *
+     * @author Brian Ewins
+     */
+
+    private java.util.Properties versionProps=new java.util.Properties();
+
+    /**
+     * Identify the version of a jar file. This uses a properties file
+     * containing known names and sizes in the format
+     * 'name(size)=version'. Version strings should be like 'xerces-1.4'
+     * ie they should include the name of the library.
+     */
+    public String getFileVersion(File file) throws IOException {
+        String key="<td>"+file.getName()+"</td>";
+        key+= "<td>"+file.length()+"</td>";
+        Date timestamp=new Date(file.lastModified());
+        key+= "<td>"+timestamp.toString()+"</td>";
+        return key;
+
+        /* TODO: implement
+        String value=versionProps.getProperty(key);
+        if (value==null) {
+            // make it possible to have jars without version nos
+            value=versionProps.getProperty(file.getName());
+        }
+        if (value==null) {
+            // fall back on something obvious
+            value=key;
+            Date timestamp=new Date(file.lastModified());
+            value+=" / "+timestamp.toString();
+        }
+        return value;
+        */
+    }
+
+    /**
+     * Split up a classpath-like variable. Returns a list of files.
+     * TODO: this can't cope with relative paths. I think theres code in BCEL that
+     * can be used for this?
+     */
+    File[] splitClasspath(String path) throws IOException {
+        java.util.StringTokenizer st=
+            new java.util.StringTokenizer(path,
+                            System.getProperty("path.separator"));
+        int toks=st.countTokens();
+        File[] files=new File[toks];
+        for(int i=0;i<toks;i++) {
+            files[i]=new File(st.nextToken());
+        }
+        return files;
+    }
+
+    /** given a list of files, return a list of jars which actually exist */
+    File[] scanFiles(File[] files) throws IOException {
+        File[] jars=new File[files.length];
+        int found=0;
+        for (int i=0; i<files.length; i++) {
+            if (files[i].getName().toLowerCase().endsWith(".jar")
+                    && files[i].exists()) {
+                jars[found]=files[i];
+                found++;
+            }
+        }
+        if (found<files.length) {
+            File[] temp=new File[found];
+            System.arraycopy(jars,0,temp,0,found);
+            jars=temp;
+        }
+        return jars;    
+    }
+
+    private static final File[] NO_FILES=new File[0];
+
+    /** scan a directory for jars */    
+    public File[] scanDir(String dir) throws IOException 
+        {
+        if(dir==null) {
+            return NO_FILES;
+        }
+        return scanDir(new File(dir));
+        }
+        
+    public File[] scanDir(File dir) throws IOException {
+        if (!dir.exists() || !dir.isDirectory()) {
+            return NO_FILES;
+        }
+        return scanFiles(dir.listFiles());
+    }
+
+    /** scan a classpath for jars */    
+    public File[] scanClasspath(String path) throws IOException {
+        if (path==null) {
+            return NO_FILES;
+        }
+        return scanFiles(splitClasspath(path));
+    }
+
+    /** 
+     * scan a 'dirpath' (like the java.ext.dirs system property) for jars 
+     */   
+    public File[] scanDirpath(String path) throws IOException {
+        if (path==null) {
+            return NO_FILES;
+        }
+        File[] current=new File[0];
+        File[] dirs=splitClasspath(path);
+        for(int i=0; i<dirs.length; i++) {
+            File[] jars=scanDir(dirs[i]);
+            File[] temp=new File[current.length+jars.length];
+            System.arraycopy(current,0,temp,0,current.length);
+            System.arraycopy(jars,0,temp,current.length,jars.length);
+            current=temp;
+        }
+        return scanFiles(current);
+    }
+
+    /** print out the jar versions for a directory */
+    public void listDirectory(String title, JspWriter out,String dir, String comment) throws IOException {
+        listVersions(title, out,scanDir(dir), comment);
+    }
+
+    /** print out the jar versions for a directory-like system property */
+    public void listDirProperty(String title, JspWriter out,String key, String comment) throws IOException {
+        listVersions(title, out,scanDir(System.getProperty(key)), comment);
+    }
+
+    /** print out the jar versions for a classpath-like system property */
+    public void listClasspathProperty(String title, JspWriter out,String key, String comment) throws IOException {
+        listVersions(title, out,scanClasspath(System.getProperty(key)), comment);
+    }
+
+    /** print out the jar versions for a 'java.ext.dirs'-like system property */
+    public void listDirpathProperty(String title, JspWriter out,String key, String comment) throws IOException {
+        listVersions(title, out,scanDirpath(System.getProperty(key)), comment);
+    }
+
+    /** print out the jar versions for a context-relative directory */
+    public void listContextPath(String title, JspWriter out, String path, String comment)  throws IOException {
+        listVersions(title, out,scanDir(getServletConfig().getServletContext().getRealPath(path)), comment);
+    }
+
+    /** print out the jar versions for a given list of files */
+    public void listVersions(String title, JspWriter out,File[] jars, String comment) throws IOException {
+        out.print("<h2>");
+        out.print(title);
+        out.println("</h2>");
+        out.println("<table>");
+        for (int i=0; i<jars.length; i++) {
+            out.println("<tr>"+getFileVersion(jars[i])+"</tr>");
+        }
+        out.println("</table>");
+        if(comment!=null && comment.length()>0) {
+            out.println("<p>");
+            out.println(comment);
+            out.println("<p>");
+        }
+    }
+
+%>
+<h1>System Fingerprint</h1>
+<h2>JVM and Server Version</h2>
+<table>
+<tr>
+    <td>Servlet Engine</td>
+    <td><%= getServletConfig().getServletContext().getServerInfo() %></td>
+    <td><%= getServletConfig().getServletContext().getMajorVersion() %></td>
+    <td><%= getServletConfig().getServletContext().getMinorVersion() %></td>
+</tr>
+<tr>
+    <td>Java VM</td>
+    <td><%= System.getProperty("java.vm.vendor") %></td>
+    <td><%= System.getProperty("java.vm.name") %></td>
+    <td><%= System.getProperty("java.vm.version") %></td>
+</tr>
+<tr>
+    <td>Java RE</td>
+    <td><%= System.getProperty("java.vendor") %></td>
+    <td><%= System.getProperty("java.version") %></td>
+    <td> </td>
+</tr>
+<tr>
+    <td>Platform</td>
+    <td><%= System.getProperty("os.name") %></td>
+    <td><%= System.getProperty("os.arch") %></td>
+    <td><%= System.getProperty("os.version") %></td>
+</tr>
+</table>
+
+<%
+listClasspathProperty("Boot jars", out,"sun.boot.class.path", "Only valid on a sun jvm");
+listClasspathProperty("System jars", out,"java.class.path", null);
+listDirpathProperty("Extra system jars", out,"java.ext.dirs", null);
+listContextPath("Webapp jars", out, "/WEB-INF/lib", null);
+// identify the container...
+String container=getServletConfig().getServletContext().getServerInfo();
+if (container.startsWith("Tomcat Web Server/3.2")) {
+    String home=System.getProperty("tomcat.home");
+    if(home!=null) {
+        listDirectory("Tomcat 3.2 Common Jars", out,
+                      home+File.separator
+                      +"lib",
+                      null);
+    }
+} else if (container.startsWith("Tomcat Web Server/3.3")) {
+    String home=System.getProperty("tomcat.home");
+    if(home!=null) {
+        listDirectory("Tomcat 3.3 Container Jars", out,
+                      home+File.separator
+                      +"lib"+File.separator
+                      +"container",
+                      null);
+        listDirectory("Tomcat 3.3 Common Jars", out,
+                      home+File.separator
+                      +"lib"+File.separator
+                      +"common",
+                      null);
+    }
+} else if (container.startsWith("Apache Tomcat/4.0")) {
+    //handle catalina common dir
+    String home=System.getProperty("catalina.home");
+    if(home!=null) {
+        listDirectory("Tomcat 4.0 Common Jars", out,
+                      home+File.separator
+                      +"common"+File.separator
+                      +"lib",
+                      null);
+    }
+} else if (container.startsWith("Apache Tomcat/4.1")) {
+    //handle catalina common dir
+    String home=System.getProperty("catalina.home");
+    if(home!=null) {
+        listDirectory("Tomcat 4.1 Common Jars", out,
+                      home+File.separator
+                      +"shared"+File.separator
+                      +"lib",
+                      null);
+    }
+} else if (System.getProperty("resin.home")!=null) {
+    String home=System.getProperty("resin.home");
+    if(home!=null) {
+        listDirectory("Resin Common Jars", out,
+                      home+File.separator
+                      +"lib",
+                      null);
+    }    
+} else if (System.getProperty("weblogic.httpd.servlet.classpath")!=null) {
+    listClasspathProperty("Weblogic Servlet Jars", out,
+                  "weblogic.httpd.servlet.classpath",
+                  null);
+} else {
+    //TODO: identify more servlet engine classpaths.
+}
+%>
+</body>
+</html>
\ No newline at end of file
diff --git a/trunk/webapps/axis/happyaxis.jsp b/trunk/webapps/axis/happyaxis.jsp
new file mode 100644
index 0000000..4133423
--- /dev/null
+++ b/trunk/webapps/axis/happyaxis.jsp
@@ -0,0 +1,488 @@
+<html>
+<%@ page import="java.io.InputStream,
+                 java.io.IOException,
+                 javax.xml.parsers.SAXParser,
+                 javax.xml.parsers.SAXParserFactory"
+   session="false" %>
+ <%
+    /*
+ * Copyright 2002,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.
+ */
+%>
+<head>
+<title>Axis Happiness Page</title>
+</head>
+<body bgcolor='#ffffff'>
+<%!
+
+    /*
+     * Happiness tests for axis. These look at the classpath and warn if things
+     * are missing. Normally addng this much code in a JSP page is mad
+     * but here we want to validate JSP compilation too, and have a drop-in
+     * page for easy re-use
+     * @author Steve 'configuration problems' Loughran
+     * @author dims
+     * @author Brian Ewins
+     */
+
+
+    /**
+     * Get a string providing install information.
+     * TODO: make this platform aware and give specific hints
+     */
+    public String getInstallHints(HttpServletRequest request) {
+
+        String hint=
+            "<B><I>Note:</I></B> On Tomcat 4.x and Java1.4, you may need to put libraries that contain "
+            +"java.* or javax.* packages into CATALINA_HOME/common/lib"
+            +"<br>jaxrpc.jar and saaj.jar are two such libraries.";
+        return hint;
+    }
+
+    /**
+     * test for a class existing
+     * @param classname
+     * @return class iff present
+     */
+    Class classExists(String classname) {
+        try {
+            return Class.forName(classname);
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
+
+    /**
+     * test for resource on the classpath
+     * @param resource
+     * @return true iff present
+     */
+    boolean resourceExists(String resource) {
+        boolean found;
+        InputStream instream=this.getClass().getResourceAsStream(resource);
+        found=instream!=null;
+        if(instream!=null) {
+            try {
+                instream.close();
+            } catch (IOException e) {
+            }
+        }
+        return found;
+    }
+
+    /**
+     * probe for a class, print an error message is missing
+     * @param out stream to print stuff
+     * @param category text like "warning" or "error"
+     * @param classname class to look for
+     * @param jarFile where this class comes from
+     * @param errorText extra error text
+     * @param homePage where to d/l the library
+     * @return the number of missing classes
+     * @throws IOException
+     */
+    int probeClass(JspWriter out,
+                   String category,
+                   String classname,
+                   String jarFile,
+                   String description,
+                   String errorText,
+                   String homePage) throws IOException {
+        try {
+            Class clazz = classExists(classname);
+            if(clazz == null)  {
+               String url="";
+               if(homePage!=null) {
+                  url="<br>  See <a href="+homePage+">"+homePage+"</a>";
+               }
+               out.write("<p>"+category+": could not find class "+classname
+                   +" from file <b>"+jarFile
+                   +"</b><br>  "+errorText
+                   +url
+                   +"<p>");
+               return 1;
+            } else {
+               String location = getLocation(out, clazz);
+               if(location == null) {
+                  out.write("Found "+ description + " (" + classname + ")<br>");
+               }
+               else {
+                  out.write("Found "+ description + " (" + classname + ") at " + location + "<br>");
+               }
+               return 0;
+            }
+        } catch(NoClassDefFoundError ncdfe) { 
+            String url="";
+            if(homePage!=null) {
+                url="<br>  See <a href="+homePage+">"+homePage+"</a>";
+            }
+            out.write("<p>"+category+": could not find a dependency"
+                    +" of class "+classname
+                    +" from file <b>"+jarFile
+                    +"</b><br> "+errorText
+                    +url
+                    +"<br>The root cause was: "+ncdfe.getMessage()
+                    +"<br>This can happen e.g. if "+classname+" is in" 
+                    +" the 'common' classpath, but a dependency like "
+                    +" activation.jar is only in the webapp classpath."
+                    +"<p>");
+            return 1;
+        }
+    }
+
+    /**
+     * get the location of a class
+     * @param out
+     * @param clazz
+     * @return the jar file or path where a class was found
+     */
+
+    String getLocation(JspWriter out,
+                       Class clazz) {
+        try {
+            java.net.URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
+            String location = url.toString();
+            if(location.startsWith("jar")) {
+                url = ((java.net.JarURLConnection)url.openConnection()).getJarFileURL();
+                location = url.toString();
+            } 
+            
+            if(location.startsWith("file")) {
+                java.io.File file = new java.io.File(url.getFile());
+                return file.getAbsolutePath();
+            } else {
+                return url.toString();
+            }
+        } catch (Throwable t){
+        }
+        return "an unknown location";
+    }
+
+    /**
+     * a class we need if a class is missing
+     * @param out stream to print stuff
+     * @param classname class to look for
+     * @param jarFile where this class comes from
+     * @param errorText extra error text
+     * @param homePage where to d/l the library
+     * @throws IOException when needed
+     * @return the number of missing libraries (0 or 1)
+     */
+    int needClass(JspWriter out,
+                   String classname,
+                   String jarFile,
+                   String description,
+                   String errorText,
+                   String homePage) throws IOException {
+        return probeClass(out,
+                "<b>Error</b>",
+                classname,
+                jarFile,
+                description,
+                errorText,
+                homePage);
+    }
+
+    /**
+     * print warning message if a class is missing
+     * @param out stream to print stuff
+     * @param classname class to look for
+     * @param jarFile where this class comes from
+     * @param errorText extra error text
+     * @param homePage where to d/l the library
+     * @throws IOException when needed
+     * @return the number of missing libraries (0 or 1)
+     */
+    int wantClass(JspWriter out,
+                   String classname,
+                   String jarFile,
+                   String description,
+                   String errorText,
+                   String homePage) throws IOException {
+        return probeClass(out,
+                "<b>Warning</b>",
+                classname,
+                jarFile,
+                description,
+                errorText,
+                homePage);
+    }
+
+    /**
+     * probe for a resource existing,
+     * @param out
+     * @param resource
+     * @param errorText
+     * @throws Exception
+     */
+    int wantResource(JspWriter out,
+                      String resource,
+                      String errorText) throws Exception {
+        if(!resourceExists(resource)) {
+            out.write("<p><b>Warning</b>: could not find resource "+resource
+                        +"<br>"
+                        +errorText);
+            return 0;
+        } else {
+            out.write("found "+resource+"<br>");
+            return 1;
+        }
+    }
+
+
+    /**
+     *  get servlet version string
+     *
+     */
+
+    public String getServletVersion() {
+        ServletContext context=getServletConfig().getServletContext();
+        int major = context.getMajorVersion();
+        int minor = context.getMinorVersion();
+        return Integer.toString(major) + '.' + Integer.toString(minor);
+    }
+
+
+
+    /**
+     * what parser are we using.
+     * @return the classname of the parser
+     */
+    private String getParserName() {
+        SAXParser saxParser = getSAXParser();
+        if (saxParser == null) {
+            return "Could not create an XML Parser";
+        }
+
+        // check to what is in the classname
+        String saxParserName = saxParser.getClass().getName();
+        return saxParserName;
+    }
+
+    /**
+     * Create a JAXP SAXParser
+     * @return parser or null for trouble
+     */
+    private SAXParser getSAXParser() {
+        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
+        if (saxParserFactory == null) {
+            return null;
+        }
+        SAXParser saxParser = null;
+        try {
+            saxParser = saxParserFactory.newSAXParser();
+        } catch (Exception e) {
+        }
+        return saxParser;
+    }
+
+    /**
+     * get the location of the parser
+     * @return path or null for trouble in tracking it down
+     */
+
+    private String getParserLocation(JspWriter out) {
+        SAXParser saxParser = getSAXParser();
+        if (saxParser == null) {
+            return null;
+        }
+        String location = getLocation(out,saxParser.getClass());
+        return location;
+    }
+    %>
+<html><head><title>Axis Happiness Page</title></head>
+<body>
+<h1>Axis Happiness Page</h1>
+<h2>Examining webapp configuration</h2>
+
+<p>
+<h3>Needed Components</h3>
+<%
+    int needed=0,wanted=0;
+
+    /**
+     * the essentials, without these Axis is not going to work
+     */
+    needed=needClass(out, "javax.xml.soap.SOAPMessage",
+            "saaj.jar",
+            "SAAJ API",
+            "Axis will not work",
+            "http://xml.apache.org/axis/");
+
+    needed+=needClass(out, "javax.xml.rpc.Service",
+            "jaxrpc.jar",
+            "JAX-RPC API",
+            "Axis will not work",
+            "http://xml.apache.org/axis/");
+
+    needed+=needClass(out, "org.apache.axis.transport.http.AxisServlet",
+            "axis.jar",
+            "Apache-Axis",
+            "Axis will not work",
+            "http://xml.apache.org/axis/");
+
+    needed+=needClass(out, "org.apache.commons.discovery.Resource",
+            "commons-discovery.jar",
+            "Jakarta-Commons Discovery",
+            "Axis will not work",
+            "http://jakarta.apache.org/commons/discovery.html");
+
+    needed+=needClass(out, "org.apache.commons.logging.Log",
+            "commons-logging.jar",
+            "Jakarta-Commons Logging",
+            "Axis will not work",
+            "http://jakarta.apache.org/commons/logging.html");
+
+    needed+=needClass(out, "org.apache.log4j.Layout",
+            "log4j-1.2.8.jar",
+            "Log4j",
+            "Axis may not work",
+            "http://jakarta.apache.org/log4j");
+
+    //should we search for a javax.wsdl file here, to hint that it needs
+    //to go into an approved directory? because we dont seem to need to do that.
+    needed+=needClass(out, "com.ibm.wsdl.factory.WSDLFactoryImpl",
+            "wsdl4j.jar",
+            "IBM's WSDL4Java",
+            "Axis will not work",
+            null);
+
+    needed+=needClass(out, "javax.xml.parsers.SAXParserFactory",
+            "xerces.jar",
+            "JAXP implementation",
+            "Axis will not work",
+            "http://xml.apache.org/xerces-j/");
+
+    needed+=needClass(out,"javax.activation.DataHandler",
+            "activation.jar",
+            "Activation API",
+            "Axis will not work",
+            "http://java.sun.com/products/javabeans/glasgow/jaf.html");
+%>
+<h3>Optional Components</h3>
+<%
+    /*
+     * now the stuff we can live without
+     */
+    wanted+=wantClass(out,"javax.mail.internet.MimeMessage",
+            "mail.jar",
+            "Mail API",
+            "Attachments will not work",
+            "http://java.sun.com/products/javamail/");
+
+    wanted+=wantClass(out,"org.apache.xml.security.Init",
+            "xmlsec.jar",
+            "XML Security API",
+            "XML Security is not supported",
+            "http://xml.apache.org/security/");
+
+    wanted += wantClass(out, "javax.net.ssl.SSLSocketFactory",
+            "jsse.jar or java1.4+ runtime",
+            "Java Secure Socket Extension",
+            "https is not supported",
+            "http://java.sun.com/products/jsse/");
+    /*
+     * resources on the classpath path
+     */
+    /* broken; this is a file, not a resource
+    wantResource(out,"/server-config.wsdd",
+            "There is no server configuration file;"
+            +"run AdminClient to create one");
+    */
+    /* add more libraries here */
+
+    out.write("<h3>");
+    //is everythng we need here
+    if(needed==0) {
+       //yes, be happy
+        out.write("<i>The core axis libraries are present. </i>");
+    } else {
+        //no, be very unhappy
+        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        out.write("<i>"
+                +needed
+                +" core axis librar"
+                +(needed==1?"y is":"ies are")
+                +" missing</i>");
+    }
+    //now look at wanted stuff
+    if(wanted>0) {
+        out.write("<i>"
+                +wanted
+                +" optional axis librar"
+                +(wanted==1?"y is":"ies are")
+                +" missing</i>");
+    } else {
+        out.write("The optional components are present.");
+    }
+    out.write("</h3>");
+    //hint if anything is missing
+    if(needed>0 || wanted>0 ) {
+        out.write(getInstallHints(request));
+    }
+
+    %>
+    <p>
+    <B><I>Note:</I></B> Even if everything this page probes for is present, there is no guarantee your
+    web service will work, because there are many configuration options that we do
+    not check for. These tests are <i>necessary</i> but not <i>sufficient</i>
+    <hr>
+
+    <h2>Examining Application Server</h2>
+    <%
+        String servletVersion=getServletVersion();
+        String xmlParser=getParserName();
+        String xmlParserLocation = getParserLocation(out);
+
+    %>
+    <table>
+        <tr><td>Servlet version</td><td><%= servletVersion %></td></tr>
+        <tr><td>XML Parser</td><td><%= xmlParser %></td></tr>
+        <tr><td>XML ParserLocation</td><td><%= xmlParserLocation %></td></tr>
+    </table>
+<% if(xmlParser.indexOf("crimson")>=0) { %>
+    <p>
+    <b>We recommend <a href="http://xml.apache.org/xerces2-j/">Xerces 2</a>
+        over Crimson as the XML parser for Axis</b>
+    </p>
+<%    } %>
+
+    <h2>Examining System Properties</h2>
+<%
+    /** 
+     * Dump the system properties
+     */
+    java.util.Enumeration e=null;
+    try {
+        e= System.getProperties().propertyNames();
+    } catch (SecurityException se) {
+    }
+    if(e!=null) {
+        out.write("<pre>");
+        for (;e.hasMoreElements();) {
+            String key = (String) e.nextElement();
+            out.write(key + "=" + System.getProperty(key)+"\n");
+        }
+        out.write("</pre><p>");
+    } else {
+        out.write("System properties are not accessible<p>");
+    }
+%>
+    <hr>
+    Platform: <%= getServletConfig().getServletContext().getServerInfo()  %>
+</body>
+</html>
+
+
diff --git a/trunk/webapps/axis/index.html b/trunk/webapps/axis/index.html
new file mode 100644
index 0000000..30abc39
--- /dev/null
+++ b/trunk/webapps/axis/index.html
@@ -0,0 +1,48 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Type"
+content="text/html; charset=iso-8859-1">
+<title>Apache-Axis</title>
+</head>
+
+<body bgcolor="#FFFFFF">
+
+<h1 align="center">Apache-AXIS</h1>
+
+<p>Hello! <em>Welcome</em> to Apache-Axis.</p>
+
+<p>What do you want to do today?</p>
+
+<ul>
+    <li><a href="happyaxis.jsp">Validate</a>
+        the local installation's configuration<br>
+        <i>see below if this does not work.</i></li>
+    <li><a href="servlet/AxisServlet">View</a>
+        the list of deployed Web services</li>
+    <li><a href="EchoHeaders.jws?method=list">
+        Call a local endpoint</a> that list's the caller's
+        http headers (or see its
+        <a href="EchoHeaders.jws?wsdl">WSDL</a>). 
+    <li><a href="http://xml.apache.org/axis">Visit</a>
+        the Apache-Axis Home Page</li>
+    <li><a href="servlet/AdminServlet">Administer Axis</a> <br>
+        [disabled by default for security reasons]</li>
+    <li><a href="SOAPMonitor">SOAPMonitor</a> <br>
+        [disabled by default for security reasons]</li>
+</ul>
+To enable the disabled features, uncomment the appropriate declarations in 
+WEB-INF/web.xml in the webapplication and restart it.
+<h3>Validating Axis</h3>
+
+If the "happyaxis" validation page displays an exception instead of a 
+status page, the likely cause is that you have multiple XML parsers in 
+your classpath. Clean up your classpath by eliminating extraneous parsers. 
+
+<p>
+If you have problems getting Axis to work, consult the Axis 
+<a
+href="http://nagoya.apache.org/wiki/apachewiki.cgi?AxisProjectPages">Wiki</a>
+and then try the Axis user mailing list. 
+</body>
+</html>
diff --git a/trunk/webapps/axis/interop.jsp b/trunk/webapps/axis/interop.jsp
new file mode 100644
index 0000000..88bc26c
--- /dev/null
+++ b/trunk/webapps/axis/interop.jsp
@@ -0,0 +1,58 @@
+<html>

+<%@ page language="java" import="org.apache.ws.axis.oasis.ping.*, javax.xml.rpc.holders.StringHolder" %>

+

+<% 

+	String context = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/services" ;

+%>

+<head><title>WSS4J Interop Client</title></head>

+<body>

+<big><strong>WSS4J Interop Client</strong></big><p>

+If you have problems using this self-help page. Please send an email to <A href="mailto:dims@yahoo.com">Davanum Srinivas</a>

+<p/>

+<dl>

+<dt><strong>Interop Scenario 1</strong></dt>

+<dd><table border='0'><form method='POST' action='wss4j2.jsp'><INPUT NAME="scenario" TYPE=HIDDEN VALUE="1">

+<tr><td colspan='2'>URL: <input type='text' size='64' name='url' value='<%= context %>/Ping1' /></td></tr>

+

+<tr><td>&nbsp;</td><td align='right'><input type='submit' value='Interop 1'></td></tr>

+</form></table></dd>

+<dt><strong>Interop Scenario 2</strong></dt>

+<dd><table border='0'><form method='POST' action='wss4j2.jsp'><INPUT NAME="scenario" TYPE=HIDDEN VALUE="2">

+<tr><td colspan='2'>URL: <input type='text' size='64' name='url' value='<%= context %>/Ping2' /></td></tr>

+<tr><td>&nbsp;</td><td align='right'><input type='submit' value='Interop 2'></td></tr>

+</form></table></dd>

+<dt><strong>Interop Scenario 3</strong></dt>

+<dd><table border='0'><form method='POST' action='wss4j2.jsp'><INPUT NAME="scenario" TYPE=HIDDEN VALUE="3">

+<tr><td colspan='2'>URL: <input type='text' size='64' name='url' value='<%= context %>/Ping3' /></td></tr>

+

+<tr><td>&nbsp;</td><td align='right'><input type='submit' value='Interop 3'></td></tr>

+</form></table></dd>

+<dt><strong>Interop Scenario 4</strong></dt>

+<dd><table border='0'><form method='POST' action='wss4j2.jsp'><INPUT NAME="scenario" TYPE=HIDDEN VALUE="4">

+<tr><td colspan='2'>URL: <input type='text' size='64' name='url' value='<%= context %>/Ping4' /></td></tr>

+<tr><td>&nbsp;</td><td align='right'><input type='submit' value='Interop 4'></td></tr>

+</form></table></dd>

+<dt><strong>Interop Scenario 5</strong></dt>

+<dd><table border='0'><form method='POST' action='wss4j2.jsp'><INPUT NAME="scenario" TYPE=HIDDEN VALUE="5">

+<tr><td colspan='2'>URL: <input type='text' size='64' name='url' value='<%= context %>/Ping5' /></td></tr>

+<tr><td>&nbsp;</td><td align='right'><input type='submit' value='Interop 5'></td></tr>

+</form></table></dd>

+<dt><strong>Interop Scenario 6</strong></dt>

+

+<dd><table border='0'><form method='POST' action='wss4j2.jsp'><INPUT NAME="scenario" TYPE=HIDDEN VALUE="6">

+<tr><td colspan='2'>URL: <input type='text' size='64' name='url' value='<%= context %>/Ping6' /></td></tr>

+<tr><td>&nbsp;</td><td align='right'><input type='submit' value='Interop 6'></td></tr>

+</form></table></dd>

+<dt><strong>Interop Scenario 7</strong></dt>

+<dd><table border='0'><form method='POST' action='wss4j2.jsp'><INPUT NAME="scenario" TYPE=HIDDEN VALUE="7">

+<tr><td colspan='2'>URL: <input type='text' size='64' name='url' value='<%= context %>/Ping7' /></td></tr>

+<tr><td>&nbsp;</td><td align='right'><input type='submit' value='Interop 7'></td></tr>

+</form></table></dd>

+</dl>

+<p/>        <font size="-1">

+

+         <em>Copyright &#169; 1999-2004, The Apache Software Foundation</em>

+        </font>

+

+</body>

+</html>
\ No newline at end of file
diff --git a/trunk/webapps/axis/wss4j2.jsp b/trunk/webapps/axis/wss4j2.jsp
new file mode 100644
index 0000000..8ab3dbd
--- /dev/null
+++ b/trunk/webapps/axis/wss4j2.jsp
@@ -0,0 +1,56 @@
+<html>
+<%@ page language="java" import="org.apache.ws.axis.oasis.ping.*, javax.xml.rpc.holders.StringHolder" %>
+
+<% 
+	String url = request.getParameter ("url");
+	String scenario = request.getParameter ("scenario").trim();
+%>
+<head><title>WSS4J Interop Scenario <%= scenario %> Results</title></head>
+<body>
+<big><strong>WSS4J Interop Scenario <%= scenario %> Results</strong></big><p>
+<strong>Server URL:</strong> <%= url %><p>
+
+<%
+        PingServiceLocator service = new PingServiceLocator();
+        java.net.URL endpoint = new java.net.URL(url);
+        PingPort port = null;
+        if(scenario.equals("1"))
+             port = (PingPort) service.getPing1(endpoint);
+        else if(scenario.equals("2"))
+             port = (PingPort) service.getPing2(endpoint);
+        else if(scenario.equals("3"))
+             port = (PingPort) service.getPing3(endpoint);
+        else if(scenario.equals("4"))
+             port = (PingPort) service.getPing4(endpoint);
+        else if(scenario.equals("5"))
+             port = (PingPort) service.getPing5(endpoint);
+        else if(scenario.equals("6"))
+             port = (PingPort) service.getPing6(endpoint);
+        else if(scenario.equals("7"))
+             port = (PingPort) service.getPing7(endpoint);
+
+        StringHolder text =
+                new StringHolder("WSS4J - Scenario " + scenario + " @ [" + new java.util.Date(System.currentTimeMillis()) + "]");
+%>
+<strong>Request:</strong> <%= text.value %><p>
+
+<%
+
+        port.ping(new org.apache.ws.axis.oasis.ping.TicketType("WSS4J" + scenario), text);
+        System.out.println(text.value);
+
+%>
+<strong>Response:</strong> <%= text.value %><p>
+
+<p/>
+<font size="-1">
+<A HREF="wss4j.html">Go Back</A>
+</font>
+<p/>        <font size="-1">
+
+         <em>Copyright &#169; 1999-2004, The Apache Software Foundation</em>
+        </font>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/trunk/xdocs/api.xml b/trunk/xdocs/api.xml
new file mode 100644
index 0000000..2c94a03
--- /dev/null
+++ b/trunk/xdocs/api.xml
@@ -0,0 +1,541 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<document><properties><title>Apache WSS4J API Overview</title></properties><body><section name="Apache WSS4J API Overview"></section><section name=""><subsection name="Contents"><ul>
+  <li><a href="#API_Overview">API Overview</a><br></br>
+  </li>
+  <ul>
+    <li><a href="#org.apache.ws.security.WSSecurityEngine">WSSecurityEngine</a></li>
+    <li><a href="#org.apache.ws.security.message.WSBaseMessage">WSBaseMessage</a></li>
+    <li><a href="#org.apache.ws.security.message.WSSignEnvelope">WSSignEnvelope</a> 
+(extends WSBaseMessage)</li>
+    <li><a href="#org.apache.ws.security.message.WSAddTimestamp">WSAddTimestamp</a> 
+(extends WSBaseMessage)</li>
+    <li><a href="#org.apache.ws.security.message.WSEncryptBody">WSEncryptBody</a>  
+(extends WSBaseMessage)</li>
+    <li><a href="#org.apache.ws.security.message.WSAddUsernameToken">WSAddUsernameToken</a>
+(extends WSBaseMessage)</li>
+    <li><a href="#org.apache.ws.security.message.WSSAddSAMLToken">WSSAddSAMLToken</a>
+(extends WSBaseMessage)</li>
+  </ul>
+  <li><a href="#Examples">Examples</a></li>
+  <ul>
+    <li>Sign the SOAP Body</li>
+    <li>Encrypt the SOAP Body</li>
+    <li>Process WSS Header and Check the Results<br></br>
+    </li>
+  </ul>
+</ul><br></br></subsection></section><section name=""><subsection name="API Overview"><p>WSS4J can be used as a library to provide an API for WS-Security
+processing. In this case WSS4J does not need to be used with Axis, or
+even be a part of a deployed web application. The WSS4J API can be
+invoked directly to create WS-Security headers or process them given a
+SOAP Envelope DOM Document.<br></br>
+</p><p>Following is an overview of the main classes and methods for the
+WSS4J API. Please refer to the java docs for the complete API
+documentation.<br></br>
+</p></subsection><subsection name="org.apache.ws.security.WSSecurityEngine"><table style="width: 100%; text-align: left;" border="0" cellpadding="4" cellspacing="4">
+  <tbody>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Action<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Method<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle;">Get an instance of security
+engine </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top;">
+      <pre>public static org.apache.ws.security.WSSecurityEngine getInstance()</pre>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Description<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 255, 255);">Get
+a singleton instance of security engine
+class. If you need to get an instance configured for an older spec
+(different namespaces) then use the other method which takes
+org.apache.ws.security.WSSConfig<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td colspan="1" rowspan="4" style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Parameters<br></br>
+      </td>
+    </tr>
+    <tr>
+    </tr>
+    <tr>
+    </tr>
+    <tr>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204);"><span style="font-weight: bold;">Returns</span><br></br>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">
+      <pre>org.apache.ws.security.WSSecurityEngine</pre>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">Processes
+WS-Security Headers in a SOAP Envelope<br></br>
+      </td>
+    </tr>
+  </tbody>
+</table><br></br><table style="width: 100%; text-align: left;" border="0" cellpadding="4" cellspacing="4">
+  <tbody>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Action<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Method<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle;">Verify WSS Headers<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top;">
+      <pre>java.util.Vector <b>processSecurityHeader</b>(<br></br>    org.w3c.dom.Document doc,<br></br>    java.lang.String actor,<br></br>    javax.security.auth.callback.CallbackHandler cb,<br></br>    org.apache.ws.security.components.crypto.Crypto crypto<br></br>    ) throws org.apache.ws.security.WSSecurityException</pre>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Description<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 255, 255);">Takes
+a SOAP Envelope as a W3C Document and verifies the WSS Headers. 
+This
+includes Username Token processing, Signature verification, decryption
+and timestamp verification. In the case of encrypted elements,
+decryption is performed live on the passed document, i.e., it is
+transformed into the decrypted format.<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td colspan="1" rowspan="4" style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Parameters<br></br>
+      </td>
+      <td style="vertical-align: top; font-weight: bold;">
+      <pre>doc</pre>
+      </td>
+      <td style="vertical-align: top;">the SOAP Envelope as W3C DOM
+Document</td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; font-weight: bold; background-color: rgb(204, 255, 255);">actor</td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">the
+engine works on behalf of this actor. Refer to the SOAP specification
+about actor or role, this may be null.<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; font-weight: bold;">cb<br></br>
+      </td>
+      <td style="vertical-align: top;">a callback hander to the caller
+to resolve passwords during encryption and UsernameToken handling, this
+may be null.<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; font-weight: bold; background-color: rgb(204, 255, 255);">crypto<br></br>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">the
+object that implements the access to the keystore and the handling of
+certificates. A default implementation is included:
+org.apache.ws.security.components.crypto.Merlin<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204);"><span style="font-weight: bold;">Returns</span><br></br>
+      </td>
+      <td style="vertical-align: top;">
+      <pre>java.util.Vector</pre>
+      </td>
+      <td style="vertical-align: top;">Vector of
+org.apache.ws.security.WSSecurityEngineResult, this has the information
+resulting from the processing, such as the principal, SAML token, etc.<br></br>
+      </td>
+    </tr>
+  </tbody>
+</table><br></br></subsection><subsection name="org.apache.ws.security.message.WSBaseMessage"><table style="width: 100%; text-align: left;" border="0" cellpadding="4" cellspacing="4">
+  <tbody>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Action<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Method<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle;">Set the Signature/Encryption
+parts<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top;">
+      <pre>public void setParts(java.util.Vector parts)</pre>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Description<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 255, 255);">Takes
+a vector of org.apache.ws.security.WSEncryptionPart.<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td colspan="1" rowspan="2" style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Parameters<br></br>
+      </td>
+      <td style="vertical-align: top; font-weight: bold;">
+      <pre>doc</pre>
+      </td>
+      <td style="vertical-align: top;">the SOAP Envelope as W3C DOM
+Document</td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; font-weight: bold; background-color: rgb(204, 255, 255);">crypto<br></br>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">the
+object that implements the access to the keystore and the handling of
+certificates. A default implementation is included:
+org.apache.ws.security.components.crypto.Merlin<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204);"><span style="font-weight: bold;">Returns</span><br></br>
+      </td>
+      <td style="vertical-align: top;">
+      <pre>org.w3c.dom.Document</pre>
+      </td>
+      <td style="vertical-align: top;">the
+SOAP Envelope Signed. The signed elements depend on the signature parts
+that are specified by the WSBaseMessage.setParts(java.util.Vector
+parts) method<br></br>
+      </td>
+    </tr>
+  </tbody>
+</table><br></br></subsection><subsection name="org.apache.ws.security.message.WSSignEnvelope
+(extends WSBaseMessage)"><table style="width: 100%; text-align: left;" border="0" cellpadding="4" cellspacing="4">
+  <tbody>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Action<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Method<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle;">Signs a SOAP Envelope<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top;">
+      <pre>public org.w3c.dom.Document build(<br></br>    org.w3c.dom.Document doc,<br></br>    org.apache.ws.security.components.crypto.Crypto crypto<br></br>    ) throws org.apache.ws.security.WSSecurityException</pre>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Description<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 255, 255);">Takes
+a SOAP Envelope as a W3C Document and adds WSS Signature header to it.
+The signed elements depend on the signature parts
+that are specified by the WSBaseMessage.setParts(java.util.Vector
+parts) method. By default, SOAP Body is signed </td>
+    </tr>
+    <tr>
+      <td colspan="1" rowspan="2" style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Parameters<br></br>
+      </td>
+      <td style="vertical-align: top; font-weight: bold;">
+      <pre>doc</pre>
+      </td>
+      <td style="vertical-align: top;">the SOAP Envelope as W3C DOM
+Document</td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; font-weight: bold; background-color: rgb(204, 255, 255);">crypto<br></br>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">the
+object that implements the access to the keystore and the handling of
+certificates. A default implementation is included:
+org.apache.ws.security.components.crypto.Merlin<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204);"><span style="font-weight: bold;">Returns</span><br></br>
+      </td>
+      <td style="vertical-align: top;">
+      <pre>org.w3c.dom.Document</pre>
+      </td>
+      <td style="vertical-align: top;">the
+SOAP Envelope signed.<br></br>
+      </td>
+    </tr>
+  </tbody>
+</table><br></br></subsection><subsection name="org.apache.ws.security.message.WSAddTimestamp
+(extends WSBaseMessage)"><table style="width: 100%; text-align: left;" border="0" cellpadding="4" cellspacing="4">
+  <tbody>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Action<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Method<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle;">Add a Timestamp Token to a
+SOAP Envelope </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top;">
+      <pre>public org.w3c.dom.Document <b>build</b>(<br></br>    org.w3c.dom.Document doc,<br></br>    int ttl)</pre>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Description<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 255, 255);">Takes
+a SOAP Envelope as a W3C Document and adds a Timestamp header to
+it. Please refer to the WS specification 1.0. chapter 10 / appendix A.2
+      <p> </p>
+      <p> </p>
+      </td>
+    </tr>
+    <tr>
+      <td colspan="1" rowspan="2" style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Parameters<br></br>
+      </td>
+      <td style="vertical-align: top; font-weight: bold;">
+      <pre>doc</pre>
+      </td>
+      <td style="vertical-align: top;">the SOAP Envelope as W3C DOM
+Document</td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; font-weight: bold; background-color: rgb(204, 255, 255);">
+      <pre>ttl</pre>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">(time
+to live) This is the time difference in seconds between the <code>Created</code>
+and the <code>Expires</code> in <code>Timestamp</code>, set to zero
+if <code>Expires</code> should not be added. </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204);"><span style="font-weight: bold;">Returns</span><br></br>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(255, 255, 255);">
+      <pre>org.w3c.dom.Document</pre>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(255, 255, 255);">the
+SOAP Envelope with the Timestamp added<br></br>
+      </td>
+    </tr>
+  </tbody>
+</table><br></br></subsection><subsection name="org.apache.ws.security.message.WSEncryptBody
+(extends WSBaseMessage)"><table style="width: 100%; text-align: left;" border="0" cellpadding="4" cellspacing="4">
+  <tbody>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Action<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Method<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle;">Encrypt a SOAP Envelope<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top;">
+      <pre>public org.w3c.dom.Document build(<br></br>    org.w3c.dom.Document doc,<br></br>    org.apache.ws.security.components.crypto.Crypto crypto<br></br>    ) throws org.apache.ws.security.WSSecurityException</pre>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Description<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 255, 255);">Takes
+a SOAP Envelope as a W3C Document and adds WSS Encryption header to it.
+Unlike
+what the class name might imply, this can be used to encrypt elements
+in the SOAP Header, such as Username Tokens or other arbitrary
+elements. The encrypted elements depend on the signature parts
+that are specified by the WSBaseMessage.setParts(java.util.Vector
+parts) method. By default, SOAP Body is encrypted</td>
+    </tr>
+    <tr>
+      <td colspan="1" rowspan="2" style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Parameters<br></br>
+      </td>
+      <td style="vertical-align: top; font-weight: bold;">
+      <pre>doc</pre>
+      </td>
+      <td style="vertical-align: top;">the SOAP Envelope as W3C DOM
+Document</td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; font-weight: bold; background-color: rgb(204, 255, 255);">crypto<br></br>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">the
+object that implements the access to the keystore and the handling of
+certificates. A default implementation is included:
+org.apache.ws.security.components.crypto.Merlin<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204);"><span style="font-weight: bold;">Returns</span><br></br>
+      </td>
+      <td style="vertical-align: top;">
+      <pre>org.w3c.dom.Document</pre>
+      </td>
+      <td style="vertical-align: top;">the
+SOAP Envelope encrypted.<br></br>
+      </td>
+    </tr>
+  </tbody>
+</table><br></br></subsection><subsection name="org.apache.ws.security.message.WSAddUsernameToken
+(extends WSBaseMessage)"><table style="width: 100%; text-align: left;" border="0" cellpadding="4" cellspacing="4">
+  <tbody>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Action<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Method<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle;">Add a Username Token to a
+SOAP Envelope<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top;">
+      <pre>public org.w3c.dom.Document build(<br></br>    org.w3c.dom.Document doc,<br></br>    java.lang.String username,<br></br>    java.lang.String password)</pre>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Description<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 255, 255);">Takes
+a SOAP Envelope as a W3C Document and adds a Username Token header to
+it. Use setPasswordType(java.lang.String pwType) to choose between
+plain text passwords and digested ones. </td>
+    </tr>
+    <tr>
+      <td colspan="1" rowspan="3" style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Parameters<br></br>
+      </td>
+      <td style="vertical-align: top; font-weight: bold;">
+      <pre>doc</pre>
+      </td>
+      <td style="vertical-align: top;">the SOAP Envelope as W3C DOM
+Document</td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; font-weight: bold; background-color: rgb(204, 255, 255);">username<br></br>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">the
+username to use<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top;">password<br></br>
+      </td>
+      <td style="vertical-align: top;">the password to use (a plain
+text string)<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204);"><span style="font-weight: bold;">Returns</span><br></br>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">
+      <pre>org.w3c.dom.Document</pre>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">the
+SOAP Envelope with the username token header added<br></br>
+      </td>
+    </tr>
+  </tbody>
+</table><br></br></subsection><subsection name="org.apache.ws.security.message.WSSAddSAMLToken
+(extends WSBaseMessage)"><table style="width: 100%; text-align: left;" border="0" cellpadding="4" cellspacing="4">
+  <tbody>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Action<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 204, 204); font-weight: bold;">Method<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle;">Add a SAML Token to a SOAP
+Envelope </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top;">
+      <pre>public org.w3c.dom.Document build(<br></br>    org.w3c.dom.Document doc,<br></br>    org.opensaml.SAMLAssertion assertion)</pre>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Description<br></br>
+      </td>
+      <td colspan="2" rowspan="1" style="vertical-align: top; background-color: rgb(204, 255, 255);">Takes
+a SOAP Envelope as a W3C Document and adds a SAML Assertion Token
+header to
+it. Please refer to the OpenSAML documentation on how to construct SAML
+assertions.<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td colspan="1" rowspan="2" style="vertical-align: middle; background-color: rgb(204, 204, 204); font-weight: bold;">Parameters<br></br>
+      </td>
+      <td style="vertical-align: top; font-weight: bold;">
+      <pre>doc</pre>
+      </td>
+      <td style="vertical-align: top;">the SOAP Envelope as W3C DOM
+Document</td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; font-weight: bold; background-color: rgb(204, 255, 255);">
+      <pre>assertion</pre>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(204, 255, 255);">the
+SAML assertion to add<br></br>
+      </td>
+    </tr>
+    <tr>
+      <td style="vertical-align: top; background-color: rgb(204, 204, 204);"><span style="font-weight: bold;">Returns</span><br></br>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(255, 255, 255);">
+      <pre>org.w3c.dom.Document</pre>
+      </td>
+      <td style="vertical-align: top; background-color: rgb(255, 255, 255);">the
+SOAP Envelope with the SAML assertion header added<br></br>
+      </td>
+    </tr>
+  </tbody>
+</table><br></br></subsection><subsection name="Examples"></subsection><subsection name="Sign the SOAP Body"><small>Document envelope = ...<br></br>
+WSSignEnvelope signer = new WSSignEnvelope();<br></br>
+Crypto crypto = CryptoFactory.getInstance("crypto.properties");<br></br>
+Vector parts = new Vector();<br></br>
+WSEncryptionPart part = new
+WSEncryptionPart(soapConstants.getBodyQName().getLocalPart(),<br></br>
+                       
+                 
+   soapConstants.getEnvelopeURI(),<br></br>
+                 
+                          
+"Content");<br></br>
+parts.add(part);<br></br>
+signer.setParts(parts); // this is optional since the body is signed by
+default<br></br>
+envelope = signer.build(envelope, crypto);</small><br></br></subsection><subsection name="Encrypt the SOAP Body"><small>Document envelope = ...<br></br>
+WSEncryptBody encryptor = new WSEncryptBody();<br></br>
+Crypto crypto = CryptoFactory.getInstance("crypto.properties");<br></br>
+Vector parts = new Vector();<br></br>
+WSEncryptionPart part = new
+WSEncryptionPart(soapConstants.getBodyQName().getLocalPart(),<br></br>
+                       
+                 
+   soapConstants.getEnvelopeURI(),<br></br>
+                 
+                          
+"Content");<br></br>
+parts.add(part);<br></br>
+encryptor.setParts(parts); </small><small>// this is optional since
+the body is encrypted by default</small><br></br><small>envelope = encryptor.build(envelope, crypto);</small><br></br></subsection><subsection name="Process WSS Header and Check the Results"><small>
+Document envelope = ...<br></br>
+WSSecurityEngine secEngine = WSSecurityEngine.getInstance();<br></br>
+Crypto crypto = CryptoFactory.getInstance("crypto.properties");<br></br>
+<code>// </code><code>javax.security.auth.callback.CallbackHandler<br></br>
+// please refer to the tests for examples of callback handlers<br></br>
+</code><code>CallbackHandler cb = new MyCallbackHandler();</code><code></code><br></br>
+Vector results = secEngine.processSecurityHeader(envelope, null, <code>cb</code>,
+crypto);<br></br>
+for (int i = 0; i &lt; results.size(); i++) {<br></br>
+    WSHandlerResult hResult =
+(WSHandlerResult)results.get(i);<br></br>
+    String actor = hResult.getActor();<br></br>
+    Vector hResults = hResult.getResults();<br></br>
+    for (int j = 0; j &lt; hResults.size(); j++) {<br></br>
+        WSSecurityEngineResult
+eResult = (WSSecurityEngineResult)hResults.get(j);<br></br>
+        // Note: an encryption
+action does not have an associated principal<br></br>
+        // only Signature and
+UsernameToken actions return a principal<br></br>
+        if (eResult.getAction() !=
+WSConstants.ENCR) {<br></br>
+           
+System.out.println(eResult.getPrincipal().getName());<br></br>
+        }<br></br>
+    }<br></br>
+}</small><br></br></subsection></section></body></document>
\ No newline at end of file
diff --git a/trunk/xdocs/axis.xml b/trunk/xdocs/axis.xml
new file mode 100644
index 0000000..e56a36a
--- /dev/null
+++ b/trunk/xdocs/axis.xml
@@ -0,0 +1,393 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<document><properties><title>Axis Deployment Tutorial</title></properties><body><section name="Apache WSS4J"></section><section name="Axis Deployment Tutorial"></section><section name=""><subsection name="Contents"><ul>
+  <li>Introduction</li>
+  <li>Prerequisties</li>
+  <li>Steps</li>
+  <ul>
+    <li>Username Token<br></br>
+    </li>
+  </ul>
+</ul></subsection></section><section name=""><subsection name="Introduction"><div style="margin-left: 40px;">WSS4J can be used for securing web
+services deployed in virtually any application server, but it includes
+special support for Axis. WSS4J ships with handlers that can be used in
+Axis-based web
+services for an easy integration. These handlers can be added to the
+service deployment
+descriptor (wsdd file) to add a WS-Security layer to the web service.
+This is a step by step tutorial for deploying a simple service with
+Username Token.<br></br>
+</div><br></br></subsection><subsection name="Prerequisties"><div style="margin-left: 40px;"><a href="http://ws.apache.org/axis/">Axis
+1.2</a> installed and configured on a <a href="http://jakarta.apache.org/tomcat/">Tomcat Server</a>.  This
+tutorial was performed on a Linux machine with Tomcat 5.5.4/Java 1.5.0,
+however, the setup should be similar on other application servers, or
+other operating systems (like Windows) unless we stated otherwise.<br></br>
+</div></subsection><subsection name="Steps"></subsection><subsection name="    Installing WSS4J"><div style="margin-left: 40px;">
+<ol>
+  <li>Download the WSS4J binaries or build it from sources<br></br>
+  </li>
+  <li>Copy the contents of the WSS4J lib directory to your Axis
+WEB-INF/lib directory. Many jar files will already exist. Most of them
+will already exist there but you can just overwrite them all.</li>
+  <li>You may need to restart Tomcat unless you have automatic
+deployment/class loading turned on. Check the Axis Happiness Page
+(typically at http://localhost:8080/axis), make sure that the XML
+Security (xmlsec.jar) is listed under the "Optional Components" section.</li>
+</ol>
+<h4>Creating the Service</h4>
+</div><ol>
+  <ol>
+    <li>This tutorial will secure the StockQuoteService which ships
+with Axis. Unless you have one already, create a deployment descriptor
+(deploy.wsdd) file with the following contents:</li>
+  </ol>
+</ol><div style="margin-left: 40px;">
+<ol start="2">
+  <br></br>
+  <span style="color: rgb(0, 0, 153);">&lt;deployment
+xmlns="http://xml.apache.org/axis/wsdd/"
+xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+  <span style="color: rgb(0, 0, 153);"> &lt;service
+name="stock-wss-01" provider="java:RPC" style="document"
+use="literal"&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+  <span style="color: rgb(0, 0, 153);">  &lt;parameter
+name="className" value="samples.stock.StockQuoteService"/&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+  <span style="color: rgb(0, 0, 153);">  &lt;parameter
+name="allowedMethods" value="getQuote"/&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+  <span style="color: rgb(0, 0, 153);">  &lt;parameter
+name="scope" value="application"/&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+  <span style="color: rgb(0, 0, 153);"> &lt;/service&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+  <span style="color: rgb(0, 0, 153);">&lt;/deployment&gt;<br></br>
+  <br></br>
+  </span><li>deploy the service (using AxisAdmin):</li>
+</ol>
+</div><div style="margin-left: 40px;">
+<ol>
+  <span style="color: rgb(0, 0, 153);">java
+org.apache.axis.client.AdminClient
+-lhttp://localhost:8080/axis/services/AdminService deploy.wsdd<br></br>
+  </span>
+</ol>
+<h4>Creating the Client</h4>
+<ol>
+  <li>Use WSDL2Java to generate the client service bindings:<br></br>
+    <span style="color: rgb(0, 0, 153);">java
+org.apache.axis.wsdl.WSDL2Java -o .
+-Nhttp://fox:8080/axis/services/stock-wss-01 samples.stock.client
+http://fox:8080/axis/services/stock-wss-01?wsdl</span><br></br>
+    <br></br>
+A bunch of java classes will be created under samples/stock/client,
+including the StockQuoteServiceServiceLocator.<br></br>
+    <br></br>
+  </li>
+  <li>Write a simple java client that uses the generated service
+locator. For example:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);">package samples.stock.client;</span><br style="color: rgb(0, 0, 153);"></br>
+    <br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+java.rmi.RemoteException;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+javax.xml.rpc.ServiceException;</span><br style="color: rgb(0, 0, 153);"></br>
+    <br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">public class
+StockServiceClient {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">    public
+StockServiceClient() {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">    }</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">    public
+static void main(String[] args) throws ServiceException,
+RemoteException {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+if (args.length == 0) {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">           
+System.out.println("Usage:\njava StockServiceClient [symbol]");</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">           
+return;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+}</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+StockQuoteServiceService locator = new
+StockQuoteServiceServiceLocator();</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+StockQuoteService service = locator.getStockWss01();</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+float quote = service.getQuote(args[0]);</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+System.out.println("stock quote service returned " + args[0] + ": " +
+quote);</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">    }</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">}</span><br></br>
+    <br></br>
+  </li>
+  <li>run the client:<br></br>
+    <span style="color: rgb(0, 0, 153);">java
+samples.stock.client.StockServiceClient IBM</span><br></br>
+    <br></br>
+If all went well, you should get the result:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);"></span> <span style="color: rgb(0, 0, 153);">stock quote service returned IBM: 95.68</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);"><br></br>
+    </span></li>
+</ol>
+</div><div style="margin-left: 40px;">
+<h3>Username Token</h3>
+<h4>Configuring the Service<br></br>
+</h4>
+<ol>
+  <li>Modify the deployment descriptor you created above to look like
+this:<br></br>
+    <span style="color: rgb(0, 0, 153);">&lt;deployment
+xmlns="http://xml.apache.org/axis/wsdd/"
+xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);"> &lt;service
+name="stock-wss-01" provider="java:RPC" style="document"
+use="literal"&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153); font-weight: bold;"> 
+&lt;requestFlow&gt;</span><br style="color: rgb(0, 0, 153); font-weight: bold;"></br>
+    <span style="color: rgb(0, 0, 153); font-weight: bold;">  
+&lt;handler type="java:org.apache.ws.axis.security.WSDoAllReceiver"&gt;</span><br style="color: rgb(0, 0, 153); font-weight: bold;"></br>
+    <span style="color: rgb(0, 0, 153); font-weight: bold;">   
+&lt;parameter name="passwordCallbackClass" value="PWCallback"/&gt;</span><br style="color: rgb(0, 0, 153); font-weight: bold;"></br>
+    <span style="color: rgb(0, 0, 153); font-weight: bold;">   
+&lt;parameter name="action" value="UsernameToken"/&gt;</span><br style="color: rgb(0, 0, 153); font-weight: bold;"></br>
+    <span style="color: rgb(0, 0, 153); font-weight: bold;"></span><span style="color: rgb(0, 0, 153); font-weight: bold;">  
+&lt;/handler&gt;</span><br style="color: rgb(0, 0, 153); font-weight: bold;"></br>
+    <span style="color: rgb(0, 0, 153); font-weight: bold;"> 
+&lt;/requestFlow&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">  &lt;parameter
+name="className" value="samples.stock.StockQuoteService"/&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">  &lt;parameter
+name="allowedMethods" value="getQuote"/&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">  &lt;parameter
+name="scope" value="application"/&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);"> &lt;/service&gt;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">&lt;/deployment&gt;<br></br>
+    <br></br>
+    </span>WSDoAllReceiver is an Axis handler that can be located in
+wss4j.jar. This is the standard way to deploy an Axis handler. For more
+details please refer to the Axis handler for WSS4J documentation.<br></br>
+    <br></br>
+  </li>
+  <li>Create a class named PWCallback.java and compile it into your
+Axis WEB-INF/classes directory. In this example I used the default
+package for simplicity, but you might need to use the fully qualified
+class name (be consistent
+with the deployment descriptor).<br></br>
+    <br></br>
+The following code snippet shows a simple password callback class:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);">import java.io.IOException;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+javax.security.auth.callback.Callback;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+javax.security.auth.callback.CallbackHandler;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+javax.security.auth.callback.UnsupportedCallbackException;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+org.apache.ws.security.WSPasswordCallback;</span><br style="color: rgb(0, 0, 153);"></br>
+    <br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">public class PWCallback
+implements CallbackHandler {</span><span style="color: rgb(0, 0, 153);"></span><span style="color: rgb(0, 0, 153);"></span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">    public void
+handle(Callback[] callbacks)</span><span style="color: rgb(0, 0, 153);">
+throws IOException, UnsupportedCallbackException {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+for (int i = 0; i &lt; callbacks.length; i++) {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">           
+if (callbacks[i] instanceof WSPasswordCallback) {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">               
+WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];<br></br>
+               
+// set the password given a username<br></br>
+    </span>               
+    <span style="color: rgb(0, 0, 153);">if
+("wss4j".equals(pc.getIdentifier())) {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">                   
+pc.setPassword("security");</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">               
+}</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);"></span><span style="color: rgb(0, 0, 153);">           
+} else {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">               
+throw new UnsupportedCallbackException(</span><span style="color: rgb(0, 0, 153);">callbacks[i], "Unrecognized Callback");</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">           
+}</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+}</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">    }</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">}</span><br></br>
+    <span style="font-weight: bold;"></span><br></br>
+    <br></br>
+    <br></br>
+  </li>
+  <li>Redeploy the service. Your service should now be expecting a WSS
+Username Token in in the incoming requests, and clients should send the
+username "wss4j" and password "security" to get through.<br></br>
+  </li>
+</ol>
+<h4>Configuring the Client</h4>
+<ol>
+  <li>run the client we created again:<br></br>
+    <span style="color: rgb(0, 0, 153);">java
+samples.stock.client.StockServiceClient IBM</span><br></br>
+    <br></br>
+You should now get an error:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);">Exception in thread "main"
+AxisFault</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);"> faultCode:
+{http://schemas.xmlsoap.org/soap/envelope/}Server.generalException</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);"> faultSubcode:</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);"> faultString:
+WSDoAllReceiver: Request does not contain required Security header</span><br></br>
+    <br></br>
+This is because your client is not configured to send a Username Token
+yet, so the service is rejecting the request.<br></br>
+    <br></br>
+  </li>
+  <li>Create a deployment descriptor file (client_deploy.wsdd) for the
+client:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);">&lt;deployment
+xmlns="http://xml.apache.org/axis/wsdd/"
+xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;<br></br>
+ &lt;transport name="http"
+pivot="java:org.apache.axis.transport.http.HTTPSender"/&gt;<br></br>
+  &lt;globalConfiguration &gt;<br></br>
+   &lt;requestFlow &gt;<br></br>
+    &lt;handler
+type="java:org.apache.ws.axis.security.WSDoAllSender" &gt;<br></br>
+     &lt;parameter name="action"
+value="UsernameToken"/&gt;<br></br>
+     &lt;parameter name="user" value="wss4j"/&gt;<br></br>
+     &lt;parameter name="passwordCallbackClass"
+value="samples.stock.client.PWCallback"/&gt;<br></br>
+     &lt;parameter name="passwordType"
+value="PasswordDigest"/&gt;<br></br>
+    &lt;/handler&gt;<br></br>
+   &lt;/requestFlow &gt;<br></br>
+  &lt;/globalConfiguration &gt;<br></br>
+&lt;/deployment&gt;</span><span style="color: rgb(0, 0, 153);"></span><br></br>
+    <br></br>
+  </li>
+  <li>Create the <span style="color: rgb(0, 0, 153);">samples.stock.client.PWCallback</span>
+class:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);">package samples.stock.client;</span><br style="color: rgb(0, 0, 153);"></br>
+    <br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import java.io.IOException;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+javax.security.auth.callback.Callback;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+javax.security.auth.callback.CallbackHandler;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+javax.security.auth.callback.UnsupportedCallbackException;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+org.apache.ws.security.WSPasswordCallback;</span><br style="color: rgb(0, 0, 153);"></br>
+    <br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">/**</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);"> * PWCallback for the
+Client</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);"> */</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">public class PWCallback
+implements CallbackHandler {</span><br style="color: rgb(0, 0, 153);"></br>
+    <br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">    /**</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">     *
+@see
+javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">     */</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">    public void
+handle(Callback[] callbacks) throws IOException,</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">                   
+UnsupportedCallbackException {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+for (int i = 0; i &lt; callbacks.length; i++) {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">           
+if (callbacks[i] instanceof WSPasswordCallback) {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">               
+WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">               
+// set the password given a username</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">               
+if ("wss4j".equals(pc.getIdentifier())) {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">                   
+pc.setPassword("security");</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">               
+}</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">           
+} else {</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">               
+throw new UnsupportedCallbackException(callbacks[i], "Unrecognized
+Callback");</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">           
+}</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">       
+}</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">    }</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">}</span><br></br>
+    <br></br>
+  </li>
+  <li>Define the system property axis.ClientConfigFile for your client:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);">java
+-Daxis.ClientConfigFile=client_deploy.wsdd -classpath $AXISCLASSPATH
+samples.stock.client.StockServiceClient</span><br></br>
+    <br></br>
+Make sure that your classpath includes the jar files under WEB-INF/lib.<br></br>
+    <br></br>
+Another way to do this is to specify the wsdd file in your
+StockServiceClient to the service locator programmatically:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);">...</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+org.apache.axis.EngineConfiguration;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+org.apache.axis.configuration.FileProvider;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">...</span><br style="color: rgb(0, 0, 153);"></br>
+    <br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">EngineConfiguration config =
+new FileProvider("client_deploy.wsdd");</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">StockQuoteServiceService
+locator = new StockQuoteServiceServiceLocator(config);</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">...</span><br></br>
+    <br></br>
+  </li>
+  <li>Run the client, you should get no errors:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);">stock quote service returned
+IBM: 95.7</span><br></br>
+    <br></br>
+Your client is now sending a Username Token in the wsse request header
+with the username "wss4j" (see client_deploy.wsdd) and password
+"security" (see the PWCallback implementation).<br></br>
+    <br></br>
+Another way to do this is to have the client application set the
+username and CallbackHandler implementation programmatically instead of
+client_deploy.wsdd:<br></br>
+    <br></br>
+    <span style="color: rgb(0, 0, 153);">...</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">import
+org.apache.axis.client.Stub;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">...</span><br style="color: rgb(0, 0, 153);"></br>
+    <br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">Remote remote =
+locator.getPort(StockQuoteService.class);</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">Stub axisPort = (Stub)remote;</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">axisPort._setProperty(UsernameToken.PASSWORD_TYPE,
+WSConstants.PASSWORD_DIGEST);</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">axisPort._setProperty(WSHandlerConstants.USER,
+"wss4j");</span><br style="color: rgb(0, 0, 153);"></br>
+    <span style="color: rgb(0, 0, 153);">axisPort._setProperty(WSHandlerConstants.PW_CALLBACK_REF,
+pwCallback);</span><br></br>
+    <br></br>
+where "pwCallback" is a reference to a PWCallback implementation. See
+the Axis handler for WSS4J documentation for more details on this.<br></br>
+    <br></br>
+  </li>
+  <li>Try modifying your client's PWCallback to return the wrong
+password, or send the wrong username. The service should reject your
+requests.</li>
+</ol>
+<br></br>
+</div><br></br><br></br><div style="margin-left: 40px;"></div></subsection></section></body></document>
\ No newline at end of file
diff --git a/trunk/xdocs/cert.xml b/trunk/xdocs/cert.xml
new file mode 100644
index 0000000..8e898ab
--- /dev/null
+++ b/trunk/xdocs/cert.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<document>
+<properties>
+<author email="gtr@ast.cam.ac.uk">Guy Rixon</author>
+<title>Including the sender's certificate in the signed message</title>
+</properties>
+
+<body>
+<section name="Including the sender's certificate in the signed message">
+<p>
+When messages are digitally signed, the recipient must have the sender's
+certificate chain in order to check the signature. Typically, the chain has
+two certificates: that of the sender and that of the sender's certificate
+authority (CA).
+</p>
+<p>
+There are two common ways of getting the certificates to the service.
+</p>
+<ol>
+<li>
+Install the CA's certificate in the service configuration. Send the caller's
+individual certificate with the signed message. This is called "direct reference",
+since the signature mark-up in the SOAP header refers directly to an included
+credential.
+</li>
+<li>
+Install both the CA certificate and the caller's individual certificate in the
+service configuration. Send the CA's name and the serial number of the caller's
+certificate in the SOAP message; have the service retrieve its copy of the certificate
+using these metadata. This is called the "issuer-serial" method.
+</li>
+</ol>
+<p>
+The issuer-serial method presumes that all trusted users of the service are known to the
+service and have pre-registered
+their certificate chains before using the service. The direct-reference method presumes
+that the service operator trusts all users with certificates issued by a trusted CA.
+</p>
+<p>
+To use the direct-reference method when using WSDoAllSender to sign the messages, the client must
+set a handler property as follows.
+</p>
+<pre>
+stub._setProperty(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
+</pre>
+<p>
+To use the issuer-serial method, the property should be set like this:
+</p>
+<pre>
+stub._setProperty(WSHandlerConstants.SIG_KEY_ID, "IssuerSerial");
+</pre>
+<p>
+If the property is not set, the default in WSS4J is to use the issuer-serial method.
+</p>
+</section>
+</body>
+
+</document> 
diff --git a/trunk/xdocs/index.xml b/trunk/xdocs/index.xml
new file mode 100644
index 0000000..4e79910
--- /dev/null
+++ b/trunk/xdocs/index.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<document>
+    <properties>
+        <title>WSS4J Documentation</title>
+    </properties>
+    <body>
+        <section name="Apache WSS4J"/>
+        <section name="">
+            <subsection name="Contents">
+                <ul>
+                    <li>
+                        <a href="#What_is_WSS4J">What is WSS4J?</a>
+                    </li>
+                    <li>
+                        <a href="#Where_can_I_download_WSS4J">Where can I download WSS4J?</a>
+                    </li>
+                    <li>
+                        <a href="#WS-Security_Features">WS-Security Features</a>
+                    </li>
+                    <li>
+                        WSS4J Use Cases
+                    </li>
+                    <ul>
+                        <li><a href="#WSS4J_API">WSS4J API</a></li>
+                        <li><a href="#WSS4J_on_Axis">WSS4J on Axis</a></li>
+                        <li><a href="#Rampart:_WS-Security_Implementation_module_for_Axis2">
+                        Rampart: WS-Security Implementation module for Axis2</a></li>
+                        <li><a href="#WSS4J_Configuration">WSS4J Configuration</a></li>
+                    </ul>
+                </ul>
+                <br/>
+            </subsection>
+        </section>
+        <section name="">
+            <subsection name="What is WSS4J?">
+                <p style="margin-left: 40px;"> 
+Apache WSS4J is an implementation of the
+OASIS Web Services Security (WS-Security) from <a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss">OASIS
+Web Services Security TC</a>. WSS4J is primarily a Java library that can be used to sign and verify SOAP Messages 
+with WS-Security information. WSS4J will use Apache Axis and Apache XML-Security projects and will be interoperable 
+with JAX-RPC based server/clients and .NET server/clients.
+<br/>
+                </p>
+                <p style="margin-left: 40px;">WSS4J implements<br/>
+                </p>
+                <ul style="margin-left: 40px;">
+                    <li>
+                        <a href="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0.pdf">OASIS
+Web Services Security: SOAP Message Security 1.0 Standard 200401, March
+2004</a>
+                    </li>
+                    <li>
+                        <a href="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf">Username
+Token profile V1.0</a>
+                    </li>
+                    <li>
+                        <a href="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0.pdf">X.509
+Token Profile V1.0</a>
+                    </li>
+                </ul>
+            </subsection>
+            <subsection name="Where can I download WSS4J">
+                <p style="margin-left: 40px;">You can download the latest version of WSS4J at the following URL:<br/>
+                    <a href="http://www.apache.org/dyn/closer.cgi/ws/wss4j/">http://www.apache.org/dyn/closer.cgi/ws/wss4j/</a>
+                </p>
+                <p style="margin-left: 40px;">The latest release of WSS4J is version 1.5.4.
+                </p>
+            </subsection>
+            <subsection name="WS-Security Features">
+                <p style="margin-left: 40px;">WSS4J can generate and process the
+following SOAP Bindings:<br/>
+                </p>
+                <ul>
+                    <ul>
+                        <li>XML Security<br/>
+                        </li>
+                        <ul>
+                            <li>XML Signature</li>
+                        </ul>
+                        <ul>
+                            <li>XML Encryption</li>
+                        </ul>
+                        <li>Tokens</li>
+                        <ul>
+                            <li>Username
+Tokens</li>
+                            <li>Timestamps</li>
+                        </ul>
+                        <ul>
+                            <li>SAML Tokens</li>
+                        </ul>
+                    </ul>
+                </ul>
+                <p style="margin-left: 40px;">WSS4J supports X.509 binary
+certificates and certificate paths.<br/>
+                    <br/>
+                </p>
+                <p style="margin-left: 40px;"/>
+            </subsection>
+            <subsection name="WSS4J API">
+                <p style="margin-left: 40px;">Please refer to the <a href="api.html">API
+Overview</a>
+for details.<br/>
+                    <br/>
+                </p>
+            </subsection>
+            <subsection name="WSS4J on Axis">
+                <p style="margin-left: 40px;">Please refer to the <a href="axis.html">Axis
+Deployment Tutorial</a> for a short tutorial and <a href="package.html">Axis Deployment Examples</a> for more details.<br/>
+                </p>
+                <br/>
+            </subsection>
+            <subsection name="Rampart: WS-Security Implementation module for Axis2">
+                <p style="margin-left: 40px;">Please refer to the 
+                <a href="http://ws.apache.org/axis2/modules/rampart/1_2/security-module.html">
+                Rampart configuration guide</a> for configuration information.<br/>
+                </p>
+                <br/>
+            </subsection>
+            <subsection name="WSS4J Configuration">
+                <p style="margin-left: 40px;"><a href="cert.html">Difference between issuer-serial (WSS4J default) and direct-reference modes</a> 
+                </p>
+                <br/>
+            </subsection>
+        </section>
+    </body>
+</document>
diff --git a/trunk/xdocs/package.xml b/trunk/xdocs/package.xml
new file mode 100644
index 0000000..565666f
--- /dev/null
+++ b/trunk/xdocs/package.xml
@@ -0,0 +1,648 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<document><properties><title>Axis Deployment Examples</title></properties><body><section><p>
+
+WSS4J Axis handlers process SOAP requests according to the OASIS Web Service 
+Security (WSS) specifications.
+</p><p></p><p>
+The WSS4J Axis handlers <code>WSDoAllSender</code> and <code>WSDoAllReceiver
+</code> control the creation and consumption of secure SOAP requests.
+The handlers work behind the scenes and are usually transparent to Web Service
+(WS) applications. The Axis deployment descriptor files (*.wsdd) may contain all
+necessary information to control the security processing.
+</p><p></p><p>
+A WS application may also set properties to control the handlers
+and provide default values. If the deployment descriptor sets the same 
+property (parameter) then the deployment descriptor overwrites the application
+defined property.  Thus, deployment settings overwrite application settings 
+to fulfill site specific requirements.
+
+</p></section><section name="Prerequisties"><p>
+The WS Security Axis handlers use the WSS4J classes (Web Service Security 
+for Java) to process the SOAP messages. WSS4J in turn uses the Apache XML Security 
+project to handle XML Security according to XML Signature and XML Encryption. 
+
+<ul>
+  <li><a href="http://ws.apache.org/wss4j/index.html">WSS4J</a></li>
+  <li><a href="http://xml.apache.org/security/index.html">XML Security</a></li>
+</ul>
+
+The WSS4J Axis handlers require Axis V1.2 because of some problems in previous
+Axis versions. WSS4J CVS contains the latest Axis libraries. 
+
+</p></section><section name="Related Documentation"><p>
+The OASIS WSS specifications define a number of features and it is possible 
+to combine them in several ways. The WSS4J Axis handlers already support 
+a large number of WSS features and their combinations. 
+<a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss">
+Here</a> are the WSS specifications.
+
+</p></section><section name="The basics - a simple example that uses"><p>
+This chapter gives an overview and some examples how to deploy 
+the WSS4J Axis handlers and how the parameters and their values control the
+handlers. For a better understanding of this chapter the reader shall 
+have a knowledge of the OASIS WSS specifications.
+</p><p></p><p>
+The {@link org.apache.ws.security.handler.WSHandlerConstants}, 
+{@link org.apache.ws.axis.security.WSDoAllSender}, and 
+{@link org.apache.ws.axis.security.WSDoAllReceiver}
+provide additional and detailed documentation.
+
+</p><subsection name="Axis deployment descriptor to insert a"><p>
+The following snippet shows a general layout how to deploy a WS Axis handler
+on the client (application) side.
+<source>
+ &lt;!-- define the service, use the WSDoAllSender security handler in request flow --&gt;
+ &lt;service name="Ping1"&gt;
+  &lt;requestFlow&gt;
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" &gt;
+    &lt;parameter name="action" value="UsernameToken"/&gt;
+    &lt;parameter name="user" value="werner"/&gt;
+    &lt;parameter name="passwordType" value="PasswordText" /&gt;
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback1"/&gt;
+   &lt;/handler&gt;
+  &lt;/requestFlow&gt;
+  &lt;/service&gt;
+</source>
+
+This is the standard way to deploy an Axis handler. Axis parses the deployment
+descriptor and provides the parameters and their value to the handler. Each
+service can have its own request and response flow definition, which provides
+a very flexible set-up of the security parameters.
+</p><p></p><p>
+The above setup inserts the most simple security structure into a SOAP request: 
+the simple <code>UsernameToken</code>. This token includes a username and the 
+according password. Both fields are sent in cleartext, thus it provides no 
+real security.
+</p><p></p><p>
+
+The parameters and their meanings are:
+<ul>
+<li><code>action</code> defines the security action. The value <code>
+    UsernameToken</code> directs the handler to insert this token into
+    the SOAP request.
+</li>
+<li><code>user</code> specifies the username to include in the token.
+</li>
+<li><code>passwordType</code> is a pecific parameter for the <code>
+    UsernameToken</code> action and defines the encoding of the passowrd.
+    <code>PasswordText</code> specifies to send the password in
+    plain text, <code>PasswordDigest</code> specifies to send the
+    password in digest mode (refer to WSS UsernameToken Profile)
+</li>
+<li><code>passwordCallbackClass</code> contains the name of a class that
+    implements a method to get the user's password. Please refer to the
+    detailed documentation in 
+    {@link org.apache.ws.security.handler.WSHandlerConstants#PW_CALLBACK_CLASS}.
+    </li>
+</ul>
+The WSS4J Axis security handler interprets the parameter values and controls
+the WSS4J modules to generate the following SOAP request:
+<source>
+&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
+  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
+  &lt;soapenv:Header&gt;
+    &lt;wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext" 
+      soapenv:mustUnderstand="true"&gt;
+      &lt;wsse:UsernameToken&gt;
+        &lt;wsse:Username&gt;werner&lt;/wsse:Username&gt;
+        &lt;wsse:Password Type="wsse:PasswordText"&gt;security&lt;/wsse:Password&gt;
+      &lt;/wsse:UsernameToken&gt;
+    &lt;/wsse:Security&gt;
+  &lt;/soapenv:Header&gt;
+  &lt;soapenv:Body&gt;
+    &lt;Ping xmlns="http://xmlsoap.org/Ping"&gt;
+      &lt;text&gt;Scenario 1 text&lt;/text&gt;
+      &lt;ticket xmlns:ns1="http://xmlsoap.org/Ping" 
+        xsi:type="ns1:ticketType"&gt;scenario1&lt;/ticket&gt;
+    &lt;/Ping&gt;
+  &lt;/soapenv:Body&gt;
+&lt;/soapenv:Envelope&gt;
+</source>
+This is a pretty print of the real SOAP message.
+
+</p></subsection><subsection name="The password callback class"><p>
+
+The deployment descriptor contains the user name that the handler inserts into
+the <code>UsernameToken</code> but not the password. In general it is not a
+good idea to store sensitive information like a password in cleartext. To
+get the password the WSS4J Axis handler uses a password callback
+technique similar to the JAAS mechansim. The parameter 
+<code>passwordCallbackClass</code> contains the classname of the callback
+class. This class must implement the
+{@link javax.security.auth.callback.CallbackHandler}
+interface. The WSS4J Axis handler gets this class,
+instantiates it, and calls the <code>handle</code> method when it
+needs a password. Refer also to the 
+{@link org.apache.ws.security.handler.WSHandlerConstants#PW_CALLBACK_CLASS
+ parameter} documentation.
+ </p><p></p><p>
+ The following code snippet shows a simple password callback class:
+ <source>
+package org.apache.ws.axis.oasis;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.ws.security.WSPasswordCallback;
+
+public class PWCallback implements CallbackHandler {
+
+  private static final byte[] key = {
+    (byte)0x31, (byte)0xfd, (byte)0xcb, (byte)0xda,
+    (byte)0xfb, (byte)0xcd, (byte)0x6b, (byte)0xa8,
+    (byte)0xe6, (byte)0x19, (byte)0xa7, (byte)0xbf,
+    (byte)0x51, (byte)0xf7, (byte)0xc7, (byte)0x3e,
+    (byte)0x80, (byte)0xae, (byte)0x98, (byte)0x51,
+    (byte)0xc8, (byte)0x51, (byte)0x34, (byte)0x04,
+  };
+	
+  public void handle(Callback[] callbacks)
+    throws IOException, UnsupportedCallbackException {
+    for (int i = 0; i &lt; callbacks.length; i++) {
+      if (callbacks[i] instanceof WSPasswordCallback) {
+        WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+        /*
+         * here call a function/method to lookup the password for
+         * the given identifier (e.g. a user name or keystore alias)
+         * e.g.: pc.setPassword(passStore.getPassword(pc.getIdentfifier))
+         * for testing we supply a fixed name/fixed key here.
+         */
+        if (pc.getUsage() == WSPasswordCallback.KEY_NAME) {
+          pc.setKey(key);
+        }
+        else {
+          pc.setPassword("security");
+        }
+      } else {
+        throw new UnsupportedCallbackException(
+          callbacks[i], "Unrecognized Callback");
+      }
+    }
+  }
+}
+</source>
+The Java {@link javax.security.auth.callback.CallbackHandler callback} handler
+documentation provides a detailed description of the interface and exceptions.
+</p><p></p><p>
+The WSS4J library uses a specific class to get the required password or key
+informations. The <code>WSSPasswordCallback</code> class implements the
+{@link javax.security.auth.callback.Callback} interface according to the
+JAAS. Depending on it usage this class either carries the required password
+as a Java <code>String </code> or it carries the required key information 
+as a Java <code>byte[]</code> array. Refer to
+{@link org.apache.ws.security.WSPasswordCallback} that contains a
+detailed description of the usage codes.
+</p><p></p><p>
+The WSS4J Axis handler or the WSS4J modules set the usage code before
+they call <code>handle</code> method. 
+
+</p></subsection><subsection name="Application sets parameters to insert in"><p>
+
+Sometimes it is not feasable or not possible to determine parameters
+and their values during deployment. In this case the application can
+set paramters during runtime. The WSS4J Axis handlers use the Axis
+<code>setProperty</code> method to support this feature.
+</p><p></p><p>
+The following code snippet shows an example how to use the dynamic setting
+of parameters and their values:
+<source>
+   ...
+ Service service = new Service();
+ Call call = (Call) service.createCall();
+   ...  
+ call.setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
+ call.setProperty(WSHandlerConstants.USER, "werner");
+   ...
+</source>
+Use this way if your application dynamically creates a <code>call</code>
+object. If your application uses stubs generated by Axis' <code>WSDL2Java
+</code> tool, the application uses the following functions:
+<source>
+    ...
+ PingServiceLocator service = new PingServiceLocator();
+    ...
+ PingPort port = (PingPort) service.getPing1();
+ port._setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
+ port._setProperty(WSHandlerConstants.USER, "werner");
+    ...
+</source>
+Please note that <code>_setProperty</code> is a Axis specific call.
+
+</p></subsection><subsection name="The password callback object reference"><p>
+
+In addition to the <a href="#pwCallBackClass">password callback class</a>
+an application may set a password callback object using the <code>
+  setProperty()</code> methods. Only applications (and Axis handlers that
+  preceed the WSS4J Axis handlers in a handler chain) can use this feature.
+  </p><p></p><p>
+  For example:
+  <source>
+public class Scenario1 implements CallbackHandler {
+
+  public static void main(String args[]) {
+    ...
+    PingServiceLocator service = new PingServiceLocator();
+    ...
+    PingPort port = (PingPort) service.getPing1();
+    ((org.apache.axis.client.Stub)port)._setProperty(UsernameToken.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
+    ((org.apache.axis.client.Stub)port._setProperty(WSHandlerConstants.USER, "werner");
+    ((org.apache.axis.client.Stub)port._setProperty(WSHandlerConstants.PW_CALLBACK_REF, this);
+    ...
+  }
+
+  public void handle(Callback[] callbacks) {
+    ...
+  }
+}
+</source>
+
+</p></subsection><subsection name="Deployment of the WSS4J Axis  handler"><p>
+
+Similar to the deployment descriptor of the sending handler <code>WSDoAllSender
+</code> a deployment descriptor for the receiving handler exists. For the above
+example the deployment descriptor look like:
+<source>
+  &lt;requestFlow&gt;
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllReceiver"&gt;
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/&gt;
+    &lt;parameter name="action" value="UsernameToken"/&gt;
+   &lt;/handler&gt;
+  &lt;/requestFlow&gt;
+</source>
+The receiving WSS4J Axis handler checks if the SOAP request matches the defined
+actions.
+
+</p></subsection></section><section name="Combining security actions"><p>
+
+Often it is necessary to combine or concatenate several security actions, for 
+example to encrypt parts of a message and sign some other parts. The WSS4J 
+Axis handlers provide easy and simple methods to combine or concatenate
+security actions. 
+</p><p></p><p>
+This chapter describes simple combinations of actions.
+
+</p><subsection name="Combine  and"><p>
+
+The WS Interoperability specifications define this use case: 
+<ul>
+  <li>Insert a <code>UsernameToken</code>, use <code>PasswordText</code>
+    to set the password. In addition add a timestamp and a nonce into
+    the <code>UsernameToken</code></li>
+  <li>Encrypt the <code>UsernameToken</code> to protect the information.
+    </li>
+</ul>
+
+The Axis deplyment descriptor for this use case:
+<source>
+  &lt;requestFlow&gt;
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" &gt;
+    &lt;parameter name="action" value="UsernameToken Encrypt"/&gt;
+    &lt;parameter name="user" value="werner"/&gt;
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/&gt;
+    &lt;parameter name="passwordType" value="PasswordText" /&gt;
+    &lt;parameter name="addUTElement" value="Nonce Created" /&gt;
+    &lt;parameter name="encryptionPropFile" value="crypto.properties" /&gt;
+    &lt;parameter name="encryptionKeyIdentifier" value="X509KeyIdentifier" /&gt;
+    &lt;parameter name="encryptionUser" 
+      value="16c73ab6-b892-458f-abf5-2f875f74882e" /&gt;
+    &lt;parameter name="encryptionParts" 
+      value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken" /&gt;  
+   &lt;/handler&gt;
+  &lt;/requestFlow&gt;  
+</source>
+
+This descriptor contains some new parameters to control the <code>UsernameToken
+</code> element and its encryption. The new parameters and their meaning are:
+<ul>
+  <li><code>addUTElement</code> - controls if the handler shall insert elements
+    into the <code>UsernameToken</code>. The value is a blank separated list of
+    element names to include. Only <code>Nonce</code> and <code>Created</code> are
+    supported.</li>
+  <li><code>encryptionPropFile</code> - the name of a crypto property file. This
+    file contains parameters and property that control the encryption. Please refer
+    to the
+    {@link org.apache.ws.security.handler.WSHandlerConstants#ENC_PROP_FILE 
+    detailed} description of the cyrpto property file.</li>
+  <li><code>encryptionKeyIdentifier</code> - specifies the format in which the 
+    handler inserts the encryption key into the SOAP request. Please refer
+    to the 
+    {@link org.apache.ws.security.handler.WSHandlerConstants#ENC_KEY_ID 
+    detailed} description.</li>
+  <li><code>encryptionUser</code> - the name or identifier of the user who owns
+    the public key to encrypt the data. Usually this is the name or alias name
+    of the owner's certificate in a keystore.</li>
+  <li><code>encryptionParts</code> - controls which part or parts the handler
+    of the SOAP shall encrypt. If this parameter is not defined, WSS4J encrypts
+    the whole SOAP Body in <code>Content</code> mode. The value of the
+    parameter in this example specifies to encrypt the element <code>
+    UsernameToken</code>, contained in the namespace
+    <code>http://schemas.xmlsoap.org/ws/2002/07/secext</code>. The encryption
+    module uses the <code>Element</code> mode to encrypt the element data.
+    Please refer to the
+    {@link org.apache.ws.security.handler.WSHandlerConstants#ENCRYPTION_PARTS 
+    detailed} description.
+    </li>
+</ul>
+The matching receiver deployment descriptor:
+<source>
+  &lt;requestFlow&gt;
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllReceiver"&gt;
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/&gt;
+    &lt;parameter name="action" value="UsernameToken Encrypt"/&gt;
+    &lt;parameter name="decryptionPropFile" value="crypto.properties" /&gt;
+   &lt;/handler&gt;
+  &lt;/requestFlow&gt;
+</source>
+The only new parameter here is the <code>decryptionPropFile</code>. This
+parameter defines the crypto property file at the receiver side. The value
+  of the <code>action</code> parameter matches the according value at the
+  sender side. The WSS4J Axis receiver checks if the SOAP request contains
+  the required security data.
+
+</p></subsection><subsection name="Combine Signature and Encryption"><p>
+
+This is a very common usage of Web Service security. The WSS4J Axis handler
+provides flexible parameter settings that support several ways to use
+the Signature/Encryption combination.
+</p><p></p><p>
+A WSS4J Axis deployment descriptor for a simple Singature/Encryption of
+SOAP requests:
+<source>
+&lt;requestFlow&gt;
+  &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" &gt;
+    &lt;parameter name="user" value="16c73ab6-b892-458f-abf5-2f875f74882e"/&gt;
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/&gt;
+    &lt;parameter name="action" value="Signature Encrypt"/&gt;
+    &lt;parameter name="signaturePropFile" value="crypto.properties" /&gt;
+  &lt;/handler&gt;
+&lt;/requestFlow&gt;
+</source>
+This simple deployment descriptor signs and encrypts the SOAP Body part.
+The only new parameter, <code>signaturePropFile</code>, specifies the
+name of the signature crypto property file to use. Because no 
+<code>encryptionPropFile</code> is declared the handler also uses the signature
+property file to get the encryption certificate. The same holds true for
+the username. The password callback class must return a password
+to get the user's private key (the keystore is defined in the crypto
+property file) that WSS4J uses to generate the signature. The encryption
+method uses the user's public key to encrypt the dynamically generated
+session key.
+</p><p></p><p>
+The <code>action</code> parameter defines <code>Signature Encryption</code>.
+Thus the handler first signs, then the encrypts the data.
+Because the deployment descriptor does not contain specific encryption or 
+signature part parameters, WSS4J defaults to the data of the SOAP Body element.
+</p><p></p><p>
+Also all other parameters use their default setting, such as the format of the
+key identifiers, encryption modifiers, and so on. Please refer to the
+{@link org.apache.ws.security.handler.WSHandlerConstants detailed}
+documentation of the parameters.
+</p><p></p><p>
+If the WSS4J Axis handler shall perform encryption only, then the
+deployment descriptor must contain the encryption specific parameters. Only
+if sign <b>and</b> encryption is required the encryption method falls back to
+the signature parameters if the encryption specific parameters are not set.
+</p><p></p><p>
+The matching receiver deployment descriptor is also very simple:
+<source>
+&lt;requestFlow&gt;
+  &lt;handler type="java:org.apache.ws.axis.security.WSDoAllReceiver"&gt;
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/&gt;
+    &lt;parameter name="action" value="Signature Encrypt"/&gt;
+    &lt;parameter name="signaturePropFile" value="crypto.properties" /&gt;
+  &lt;/handler&gt;
+ &lt;/requestFlow&gt;	
+</source>
+To reverse the actions, just reverse the action specifiers. The WSS4J
+handler encrypts the SOAP Body first, then signs the encrypted data.
+
+</p></subsection></section><section name="Signing and encrypting multiple XML elements"><p>
+
+Sometimes it is necessary to sign and/or encrypt several parts of a SOAP
+message. The deployment parameters <code>signatureParts</code> and 
+<code>encryptionParts</code> control which SOAP elements to sign or
+to encrypt. Please refer to the
+{@link org.apache.ws.security.handler.WSHandlerConstants#ENCRYPTION_PARTS 
+detailed} description of these parameters.
+</p><p></p><p>
+WSS4J signs or encrypts all declared parts using the same keys, that is 
+the signature or encryption data structures directly reference the 
+specified parts as described in the WSS specifications. The receiver
+automatically detects these references and verfies and decrypts the
+data parts. No special settings in the depolyment descriptor is necessary.
+
+</p></section><section name="Chaining of WSS4J Axis handlers"><p>
+
+This is a very powerful feature that supports even more flexible signature and
+encryption processing such as signatures with multiple keys (overlapping
+signatures), multiple encryption algorithms, or different SOAP actor (role)
+defintions of the security headers.
+
+</p><subsection name="Deployment at the client"><p>
+A deployment descriptor to chain handlers:
+<source>
+  &lt;requestFlow&gt;
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" &gt;
+    &lt;parameter name="action" value="Signature NoSerialization"/&gt;
+    &lt;parameter name="user" value="firstUser"/&gt;
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/&gt;
+    &lt;parameter name="signaturePropFile" value="crypto.properties" /&gt;
+    &lt;parameter name="signatureParts" value="{}{http://xmlsoap.org/Ping}ticket" /&gt;    
+   &lt;/handler&gt;
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllSender" &gt;
+    &lt;parameter name="action" value="Signature"/&gt;
+    &lt;parameter name="user" value="anotherUser"/&gt;
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/&gt;
+    &lt;parameter name="signaturePropFile" value="crypto.properties" /&gt;
+   &lt;/handler&gt;  
+  &lt;/requestFlow&gt;
+</source>
+Note the action specifier <code>NoSerialization</code> first handler. 
+In a handler chain of WSS4J handlers every
+but the last handler <i>must</i> have this action specifier. This specifier
+surpresses the very last step of the handler's security processing: the 
+serialization of the processed SOAP request in a XML string (document) that 
+Axis sends to the reveiver. Only the last handler must perform this 
+serialization.
+</p><p></p><p>
+Every handler specification can have its own set of parameters that define
+the individual values for this handler instance. Thus the deployment
+descriptor can define different crypto property files, different usernames,
+and so on. In the example the first handler signs the <code>ticket</code>
+element and the second handler the SOAP Body (default).
+</p><p></p><p>
+Parameters set by the application with <code>setProperty</code> are valid for 
+<b>all</b> handler instances in the handler
+chain (<code>setProperty</code> is defined on the SOAP request (call) level).
+As already decribed, deployment settings overrule application settings. Thus it
+is possible to combine various parameter specifications. A special case is the
+definition of the username. If an application sets the username and one
+handler instance in the chain does not have a <code>user</code> parameter 
+in its deployment part, then this one handler instance uses the username set
+bey the application. After the handler copied the username from the username
+property, the handler sets the property's content to <code>null</code>. 
+Handlers that follow in the chain cannot use this username anymore and 
+must have a user (or encryption user) parameter in their deployment part.
+
+</p></subsection><subsection name="Deployment at the server"><p>
+
+Note: Handler chaining at the receiver side is not yet fully tested.
+</p><p></p><p>
+Handlers at the receiver can only determine different security headers if their
+SOAP actors are different. The WSS4J handler processes each security structure
+inside one security header. Because the security structures contain most
+information to verify or decrypt the SOAP request this constraint is
+not too much of an issue.
+</p><p></p><p>
+Only the password call back class and the <code>Crypto</code> implementation
+(as defined in the crypto property file) must be able to handle all possible 
+certificates, users, passwords, and keys that a security header may contain.
+The following deployment descriptor of a receiver shows this.
+<source>
+  &lt;requestFlow&gt;
+   &lt;handler type="java:org.apache.ws.axis.security.WSDoAllReceiver"&gt;
+    &lt;parameter name="passwordCallbackClass" 
+      value="org.apache.ws.axis.oasis.PWCallback"/&gt;
+    &lt;parameter name="action" value="Signature Signature"/&gt;
+    &lt;parameter name="signaturePropFile" value="crypto.properties" /&gt;
+   &lt;/handler&gt;
+  &lt;/requestFlow&gt;
+</source>
+The client uses two handlers in a chain, each signing a part of the SOAP 
+request but with different certificates. Because the handlers do not 
+specifiy a SOAP actor WSS4J puts both signatures in the security header
+of the default actor. 
+To match the security actions the deployment descriptor of the receiver needs 
+to contain the action declaration <code>Signature Signature</code>. This 
+instructs the WSS4J handler to accept and verify two distinct signatures 
+contained in one security header. Because the signatures use different 
+certificates the <code>Crypto</code> implementation must be able to handle
+these certificates.
+</p><p></p><p>
+Similar requirements are true for the password callback implementation if the
+sender uses handler chaining and uses different encryption parameters in the
+same security header.
+</p><p></p><p>
+If it is necessary to have different parameters for the distinct signature or
+decryption data then these should be put in different security headers. The 
+easiest way to do this is to define different <code>actor</code> parameters
+for each handler in a WSS4J handler chain.
+ 
+</p></subsection></section><section name="Reporting Security results to services/applications"><p>
+The WSS4J <code>WSSecurityEngine</code> processes the security elements inside
+a security header. If something goes wrong, for example a signature 
+verfication fails, then the engine throws a fault. If the security engine
+could perform all operations sucessfully it returns a data structure
+that contains the results of the performed security actions. This data
+structure holds information about the performed action, the usernames or
+identifier in case the security engine performed signature or username token
+processing. Please refer to the
+{@link org.apache.ws.security.WSSecurityEngineResult result} structure.
+</p><p></p><p>
+The <code>WSDoAllReceiver</code> WSS4J handler takes this structure and
+checks if all required actions were performed. If this check fails, the
+WSS4J handler aborts the SOAP request and throws an Axis SOAP fault.
+Otherwise it creates its own data structure 
+{@link org.apache.ws.axis.security.WSDoAllReceiverResult}, copies the
+security results in this structure, and adds the actor name of the
+security header. The it stores this new data structure in a vector and stores
+this vector in a specific 
+{@link org.apache.ws.security.handler.WSHandlerConstants#RECV_RESULTS property} 
+of the current message context. If WSS4J handlers are
+chained, then every handler in the chain adds its result to the vector. The
+vector contains the results in handler-chain order.
+</p><p></p><p>
+This code snippet shows how a Axis service can access the security result
+data:
+<source>
+    public void ping(javax.xml.rpc.holders.StringHolder text,
+        org.apache.ws.axis.oasis.ping.TicketType ticket)
+        throws java.rmi.RemoteException {
+
+        text.value = "Echo " + text.value.trim();
+		
+        // get the message context first
+        MessageContext msgContext = MessageContext.getCurrentContext();
+        Message reqMsg = msgContext.getRequestMessage();
+
+        Vector results = null;
+        // get the result Vector from the property
+        if ((results =
+            (Vector) msgContext.getProperty(WSHandlerConstants.RECV_RESULTS))
+             == null) {
+            System.out.println("No security results!!");
+        }
+        System.out.println("Number of results: " + results.size());
+        for (int i = 0; i &lt; results.size(); i++) {
+            WSHandlerResult hResult = (WSHandlerResult)results.get(i);
+            String actor = hResult.getActor();
+            Vector hResults = hResult.getResults();
+            for (int j = 0; j &lt; hResults.size(); j++) {
+              	WSSecurityEngineResult eResult = (WSSecurityEngineResult) hResults.get(j);
+                // Note: an encryption action does not have an associated principal
+    	        // only Signature and UsernameToken actions return a principal
+                if (eResult.getAction() != WSConstants.ENCR) {
+                    System.out.println(eResult.getPrincipal().getName());
+                }
+            }
+        }
+    }
+</source>
+The principal structure is either a 
+{@link org.apache.ws.security.WSUsernameTokenPrincipal UsernameToken} principal 
+or a {@link java.security.Principal X509Principal}. The 
+princpals contain the names plus other information of the verified username
+token or signature certificate.
+ 
+</p></section><section name="Some hints"><subsection name="Client"><p>
+At the client side, the WSS4J Axis handler, as all other parts of Axis, run
+in the context of the calling application. Depending on the application,
+the callback classes may perform complex operations, even do some user 
+interaction, to get the password or to access some database to get 
+certificates or keys. There are no timeouts defined at the client side 
+before the SOAP request is put on the wire.
+
+</p></subsection><subsection name="Server"><p>
+On the server side the WSS4J handler run in the same context as the other part
+of the server, usually some servlet container, such as Tomcat. Also the server
+must be able to handle many requests in a short time. Thus the password 
+callback as well as the <code>Crypto</code> implementation shall be
+as fast as possible. In general, no user interaction is possible at the
+server side to gather passwords. Also at this point of the SOAP request
+processing there are active timeouts, even if they are fairly long.
+
+</p></subsection><subsection name="Bi-directional SOAP Security"><p>
+WSS4J fully supports bi-directional SOAP security. To enable bi-directional
+support just put <code>WSDoAllSender</code> on the 
+<code>responseFlow</code> at the server and <code>WSDoAllReceiver</code>
+at the response flow of the client thus reversing the roles. Similar to
+the above hints, the server side part (now <code>WSDoAllSender</code>)
+runs in the server context and <code>WSDoAllReceiver</code>
+runs in the application (client) context. There are no Axis timeout
+constraints on the client side after Axis received the response 
+and handed it over to the WSS4J handler.
+
+</p></subsection><subsection name="Handler chaining"><p>
+Usually WSS4J handlers are chained without any other handler between them in
+the chain. It is, however, possible to do so. In this case the intermediate
+handler <b>must not</b> modify the SOAP Envelope that is contained in the
+Axis message. This could (most probably will) invalidate or destroy any 
+security actions done sofar. Such an intermediate handler may set some 
+properties that may influence the processing of the following WSS4J handler, 
+such as setting a new username, password callback class, and so on.
+
+<!-- Put @see and @since tags down here. -->
+@since WSS4J 1.0</p></subsection></section></body></document>
\ No newline at end of file
diff --git a/trunk/xdocs/stylesheets/maven.css b/trunk/xdocs/stylesheets/maven.css
new file mode 100644
index 0000000..6addb4c
--- /dev/null
+++ b/trunk/xdocs/stylesheets/maven.css
@@ -0,0 +1,114 @@
+body {
+ background: #fff;
+ color: #000;
+ }
+
+.app h3 {
+ color: #fff;
+ background-color: #036;
+ }
+
+.app h4 {
+ color: #fff;
+ background-color: #888;
+ }
+
+.a td { 
+ background: #ddd;
+ color: #000;
+ }
+
+.b td { 
+ background: #efefef;
+ color: #000;
+ }
+
+.app th {
+ background-color: #bbb;
+ color: #fff;
+ }
+
+div#banner {
+ border-top: 1px solid #369;
+ border-bottom: 1px solid #003;
+ }
+
+#banner, #banner td { 
+ background: #036;
+ color: #fff;
+ }
+
+#leftcol {
+ background: #eee;
+ color: #000;
+ border-right: 1px solid #aaa;
+ border-bottom: 1px solid #aaa;
+ border-top: 1px solid #fff;
+}
+
+#navcolumn {
+ background: #eee;
+ color: #000;
+ border-right: none;
+ border-bottom: none;
+ border-top: none;
+ }
+
+#breadcrumbs {
+ background-color: #ddd;
+ color: #000;
+ border-top: 1px solid #fff;
+ border-bottom: 1px solid #aaa;
+ }
+
+#source {
+ background-color: #fff;
+ color: #000;
+ border-right: 1px solid #888; 
+ border-left: 1px solid #888; 
+ border-top: 1px solid #888; 
+ border-bottom: 1px solid #888; 
+ margin-right: 7px;
+ margin-left: 7px;
+ margin-top: 1em;
+ }
+
+#source pre {
+ margin-right: 7px;
+ margin-left: 7px;
+ }
+
+a[name]:hover, #leftcol a[name]:hover {
+ color: inherit !important;
+ }
+
+a:link, #breadcrumbs a:visited, #navcolumn a:visited, .app a:visited, .tasknav a:visited {
+ color: blue;
+ }
+
+a:active, a:hover, #leftcol a:active, #leftcol a:hover {
+ color: #f30 !important;
+ }
+
+a:link.selfref, a:visited.selfref {
+ color: #555 !important;
+ }
+
+h3, h4 {
+ margin-top: 1em;
+ margin-bottom: 0;
+ }
+
+img.handle {
+ border: 0;
+ padding-right: 2px;
+}
+
+#navcolumn div div  {
+ background-image: none;
+ background-repeat: no-repeat;
+}
+
+#navcolumn div div {
+  padding-left: 10px;
+}