From 7a13d9d0aa87ca5de9acacc060a1a23130c96232 Mon Sep 17 00:00:00 2001
From: ctissot <ctissot@localhost>
Date: Thu, 20 Dec 2007 09:55:23 +0000
Subject: [PATCH] I use this bug id (138) as an umbrella for a list of  bugfixes/improvements for the DSML gateway.

---
 opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLAbandonOperation.java |   11 
 opendj-sdk/opends/build.xml                                                   |    5 
 opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLDeleteOperation.java  |    7 
 opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java  |  460 +++++++++++++++++++------
 opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java          |  587 +++++++++++++++++++++-----------
 5 files changed, 755 insertions(+), 315 deletions(-)

diff --git a/opendj-sdk/opends/build.xml b/opendj-sdk/opends/build.xml
index 5fad80c..076e0f3 100644
--- a/opendj-sdk/opends/build.xml
+++ b/opendj-sdk/opends/build.xml
@@ -1007,6 +1007,11 @@
       </classpath>
     </javac>
 
+     <mkdir dir="${dsml.classes.dir}/resources" />
+     <copy file="${dsml.dir}/schema/DSMLv2.xsd"
+           tofile="${dsml.classes.dir}/resources/DSMLv2.xsd"
+           overwrite="true"/>
+
     <war destfile="${classes.dir}/${SHORT_NAME}-${VERSION_NUMBER_STRING}-DSML.war"
          webxml="${dsml.dir}/webapp/web.xml">
       <fileset file="${dsml.dir}/webapp/server.properties" />
diff --git a/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLAbandonOperation.java b/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLAbandonOperation.java
index 6f218de..260d5d5 100644
--- a/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLAbandonOperation.java
+++ b/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLAbandonOperation.java
@@ -27,11 +27,14 @@
 package org.opends.dsml.protocol;
 
 import java.io.IOException;
+import org.opends.messages.Message;
 
 import org.opends.server.protocols.ldap.AbandonRequestProtocolOp;
 import org.opends.server.protocols.ldap.LDAPMessage;
+import org.opends.server.protocols.ldap.LDAPResultCode;
 import org.opends.server.protocols.ldap.ProtocolOp;
 import org.opends.server.tools.LDAPConnection;
+import org.opends.server.types.LDAPException;
 
 
 
@@ -66,13 +69,10 @@
    */
   public LDAPResult doOperation(ObjectFactory objFactory,
         AbandonRequest abandonRequest)
-    throws IOException
+    throws LDAPException, IOException
   {
     LDAPResult abandonResponse = objFactory.createLDAPResult();
 
-    // Set the id for the response.
-    abandonResponse.setRequestID(abandonRequest.getRequestID());
-
     String abandonIdStr = abandonRequest.getAbandonID();
     int abandonId = 0;
     try
@@ -80,7 +80,8 @@
       abandonId = Integer.parseInt(abandonIdStr);
     } catch (NumberFormatException nfe)
     {
-      throw new IOException(nfe.getMessage());
+      throw new LDAPException(LDAPResultCode.UNWILLING_TO_PERFORM,
+                              Message.raw(nfe.getMessage()));
     }
 
     // Create and send an LDAP request to the server.
diff --git a/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLDeleteOperation.java b/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLDeleteOperation.java
index abab00b..7bade62 100644
--- a/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLDeleteOperation.java
+++ b/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLDeleteOperation.java
@@ -36,6 +36,7 @@
 import org.opends.server.protocols.ldap.LDAPMessage;
 import org.opends.server.protocols.ldap.ProtocolOp;
 import org.opends.server.tools.LDAPConnection;
+import org.opends.server.types.DN;
 import org.opends.server.types.LDAPException;
 
 
@@ -107,6 +108,12 @@
     code.setCode(resultCode);
     delResponse.setResultCode(code);
 
+    // set the match DN
+    DN dn = delOp.getMatchedDN();
+    if ( dn != null ) {
+      delResponse.setMatchedDN(dn.toString());
+    }
+
     return delResponse;
   }
 
diff --git a/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java b/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java
index 950db87..ed9df0c 100644
--- a/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java
+++ b/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java
@@ -34,23 +34,22 @@
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
-
-import org.opends.server.protocols.asn1.ASN1Element;
+import javax.xml.bind.JAXBElement;
 import org.opends.server.protocols.asn1.ASN1Exception;
 import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.protocols.asn1.ASN1Sequence;
 import org.opends.server.protocols.ldap.LDAPAttribute;
 import org.opends.server.protocols.ldap.LDAPConstants;
 import org.opends.server.protocols.ldap.LDAPFilter;
 import org.opends.server.protocols.ldap.LDAPMessage;
-import org.opends.server.protocols.ldap.ProtocolOp;
 import org.opends.server.protocols.ldap.SearchRequestProtocolOp;
 import org.opends.server.protocols.ldap.SearchResultEntryProtocolOp;
 import org.opends.server.protocols.ldap.SearchResultReferenceProtocolOp;
 import org.opends.server.protocols.ldap.SearchResultDoneProtocolOp;
 import org.opends.server.tools.LDAPConnection;
+import org.opends.server.types.ByteString;
 import org.opends.server.types.DereferencePolicy;
 import org.opends.server.types.LDAPException;
+import org.opends.server.types.RawFilter;
 import org.opends.server.types.SearchScope;
 
 
@@ -74,6 +73,283 @@
     this.connection = connection;
   }
 
+  /**
+   * Returns a new AND search filter with the provided filter components.
+   * 
+   * @param filterSet The filter components for this filter
+   * 
+   * @return a new AND search filter with the provided filter components.
+   * 
+   * @throws LDAPException an LDAPException is thrown if the creation of a
+   *                       filter component fails.
+   */
+  private static LDAPFilter createANDFilter(FilterSet filterSet)
+          throws LDAPException {
+    List<JAXBElement<?>> list = filterSet.getFilterGroup();
+    ArrayList<RawFilter> filters = new ArrayList<RawFilter>(list.size());
+
+    for(JAXBElement<?> filter : list) {
+      filters.add(createFilter(filter));
+    }
+    return LDAPFilter.createANDFilter(filters);
+  }
+
+  /**
+   * Returns a new Approximate search filter with the provided information.
+   * 
+   * @param ava the attribute value assertion for this approximate filter.
+   * 
+   * @return a new Approximate search filter with the provided information.
+   */
+  private static LDAPFilter createApproximateFilter(AttributeValueAssertion ava)
+  {
+    return LDAPFilter.createApproximateFilter(ava.getName(),
+                                           new ASN1OctetString(ava.getValue()));
+  }
+
+  /**
+   * Returns a new Equality search filter with the provided information.
+   * 
+   * @param ava the attribute value assertion for this Equality filter.
+   * 
+   * @return a new Equality search filter with the provided information.
+   */
+  private static LDAPFilter createEqualityFilter(AttributeValueAssertion ava) {
+    return LDAPFilter.createEqualityFilter(ava.getName(),
+                                          new ASN1OctetString(ava.getValue()));
+  }
+
+  /**
+   * Returns a new Extensible search filter with the provided information.
+   * 
+   * @param mra the matching rule assertion for this Extensible filter.
+   * 
+   * @return a new Extensible search filter with the provided information.
+   */
+  private static LDAPFilter createExtensibleFilter(MatchingRuleAssertion mra) {
+    return LDAPFilter.createExtensibleFilter(mra.getMatchingRule(),
+                                        mra.getName(),
+                                        new ASN1OctetString(mra.getValue()),
+                                        mra.isDnAttributes());
+  }
+
+  /**
+   * Returns a new GreaterOrEqual search filter with the provided information.
+   * 
+   * @param ava the attribute value assertion for this GreaterOrEqual filter.
+   * 
+   * @return a new GreaterOrEqual search filter with the provided information.
+   */
+  private static LDAPFilter createGreaterOrEqualFilter(
+                              AttributeValueAssertion ava) {
+    return LDAPFilter.createGreaterOrEqualFilter(ava.getName(),
+                                          new ASN1OctetString(ava.getValue()));
+  }
+
+  /**
+   * Returns a new LessOrEqual search filter with the provided information.
+   * 
+   * @param ava the attribute value assertion for this LessOrEqual filter.
+   * 
+   * @return a new LessOrEqual search filter with the provided information.
+   */
+  private static LDAPFilter createLessOrEqualFilter(
+                              AttributeValueAssertion ava) {
+    return LDAPFilter.createLessOrEqualFilter(ava.getName(),
+                                          new ASN1OctetString(ava.getValue()));
+  }
+
+  /**
+   * Returns a new NOT search filter with the provided information.
+   * 
+   * @param filter the filter for this NOT filter.
+   * 
+   * @return a new NOT search filter with the provided information.
+   * 
+   * @throws LDAPException an LDAPException is thrown if the creation of the
+   *                       provided filter fails.
+   */
+  private static LDAPFilter createNOTFilter(Filter filter)
+          throws LDAPException {
+    return LDAPFilter.createNOTFilter(createFilter(filter));
+  }
+
+  /**
+   * Returns a new OR search filter with the provided filter components.
+   * 
+   * @param filterSet The filter components for this filter
+   * 
+   * @return a new OR search filter with the provided filter components.
+   * 
+   * @throws LDAPException an LDAPException is thrown if the creation of a
+   *                       filter component fails.
+   */
+  private static LDAPFilter createORFilter(FilterSet filterSet)
+          throws LDAPException {
+    List<JAXBElement<?>> list = filterSet.getFilterGroup();
+    ArrayList<RawFilter> filters = new ArrayList<RawFilter>(list.size());
+
+    for(JAXBElement<?> filter : list) {
+      filters.add(createFilter(filter));
+    }
+    return LDAPFilter.createORFilter(filters);
+  }
+
+  /**
+   * Returns a new Present search filter with the provided information.
+   * 
+   * @param ad the attribute description for this Present filter.
+   * 
+   * @returna new Present search filter with the provided information.
+   * 
+   * @throws LDAPException an LDAPException is thrown if the ASN.1 element 
+   *                       provided by the attribute description cannot be
+   *                       decoded as a raw search filter.
+   */
+  private static LDAPFilter createPresentFilter(AttributeDescription ad)
+          throws LDAPException {
+    return LDAPFilter.decode(
+             new StringBuilder(ad.getName()).append("=*").toString());
+  }
+
+  /**
+   * Returns a new Substring search filter with the provided information.
+   * 
+   * @param sf the substring filter for this Substring filter.
+   * 
+   * @return a new Substring search filter with the provided information.
+   */
+  private static LDAPFilter createSubstringFilter(SubstringFilter sf) {
+    List<String> anys = sf.getAny();
+    ArrayList<ByteString> subAnyElements = 
+                                         new ArrayList<ByteString>(anys.size());
+
+    for(String s : anys) {
+      subAnyElements.add(new ASN1OctetString(s));
+    }
+    return LDAPFilter.createSubstringFilter(sf.getName(),
+                                        new ASN1OctetString(sf.getInitial()),
+                                        subAnyElements,
+                                        new ASN1OctetString(sf.getFinal()));
+  }
+
+  /**
+   * Returns a new LDAPFilter according to the tag name of the provided element 
+   * that can be "and", "or", "not", "equalityMatch", "substrings",
+   * "greaterOrEqual", "lessOrEqual", "present", "approxMatch",
+   * "extensibleMatch".
+   * 
+   * @param xmlElement a JAXBElement that contains the name of the filter to
+   *                   create and the associated argument.
+   * 
+   * @return a new LDAPFilter according to the tag name of the provided element.
+   * 
+   * @throws LDAPException an LDAPException is thrown if the creation of the
+   *                       targeted filter fails.
+   */
+  private static LDAPFilter createFilter(JAXBElement<?> xmlElement)
+          throws LDAPException {
+    LDAPFilter result = null;
+
+    String filterName = xmlElement.getName().getLocalPart();
+
+    if ( "and".equals(filterName) ) {
+      // <xsd:element name="and" type="FilterSet"/>
+      result = createANDFilter((FilterSet)xmlElement.getValue());
+    }
+    else if ( "or".equals(filterName) ) {
+      // <xsd:element name="or" type="FilterSet"/>
+      result = createORFilter((FilterSet)xmlElement.getValue());
+    }
+    else if ( "not".equals(filterName) ) {
+      // <xsd:element name="not" type="Filter"/>
+      result = createNOTFilter((Filter)xmlElement.getValue());
+    }
+    else if ( "equalityMatch".equals(filterName) ) {
+      // <xsd:element name="equalityMatch" type="AttributeValueAssertion"/>
+      result = createEqualityFilter((AttributeValueAssertion)
+                                                         xmlElement.getValue());
+    }
+    else if ( "substrings".equals(filterName) ) {
+      // <xsd:element name="substrings" type="SubstringFilter"/>
+      result = createSubstringFilter((SubstringFilter)xmlElement.getValue());
+    }
+    else if ( "greaterOrEqual".equals(filterName) ) {
+      // <xsd:element name="greaterOrEqual" type="AttributeValueAssertion"/>
+      result = createGreaterOrEqualFilter((AttributeValueAssertion)
+                                                         xmlElement.getValue());
+    }
+    else if ( "lessOrEqual".equals(filterName) ) {
+      // <xsd:element name="lessOrEqual" type="AttributeValueAssertion"/>
+      result = createLessOrEqualFilter((AttributeValueAssertion)
+                                                         xmlElement.getValue());
+    }
+    else if ( "present".equals(filterName) ) {
+      // <xsd:element name="present" type="AttributeDescription"/>
+      result = createPresentFilter((AttributeDescription)xmlElement.getValue());
+    }
+    else if ( "approxMatch".equals(filterName) ) {
+      // <xsd:element name="approxMatch" type="AttributeValueAssertion"/>
+      result = createApproximateFilter((AttributeValueAssertion)
+                                                         xmlElement.getValue());
+    }
+    else if ( "extensibleMatch".equals(filterName) ) {
+      // <xsd:element name="extensibleMatch" type="MatchingRuleAssertion"/>
+      result = createExtensibleFilter((MatchingRuleAssertion)
+                                                         xmlElement.getValue());
+    }
+    return result;
+  }
+
+  /**
+   * Returns a new LDAPFilter according to the filter assigned to the provided
+   * filter.
+   * 
+   * @param filter a filter that contains the object filter to create.
+   * 
+   * @return a new LDAPFilter according to the filter assigned to the provided
+   *         filter.
+   * 
+   * @throws LDAPException an LDAPException is thrown if the creation of the
+   *                       targeted filter fails.
+   */
+  private static LDAPFilter createFilter(Filter filter)
+          throws LDAPException {
+
+    LDAPFilter result = null;
+    
+    if ( filter.getAnd() != null ) {
+      result = createANDFilter(filter.getAnd());
+    }
+    else if ( filter.getApproxMatch() != null ) {
+      result = createApproximateFilter(filter.getApproxMatch());
+    }
+    else if ( filter.getEqualityMatch() != null ) {
+      result = createEqualityFilter(filter.getEqualityMatch());
+    }
+    else if ( filter.getExtensibleMatch() != null ) {
+      result = createExtensibleFilter(filter.getExtensibleMatch());
+    }
+    else if ( filter.getGreaterOrEqual() != null ) {
+      result = createGreaterOrEqualFilter(filter.getGreaterOrEqual());
+    }
+    else if ( filter.getLessOrEqual() != null ) {
+      result = createLessOrEqualFilter(filter.getLessOrEqual());
+    }
+    else if ( filter.getNot() != null ) {
+      result = createNOTFilter(filter.getNot());
+    }
+    else if ( filter.getOr() != null ) {
+      result = createORFilter(filter.getOr());
+    }
+    else if ( filter.getPresent() != null ) {
+      result = createPresentFilter(filter.getPresent());
+    }
+    else if ( filter.getSubstrings() != null ) {
+      result = createSubstringFilter(filter.getSubstrings());
+    }
+    return result;
+  }
 
   /**
    * Perform the LDAP SEARCH operation and send the result back to the
@@ -96,24 +372,8 @@
     SearchResponse searchResponse = objFactory.createSearchResponse();
     searchResponse.setRequestID(searchRequest.getRequestID());
 
-    ArrayList<LDAPFilter> filters = new ArrayList<LDAPFilter> ();
-    LDAPFilter f = null;
-    if(searchRequest.getFilter().getPresent() != null)
-    {
-      f = LDAPFilter.decode(searchRequest.getFilter().getPresent().getName() +
-          "=*");
-    } else if(searchRequest.getFilter().getEqualityMatch() != null)
-    {
-      AttributeValueAssertion fgem =
-           searchRequest.getFilter().getEqualityMatch();
+    LDAPFilter filter = createFilter(searchRequest.getFilter());
 
-      f = LDAPFilter.createEqualityFilter(fgem.getName(),
-      new ASN1OctetString(fgem.getValue()));
-    }
-    if(f != null)
-    {
-      filters.add(f);
-    }
     DereferencePolicy derefPolicy = DereferencePolicy.NEVER_DEREF_ALIASES;
     String derefStr = searchRequest.getDerefAliases().toLowerCase();
     if (derefStr.equals("derefinsearching"))
@@ -151,113 +411,91 @@
       }
     }
 
-    for (LDAPFilter filter: filters)
+    SearchRequestProtocolOp protocolOp = new SearchRequestProtocolOp(
+        new ASN1OctetString(searchRequest.getDn()),
+        scope, derefPolicy,
+                (int) searchRequest.getSizeLimit(),
+        (int) searchRequest.getTimeLimit(),
+        searchRequest.isTypesOnly(), filter, attributes);
+    try
     {
+      LDAPMessage msg = new LDAPMessage(DSMLServlet.nextMessageID(),
+                                        protocolOp);
+      connection.getLDAPWriter().writeMessage(msg);
 
-      SearchRequestProtocolOp protocolOp = new SearchRequestProtocolOp(
-          new ASN1OctetString(searchRequest.getDn()),
-          scope, derefPolicy,
-                  (int) searchRequest.getSizeLimit(),
-          (int) searchRequest.getTimeLimit(),
-          false, filter, attributes);
-      try
+      byte opType;
+      do
       {
-        LDAPMessage msg = new LDAPMessage(DSMLServlet.nextMessageID(),
-                                          protocolOp);
-        connection.getLDAPWriter().writeMessage(msg);
+        int resultCode = 0;
+        Message errorMessage = null;
+        LDAPMessage responseMessage =
+             connection.getLDAPReader().readMessage();
 
-        byte opType;
-        do
+        opType = responseMessage.getProtocolOpType();
+        switch(opType)
         {
-          int resultCode = 0;
-          Message errorMessage = null;
-          LDAPMessage responseMessage =
-               connection.getLDAPReader().readMessage();
+          case LDAPConstants.OP_TYPE_SEARCH_RESULT_ENTRY:
+            SearchResultEntryProtocolOp searchEntryOp =
+              responseMessage.getSearchResultEntryProtocolOp();
 
-          opType = responseMessage.getProtocolOpType();
-          switch(opType)
-          {
-            case LDAPConstants.OP_TYPE_SEARCH_RESULT_ENTRY:
-              SearchResultEntryProtocolOp searchEntryOp =
-                responseMessage.getSearchResultEntryProtocolOp();
+            SearchResultEntry entry = objFactory.createSearchResultEntry();
+            java.util.List<DsmlAttr> attrList = entry.getAttr();
 
-        SearchResultEntry entry = objFactory.createSearchResultEntry();
-        java.util.List<DsmlAttr> attrList = entry.getAttr();
+            LinkedList<LDAPAttribute> attrs = searchEntryOp.getAttributes();
 
-        LinkedList<LDAPAttribute> attrs = searchEntryOp.getAttributes();
+            for(LDAPAttribute attr : attrs)
+            {
+              String nm = attr.getAttributeType();
+              DsmlAttr dsmlAttr = objFactory.createDsmlAttr();
 
-        for(LDAPAttribute attr : attrs)
-        {
-          String nm = attr.getAttributeType();
-          DsmlAttr dsmlAttr = objFactory.createDsmlAttr();
-
-          dsmlAttr.setName(nm);
-          List<String> dsmlAttrVal = dsmlAttr.getValue();
-          ArrayList<ASN1OctetString> vals = attr.getValues();
-          for(ASN1OctetString val : vals)
-          {
-            dsmlAttrVal.add(val.toString());
-          }
-          attrList.add(dsmlAttr);
-        }
-
-        entry.setDn(searchEntryOp.getDN().toString());
-        searchResponse.getSearchResultEntry().add(entry);
-        /*
-              StringBuilder sb = new StringBuilder();
-              searchEntryOp.toLDIF(sb, 80);
-              System.out.println(sb.toString());
-        */
-              break;
-
-            case LDAPConstants.OP_TYPE_SEARCH_RESULT_REFERENCE:
-              SearchResultReferenceProtocolOp searchRefOp =
-                responseMessage.getSearchResultReferenceProtocolOp();
-              System.out.println(searchRefOp.toString());
-              break;
-
-            case LDAPConstants.OP_TYPE_SEARCH_RESULT_DONE:
-              SearchResultDoneProtocolOp searchOp =
-                responseMessage.getSearchResultDoneProtocolOp();
-              resultCode = searchOp.getResultCode();
-              errorMessage = searchOp.getErrorMessage();
-              LDAPResult result = objFactory.createLDAPResult();
-              ResultCode code = objFactory.createResultCode();
-              code.setCode(resultCode);
-              result.setResultCode(code);
-              result.setErrorMessage(
-                      errorMessage != null ? errorMessage.toString() : null);
-              if(searchOp.getMatchedDN() != null)
+              dsmlAttr.setName(nm);
+              List<String> dsmlAttrVal = dsmlAttr.getValue();
+              ArrayList<ASN1OctetString> vals = attr.getValues();
+              for(ASN1OctetString val : vals)
               {
-                 result.setMatchedDN(searchOp.getMatchedDN().toString());
+                dsmlAttrVal.add(val.toString());
               }
-              searchResponse.setSearchResultDone(result);
-              break;
-            default:
-               // FIXME - throw exception
-               System.err.println("Invalid protocol operation:" + opType);
-               break;
-           }
+              attrList.add(dsmlAttr);
+            }
 
-           if(resultCode != 0 && resultCode != 10)
-           {
-             org.opends.server.types.ResultCode rc =
-                  org.opends.server.types.ResultCode.valueOf(resultCode);
+            entry.setDn(searchEntryOp.getDN().toString());
+            searchResponse.getSearchResultEntry().add(entry);
+            break;
 
-             // TODO:  FIXME - null message
-             throw new LDAPException(resultCode, null, rc.getResultCodeName());
-           }
+          case LDAPConstants.OP_TYPE_SEARCH_RESULT_REFERENCE:
+            SearchResultReferenceProtocolOp searchRefOp =
+              responseMessage.getSearchResultReferenceProtocolOp();
+            break;
 
-        } while(opType != LDAPConstants.OP_TYPE_SEARCH_RESULT_DONE);
+          case LDAPConstants.OP_TYPE_SEARCH_RESULT_DONE:
+            SearchResultDoneProtocolOp searchOp =
+              responseMessage.getSearchResultDoneProtocolOp();
+            resultCode = searchOp.getResultCode();
+            errorMessage = searchOp.getErrorMessage();
+            LDAPResult result = objFactory.createLDAPResult();
+            ResultCode code = objFactory.createResultCode();
+            code.setCode(resultCode);
+            result.setResultCode(code);
+            result.setErrorMessage(
+                    errorMessage != null ? errorMessage.toString() : null);
+            if(searchOp.getMatchedDN() != null)
+            {
+               result.setMatchedDN(searchOp.getMatchedDN().toString());
+            }
+            searchResponse.setSearchResultDone(result);
+            break;
+          default:
+             throw new RuntimeException("Invalid protocol operation:" + opType);
+         }
+      } while(opType != LDAPConstants.OP_TYPE_SEARCH_RESULT_DONE);
 
-      } catch(ASN1Exception ae)
-      {
-        ae.printStackTrace();
-        throw new IOException(ae.getMessage());
-      }
+    } catch(ASN1Exception ae)
+    {
+      ae.printStackTrace();
+      throw new IOException(ae.getMessage());
     }
+
     return searchResponse;
   }
-
 }
 
diff --git a/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java b/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java
index 2e1144f..fc6f661 100644
--- a/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java
+++ b/opendj-sdk/opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java
@@ -27,7 +27,14 @@
 package org.opends.dsml.protocol;
 
 
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.text.ParseException;
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+import javax.xml.bind.JAXBException;
+import org.opends.messages.Message;
 import org.opends.server.core.DirectoryServer;
+import org.opends.server.protocols.ldap.LDAPResultCode;
 import org.opends.server.tools.LDAPConnection;
 import org.opends.server.tools.LDAPConnectionOptions;
 import org.opends.server.util.Base64;
@@ -47,11 +54,21 @@
 import javax.xml.soap.*;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.net.URL;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.List;
 import java.util.StringTokenizer;
 import java.util.concurrent.atomic.AtomicInteger;
+import javax.xml.validation.SchemaFactory;
+import org.opends.server.tools.LDAPConnectionException;
+import org.opends.server.types.LDAPException;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
 
 
 /**
@@ -67,15 +84,33 @@
   private static final long serialVersionUID = -3748022009593442973L;
   private static final AtomicInteger nextMessageID = new AtomicInteger(1);
 
+  // definitions of return error messages
+  private static final String MALFORMED_REQUEST = "malformedRequest";
+  private static final String NOT_ATTEMPTED = "notAttempted";
+  private static final String AUTHENTICATION_FAILED = "authenticationFailed";
+  private static final String COULD_NOT_CONNECT = "couldNotConnect";
+  private static final String GATEWAY_INTERNAL_ERROR = "gatewayInternalError";
+  
+  private static final String UNKNOWN_ERROR = "Unknown error";
+
+  // definitions of onError values
+  private static final String ON_ERROR_RESUME = "resume";
+  private static final String ON_ERROR_EXIT = "exit";
+  
   private Unmarshaller unmarshaller;
   private Marshaller marshaller;
   private ObjectFactory objFactory;
   private MessageFactory messageFactory;
   private DocumentBuilder db;
 
+  // this extends the default handler of SAX parser. It helps to retrieve the
+  // requestID value when the xml request is malformed and thus unparsable
+  // using SOAP or JAXB.
+  private DSMLContentHandler contentHandler;
+  
   private String hostName;
   private Integer port;
-
+  
   /**
    * This method will be called by the Servlet Container when
    * this servlet is being placed into service.
@@ -85,19 +120,22 @@
    * @throws ServletException If an error occurs during processing.
    */
   public void init(ServletConfig config) throws ServletException {
-
+    
     try {
-
       hostName = config.getServletContext().getInitParameter(HOST);
 
       port = new Integer(config.getServletContext().getInitParameter(PORT));
 
       JAXBContext jaxbContext = JAXBContext.newInstance(PKG_NAME);
       unmarshaller = jaxbContext.createUnmarshaller();
+      // assign the DSMLv2 schema for validation
+      URL schema = getClass().getResource("/resources/DSMLv2.xsd");
+      if ( schema != null ) {
+        SchemaFactory sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
+        unmarshaller.setSchema(sf.newSchema(schema));
+      }
 
       marshaller = jaxbContext.createMarshaller();
-      marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper",
-        new NamespacePrefixMapperImpl());
 
       objFactory = new ObjectFactory();
       messageFactory = MessageFactory.newInstance();
@@ -105,29 +143,15 @@
       dbf.setNamespaceAware(true);
       db = dbf.newDocumentBuilder();
 
-      DirectoryServer.bootstrapClient();
+      this.contentHandler = new DSMLContentHandler();
 
+      DirectoryServer.bootstrapClient();
     } catch (Exception je) {
       je.printStackTrace();
       throw new ServletException(je.getMessage());
     }
   }
-
-
-  /**
-   * The HTTP GET operation.
-   *
-   * @param req Information about the request received from the client.
-   * @param res Information about the response to send to the client.
-   * @throws ServletException If an error occurs during servlet processing.
-   * @throws IOException      If an error occurs while interacting with the client.
-   */
-  public void doGet(HttpServletRequest req, HttpServletResponse res)
-    throws ServletException, IOException {
-    super.doGet(req, res);
-  }
-
-
+  
   /**
    * The HTTP POST operation. This servlet expects a SOAP message
    * with a DSML request payload.
@@ -135,222 +159,370 @@
    * @param req Information about the request received from the client.
    * @param res Information about the response to send to the client.
    * @throws ServletException If an error occurs during servlet processing.
-   * @throws IOException      If an error occurs while interacting with the client.
+   * @throws IOException   If an error occurs while interacting with the client.
    */
   public void doPost(HttpServletRequest req, HttpServletResponse res)
-    throws ServletException, IOException {
-    SOAPMessage reply;
+  throws ServletException, IOException {
     LDAPConnectionOptions connOptions = new LDAPConnectionOptions();
     LDAPConnection connection = null;
+    BatchRequest batchRequest = null;
+    
+    // Keep the Servlet input stream buffered in case the SOAP unmarshalling
+    // fails, the SAX parsing will be able to retrieve the requestID even if
+    // the XML is malmformed by resetting the input stream.
+    BufferedInputStream is = new BufferedInputStream(req.getInputStream(),
+                                                     65536);
+    if ( is.markSupported() ) {
+      is.mark(65536);
+    }
 
-    try {
-      MimeHeaders mimeHeaders = new MimeHeaders();
-      Enumeration en = req.getHeaderNames();
-      String bindDN = "";
-      String bindPassword = "";
-      while (en.hasMoreElements()) {
-        String headerName = (String) en.nextElement();
-        String headerVal = req.getHeader(headerName);
-        if (headerName.equalsIgnoreCase("authorization")) {
-          if (headerVal.startsWith("Basic ")) {
-            String authorization = headerVal.substring(6).trim();
-            // Decode and parse the authorization credentials
-            String unencoded =
-              new String(Base64.decode(authorization));
+    // Create response in the beginning as it might be used if the parsing
+    // failes.
+    BatchResponse batchResponse = objFactory.createBatchResponse();
+    List<JAXBElement<?>> batchResponses = batchResponse.getBatchResponses();
+    Document doc = db.newDocument();
+    
+    SOAPBody soapBody = null;
+    
+    MimeHeaders mimeHeaders = new MimeHeaders();
+    Enumeration en = req.getHeaderNames();
+    String bindDN = null;
+    String bindPassword = null;
+    boolean authorizationInHeader = false;
+    while (en.hasMoreElements()) {
+      String headerName = (String) en.nextElement();
+      String headerVal = req.getHeader(headerName);
+      if (headerName.equalsIgnoreCase("authorization")) {
+        if (headerVal.startsWith("Basic ")) {
+          authorizationInHeader = true;
+          String authorization = headerVal.substring(6).trim();
+          try {
+            String unencoded = new String(Base64.decode(authorization));
             int colon = unencoded.indexOf(':');
-            if (colon < 0)
-              continue;
-            bindDN = unencoded.substring(0, colon).trim();
-            bindPassword = unencoded.substring(colon + 1);
+            if (colon > 0) {
+              bindDN = unencoded.substring(0, colon).trim();
+              bindPassword = unencoded.substring(colon + 1);
+            }
+          } catch (ParseException ex) {
+            // DN:password parsing error
+            batchResponses.add(
+              createErrorResponse(
+                    new LDAPException(LDAPResultCode.INVALID_CREDENTIALS,
+                    Message.raw(ex.getMessage()))));
+            break;
           }
         }
-        StringTokenizer tk = new StringTokenizer(headerVal, ",");
-        while (tk.hasMoreTokens()) {
-          mimeHeaders.addHeader(headerName, tk.nextToken().trim());
-        }
       }
+      StringTokenizer tk = new StringTokenizer(headerVal, ",");
+      while (tk.hasMoreTokens()) {
+        mimeHeaders.addHeader(headerName, tk.nextToken().trim());
+      }
+    }
 
-      SOAPMessage message =
-        messageFactory.createMessage(mimeHeaders, req.getInputStream());
-      message.writeTo(System.out);
+    if ( ! authorizationInHeader ) {
+      // if no authorization, set default user
+      bindDN = "";
+      bindPassword = "";
+    } else {
+      // otherwise if DN or password is null, send back an error
+      if ( (bindDN == null || bindPassword == null)
+         && batchResponses.size()==0) {
+        batchResponses.add(
+              createErrorResponse(
+                    new LDAPException(LDAPResultCode.INVALID_CREDENTIALS,
+                    Message.raw("Unable to retrieve credentials."))));
+      }
+    }
 
-      Document doc = db.newDocument();
-      SOAPBody body = message.getSOAPBody();
+    // if an error already occured, the list is not empty
+    if ( batchResponses.size() == 0 ) {
+      try {
+        SOAPMessage message = messageFactory.createMessage(mimeHeaders, is);
+        soapBody = message.getSOAPBody();
+      } catch (SOAPException ex) {
+        // SOAP was unable to parse XML successfully
+        batchResponses.add(
+          createXMLParsingErrorResponse(is, 
+                                        batchResponse,
+                                        String.valueOf(ex.getCause())));
+      }
+    }
 
-      Iterator it = body.getChildElements();
+    if ( soapBody != null ) {
+      Iterator it = soapBody.getChildElements();
       while (it.hasNext()) {
         Object obj = it.next();
         if (!(obj instanceof SOAPElement)) {
           continue;
         }
         SOAPElement se = (SOAPElement) obj;
-        JAXBElement<BatchRequest> batchRequestElement =
-          unmarshaller.unmarshal(se, BatchRequest.class);
-        BatchRequest batchRequest = batchRequestElement.getValue();
-        BatchResponse batchResponse = objFactory.createBatchResponse();
-
-        List<JAXBElement<?>> batchResponses = batchResponse.getBatchResponses();
-        List<DsmlMessage> list = batchRequest.getBatchRequests();
-
-        for (DsmlMessage nextElement : list) {
-          if (nextElement instanceof SearchRequest) {
-            // Process the search request.
+        JAXBElement<BatchRequest> batchRequestElement = null;
+        try {
+          batchRequestElement = unmarshaller.unmarshal(se, BatchRequest.class);
+        } catch (JAXBException e) {
+          // schema validation failed
+          batchResponses.add(createXMLParsingErrorResponse(is,
+                                                       batchResponse,
+                                                       String.valueOf(e)));
+        }
+        if ( batchRequestElement != null ) {
+          batchRequest = batchRequestElement.getValue();
+          
+          // set requestID in response
+          batchResponse.setRequestID(batchRequest.getRequestID());
+          
+          boolean connected = false;
+          if ( connection == null ) {
             connection = new LDAPConnection(hostName, port, connOptions);
-            connection.connectToHost(bindDN, bindPassword);
-
-            SearchRequest sr = (SearchRequest) nextElement;
-            DSMLSearchOperation ds = new DSMLSearchOperation(connection);
-            SearchResponse searchResponse = ds.doSearch(objFactory, sr);
-
-            JAXBElement<SearchResponse> searchResponseEl =
-              objFactory.createBatchResponseSearchResponse(searchResponse);
-            batchResponses.add(searchResponseEl);
-
-          } else if (nextElement instanceof AddRequest) {
-            // Process the add request.
-            connection = new LDAPConnection(hostName, port, connOptions);
-            connection.connectToHost(bindDN, bindPassword);
-            AddRequest ar = (AddRequest) nextElement;
-            DSMLAddOperation addOp = new DSMLAddOperation(connection);
-            LDAPResult addResponse = addOp.doOperation(objFactory, ar);
-            JAXBElement<LDAPResult> addResponseEl =
-              objFactory.createBatchResponseAddResponse(addResponse);
-            batchResponses.add(addResponseEl);
-          } else if (nextElement instanceof AbandonRequest) {
-            // Process the abandon request.
-            connection = new LDAPConnection(hostName, port, connOptions);
-            connection.connectToHost(bindDN, bindPassword);
-            AbandonRequest ar = (AbandonRequest) nextElement;
-            DSMLAbandonOperation ao = new DSMLAbandonOperation(connection);
-            LDAPResult abandonResponse = ao.doOperation(objFactory, ar);
-          } else if (nextElement instanceof ExtendedRequest) {
-            // Process the extended request.
-            connection = new LDAPConnection(hostName, port, connOptions);
-            connection.connectToHost(bindDN, bindPassword);
-            ExtendedRequest er = (ExtendedRequest) nextElement;
-            DSMLExtendedOperation eo = new DSMLExtendedOperation(connection);
-            ExtendedResponse extendedResponse = eo.doOperation(objFactory, er);
-            JAXBElement<ExtendedResponse> extendedResponseEl =
-              objFactory.createBatchResponseExtendedResponse(extendedResponse);
-            batchResponses.add(extendedResponseEl);
-
-          } else if (nextElement instanceof DelRequest) {
-            // Process the delete request.
-            connection = new LDAPConnection(hostName, port, connOptions);
-            connection.connectToHost(bindDN, bindPassword);
-            DelRequest dr = (DelRequest) nextElement;
-            DSMLDeleteOperation delOp = new DSMLDeleteOperation(connection);
-            LDAPResult delResponse = delOp.doOperation(objFactory, dr);
-            JAXBElement<LDAPResult> delResponseEl =
-              objFactory.createBatchResponseDelResponse(delResponse);
-            batchResponses.add(delResponseEl);
-          } else if (nextElement instanceof CompareRequest) {
-            // Process the compare request.
-            connection = new LDAPConnection(hostName, port, connOptions);
-            connection.connectToHost(bindDN, bindPassword);
-            CompareRequest cr = (CompareRequest) nextElement;
-            DSMLCompareOperation compareOp =
-              new DSMLCompareOperation(connection);
-            LDAPResult compareResponse = compareOp.doOperation(objFactory, cr);
-            JAXBElement<LDAPResult> compareResponseEl =
-              objFactory.createBatchResponseCompareResponse(compareResponse);
-            batchResponses.add(compareResponseEl);
-          } else if (nextElement instanceof ModifyDNRequest) {
-            // Process the Modify DN request.
-            connection = new LDAPConnection(hostName, port, connOptions);
-            connection.connectToHost(bindDN, bindPassword);
-            ModifyDNRequest mr = (ModifyDNRequest) nextElement;
-            DSMLModifyDNOperation moddnOp =
-              new DSMLModifyDNOperation(connection);
-            LDAPResult moddnResponse = moddnOp.doOperation(objFactory, mr);
-            JAXBElement<LDAPResult> moddnResponseEl =
-              objFactory.createBatchResponseModDNResponse(moddnResponse);
-            batchResponses.add(moddnResponseEl);
-          } else if (nextElement instanceof ModifyRequest) {
-            // Process the Modify request.
-            connection = new LDAPConnection(hostName, port, connOptions);
-            connection.connectToHost(bindDN, bindPassword);
-            ModifyRequest modr = (ModifyRequest) nextElement;
-            DSMLModifyOperation modOp = new DSMLModifyOperation(connection);
-            LDAPResult modResponse = modOp.doOperation(objFactory, modr);
-            JAXBElement<LDAPResult> modResponseEl =
-              objFactory.createBatchResponseModifyResponse(modResponse);
-            batchResponses.add(modResponseEl);
-          } else {
-            String msg = "Invalid DSML request:" + nextElement;
-            throw new IOException(msg);
+            try {
+              connection.connectToHost(bindDN, bindPassword);
+              connected = true;
+            } catch (LDAPConnectionException e) {
+              // if connection failed, return appropriate error response
+              batchResponses.add(createErrorResponse(e));
+            }
+          }
+          if ( connected ) {
+            List<DsmlMessage> list = batchRequest.getBatchRequests();
+            
+            for (DsmlMessage request : list) {
+              JAXBElement<?> result = performLDAPRequest(connection, request);
+              if ( result != null ) {
+                batchResponses.add(result);
+              }
+              // evaluate response to check if an error occured
+              Object o = result.getValue();
+              if ( o instanceof ErrorResponse ) {
+                if ( ON_ERROR_EXIT.equals(batchRequest.getOnError()) ) {
+                  break;
+                }
+              } else if ( o instanceof LDAPResult ) {
+                int code = ((LDAPResult)o).getResultCode().getCode();
+                if ( code != LDAPResultCode.SUCCESS
+                  && code != LDAPResultCode.REFERRAL
+                  && code != LDAPResultCode.COMPARE_TRUE
+                  && code != LDAPResultCode.COMPARE_FALSE ) {
+                  if ( ON_ERROR_EXIT.equals(batchRequest.getOnError()) ) {
+                    break;
+                  }
+                }
+              }
+            }
+          }
+          // close connection to LDAP server
+          if ( connection != null ) {
+            connection.close(nextMessageID);
           }
         }
-
-        JAXBElement<BatchResponse> batchResponseElement =
-          objFactory.createBatchResponse(batchResponse);
-
-        marshaller.marshal(batchResponseElement, System.out);
-
-        marshaller.marshal(batchResponseElement, doc);
-      }
-
-      // Send the DSML response back to the client.
-      reply = messageFactory.createMessage();
-      sendResponse(doc, false, reply, res, null);
-
-    } catch (Exception se) {
-      se.printStackTrace();
-      // send SOAP fault
-      try {
-        reply = messageFactory.createMessage();
-        sendResponse(null, true, reply, res, se);
-      } catch (Exception e) {
-      }
-    } finally {
-      if (connection != null) {
-        connection.close(nextMessageID);
       }
     }
+    try {
+      marshaller.marshal(objFactory.createBatchResponse(batchResponse), doc);
+      sendResponse(doc, res);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
   }
 
   /**
+   * Returns an error response after a parsing error. The response has the
+   * requestID of the batch request, the error response message of the parsing
+   * exception message and the type 'malformed request'.
+   *
+   * @param is the xml InputStream to parse
+   * @param batchResponse the JAXB object to fill in
+   * @param parserErrorMessage the parsing error message
+   *
+   * @return a JAXBElement that contains an ErrorResponse
+   */
+  private JAXBElement<ErrorResponse> createXMLParsingErrorResponse(
+                                                    InputStream is,
+                                                    BatchResponse batchResponse,
+                                                    String parserErrorMessage) {
+    ErrorResponse errorResponse = objFactory.createErrorResponse();
+    
+    try {
+      // try alternative XML parsing using SAX to retrieve requestID value
+      XMLReader xmlReader = XMLReaderFactory.createXMLReader();
+      // clear previous match
+      this.contentHandler.requestID = null;
+      xmlReader.setContentHandler(this.contentHandler);
+      is.reset();
+      
+      xmlReader.parse(new InputSource(is));
+    } catch (Throwable e) {
+      // document is unparsable so will jump here
+    }
+    if ( parserErrorMessage!= null ) {
+      errorResponse.setMessage(parserErrorMessage);
+    }
+    batchResponse.setRequestID(this.contentHandler.requestID);
+    
+    errorResponse.setType(MALFORMED_REQUEST);
+    
+    return objFactory.createBatchResponseErrorResponse(errorResponse);
+  }
+
+  /**
+   * Returns an error response with attributes set according to the exception
+   * provided as argument.
+   *
+   * @param t the exception that occured
+   *
+   * @return a JAXBElement that contains an ErrorResponse
+   */
+  private JAXBElement<ErrorResponse> createErrorResponse(Throwable t) {
+    // potential exceptions are IOException, LDAPException, ASN1Exception
+    
+    ErrorResponse errorResponse = objFactory.createErrorResponse();
+    errorResponse.setMessage(String.valueOf(t));
+    
+    if ( t instanceof LDAPException ) {
+      switch(((LDAPException)t).getResultCode()) {
+        case LDAPResultCode.AUTHORIZATION_DENIED:
+        case LDAPResultCode.INAPPROPRIATE_AUTHENTICATION:
+        case LDAPResultCode.INVALID_CREDENTIALS:
+        case LDAPResultCode.STRONG_AUTH_REQUIRED:
+          errorResponse.setType(AUTHENTICATION_FAILED);
+          break;
+          
+        case LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR:
+          errorResponse.setType(COULD_NOT_CONNECT);
+          break;
+          
+        case LDAPResultCode.UNWILLING_TO_PERFORM:
+          errorResponse.setType(NOT_ATTEMPTED);
+          break;
+          
+        default:
+          errorResponse.setType(UNKNOWN_ERROR);
+          break;
+      }
+    } else if ( t instanceof LDAPConnectionException ) {
+      errorResponse.setType(COULD_NOT_CONNECT);
+    } else {
+      errorResponse.setType(GATEWAY_INTERNAL_ERROR);
+    }
+    
+    return objFactory.createBatchResponseErrorResponse(errorResponse);
+  }
+
+  /**
+   * Performs the LDAP operation and sends back the result (if any). In case
+   * of error, an error reponse is returned.
+   *
+   * @param connection a connected connection
+   * @param request the JAXB request to perform
+   *
+   * @return null for an abandon request, the expect result for all other
+   *         requests or an error in case of unexpected behaviour.
+   */
+  private JAXBElement<?> performLDAPRequest(LDAPConnection connection,
+                                            DsmlMessage request) {
+    try {
+      if (request instanceof SearchRequest) {
+        // Process the search request.
+        SearchRequest sr = (SearchRequest) request;
+        DSMLSearchOperation ds = new DSMLSearchOperation(connection);
+        SearchResponse searchResponse = ds.doSearch(objFactory, sr);
+        
+        return objFactory.createBatchResponseSearchResponse(searchResponse);
+      } else if (request instanceof AddRequest) {
+        // Process the add request.
+        AddRequest ar = (AddRequest) request;
+        DSMLAddOperation addOp = new DSMLAddOperation(connection);
+        LDAPResult addResponse = addOp.doOperation(objFactory, ar);
+        return objFactory.createBatchResponseAddResponse(addResponse);
+      } else if (request instanceof AbandonRequest) {
+        // Process the abandon request.
+        AbandonRequest ar = (AbandonRequest) request;
+        DSMLAbandonOperation ao = new DSMLAbandonOperation(connection);
+        LDAPResult abandonResponse = ao.doOperation(objFactory, ar);
+        return null;
+      } else if (request instanceof ExtendedRequest) {
+        // Process the extended request.
+        ExtendedRequest er = (ExtendedRequest) request;
+        DSMLExtendedOperation eo = new DSMLExtendedOperation(connection);
+        ExtendedResponse extendedResponse = eo.doOperation(objFactory, er);
+        return objFactory.createBatchResponseExtendedResponse(extendedResponse);
+        
+      } else if (request instanceof DelRequest) {
+        // Process the delete request.
+        DelRequest dr = (DelRequest) request;
+        DSMLDeleteOperation delOp = new DSMLDeleteOperation(connection);
+        LDAPResult delResponse = delOp.doOperation(objFactory, dr);
+        return objFactory.createBatchResponseDelResponse(delResponse);
+      } else if (request instanceof CompareRequest) {
+        // Process the compare request.
+        CompareRequest cr = (CompareRequest) request;
+        DSMLCompareOperation compareOp =
+                new DSMLCompareOperation(connection);
+        LDAPResult compareResponse = compareOp.doOperation(objFactory, cr);
+        return objFactory.createBatchResponseCompareResponse(compareResponse);
+      } else if (request instanceof ModifyDNRequest) {
+        // Process the Modify DN request.
+        ModifyDNRequest mr = (ModifyDNRequest) request;
+        DSMLModifyDNOperation moddnOp =
+                new DSMLModifyDNOperation(connection);
+        LDAPResult moddnResponse = moddnOp.doOperation(objFactory, mr);
+        return objFactory.createBatchResponseModDNResponse(moddnResponse);
+      } else if (request instanceof ModifyRequest) {
+        // Process the Modify request.
+        ModifyRequest modr = (ModifyRequest) request;
+        DSMLModifyOperation modOp = new DSMLModifyOperation(connection);
+        LDAPResult modResponse = modOp.doOperation(objFactory, modr);
+        return objFactory.createBatchResponseModifyResponse(modResponse);
+      } else if (request instanceof AuthRequest) {
+        // Process the Auth request.
+        // Only returns an BatchReponse with an AuthResponse containing the
+        // LDAP result code AUTH_METHOD_NOT_SUPPORTED
+        ResultCode resultCode = objFactory.createResultCode();
+        resultCode.setCode(LDAPResultCode.AUTH_METHOD_NOT_SUPPORTED);
+        
+        LDAPResult ldapResult = objFactory.createLDAPResult();
+        ldapResult.setResultCode(resultCode);
+        
+        return objFactory.createBatchResponseAuthResponse(ldapResult);
+      } 
+    } catch (Throwable t) {
+      return createErrorResponse(t);
+    }
+    // should never happen as the schema was validated
+    return null;
+  }
+
+  
+  /**
    * Send a response back to the client. This could be either a SOAP fault
    * or a correct DSML response.
    *
    * @param doc   The document to include in the response.
-   * @param error Indicates whether an error occurred.
-   * @param reply The reply to send to the client.
    * @param res   Information about the HTTP response to the client.
-   * @param e     Information about any exception that was thrown.
+   *
    * @throws IOException   If an error occurs while interacting with the client.
    * @throws SOAPException If an encoding or decoding error occurs.
    */
-  private void sendResponse(Document doc, boolean error, SOAPMessage reply,
-                            HttpServletResponse res, Exception e)
+  private void sendResponse(Document doc, HttpServletResponse res)
     throws IOException, SOAPException {
+    
+    SOAPMessage reply = messageFactory.createMessage();
     SOAPHeader header = reply.getSOAPHeader();
     header.detachNode();
     SOAPBody replyBody = reply.getSOAPBody();
-
+    
     res.setHeader("Content-Type", "text/xml");
-
-    if (error) {
-      SOAPFault fault = replyBody.addFault();
-      Name faultName = SOAPFactory.newInstance().createName("Server",
-        "", SOAPConstants.URI_NS_SOAP_ENVELOPE);
-      fault.setFaultCode(faultName);
-      fault.setFaultString("Server Error: " + e.getMessage());
-      // FIXME - Set correct fault actor
-      fault.setFaultActor("http://localhost:8080");
-    } else {
-      SOAPElement bodyElement = replyBody.addDocument(doc);
-    }
-
+    
+    SOAPElement bodyElement = replyBody.addDocument(doc);
+    
     reply.saveChanges();
-
+    
     OutputStream os = res.getOutputStream();
     reply.writeTo(os);
     os.flush();
   }
-
-
-
+  
+  
   /**
    * Retrieves a message ID that may be used for the next LDAP message sent to
    * the Directory Server.
@@ -358,15 +530,32 @@
    * @return  A message ID that may be used for the next LDAP message sent to
    *          the Directory Server.
    */
-  public static int nextMessageID()
-  {
+  public static int nextMessageID() {
     int nextID = nextMessageID.getAndIncrement();
-    if (nextID == Integer.MAX_VALUE)
-    {
+    if (nextID == Integer.MAX_VALUE) {
       nextMessageID.set(1);
     }
-
+    
     return nextID;
   }
+
+  /**
+   * This class is used when a xml request is malformed to retrieve the
+   * requestID value using an event xml parser.
+   */
+  private static class DSMLContentHandler extends DefaultHandler {
+    private String requestID;
+    /*
+     * This function fetches the requestID value of the batchRequest xml
+     * element and call the default implementation (super).
+     */
+    public void startElement(String uri, String localName, String qName,
+                             Attributes attributes) throws SAXException {
+      if ( requestID==null && localName.equals("batchRequest") ) {
+        requestID = attributes.getValue("requestID");
+      }
+      super.startElement(uri, localName, qName, attributes);
+    }
+  }
 }
 

--
Gitblit v1.10.0