From 475b62de777edb285f32607cd4501b9c9d551d63 Mon Sep 17 00:00:00 2001
From: Chris Ridd <chris.ridd@forgerock.com>
Date: Mon, 19 Nov 2012 15:25:30 +0000
Subject: [PATCH] Fix OPENDJ-502 DSML gateway not correctly forwarding modifications to userCertificate;binary attributes
---
opends/src/dsml/org/opends/dsml/protocol/DSMLExtendedOperation.java | 30 ----
opends/build.xml | 6
opends/src/dsml/org/opends/dsml/protocol/ByteStringUtility.java | 95 +++++++++++++++
opends/src/dsml/org/opends/dsml/protocol/DSMLModifyOperation.java | 6
opends/src/dsml/org/opends/dsml/protocol/DSMLAddOperation.java | 6
opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java | 71 +++++++----
opends/src/dsml/org/opends/dsml/protocol/DSMLCompareOperation.java | 3
opends/resource/dsml/schema/bindings.xjb | 94 +++++++++++++++
opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java | 8
9 files changed, 255 insertions(+), 64 deletions(-)
diff --git a/opends/build.xml b/opends/build.xml
index 3cbb130..140be66 100644
--- a/opends/build.xml
+++ b/opends/build.xml
@@ -1313,7 +1313,11 @@
<mkdir dir="${dsml.gen.dir}/org/opends/dsml/protocol" />
<xjc target="${dsml.gen.dir}" schema="${dsml.dir}/schema/DSMLv2.xsd"
- removeOldOutput="yes" package="org.opends.dsml.protocol">
+ removeOldOutput="yes" package="org.opends.dsml.protocol"
+ binding="${dsml.dir}/schema/bindings.xjb">
+ <!-- Don't generate package-info.java as it conflicts with
+ the one in src/dsml -->
+ <arg value="-npa"/>
<produces dir="${dsml.gen.dir}/org/opends/dsml/protocol"
includes="* impl/*" />
</xjc>
diff --git a/opends/resource/dsml/schema/bindings.xjb b/opends/resource/dsml/schema/bindings.xjb
new file mode 100644
index 0000000..ce4d5c6
--- /dev/null
+++ b/opends/resource/dsml/schema/bindings.xjb
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ! CDDL HEADER START
+ !
+ ! The contents of this file are subject to the terms of the
+ ! Common Development and Distribution License, Version 1.0 only
+ ! (the "License"). You may not use this file except in compliance
+ ! with the License.
+ !
+ ! You can obtain a copy of the license at
+ ! trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ ! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ ! See the License for the specific language governing permissions
+ ! and limitations under the License.
+ !
+ ! When distributing Covered Code, include this CDDL HEADER in each
+ ! file and include the License file at
+ ! trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ ! add the following below this CDDL HEADER, with the fields enclosed
+ ! by brackets "[]" replaced with your own identifying information:
+ ! Portions Copyright [yyyy] [name of copyright owner]
+ !
+ ! CDDL HEADER END
+ !
+ !
+ ! Copyright 2012 ForgeRock, AS.
+ ! -->
+<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0"
+xmlns:xsd="http://www.w3.org/2001/XMLSchema" schemaLocation="DSMLv2.xsd" >
+ <bindings
+node="//xsd:complexType[@name='AttributeValueAssertion']/xsd:sequence/xsd:element[@name='value']">
+ <property>
+ <baseType name="java.lang.Object"/>
+ </property>
+ </bindings>
+ <bindings
+node="//xsd:complexType[@name='SubstringFilter']/xsd:sequence/xsd:element[@name='initial']">
+ <property>
+ <baseType name="java.lang.Object"/>
+ </property>
+ </bindings>
+ <bindings
+node="//xsd:complexType[@name='SubstringFilter']/xsd:sequence/xsd:element[@name='any']">
+ <property>
+ <baseType name="java.lang.Object"/>
+ </property>
+ </bindings>
+ <bindings
+node="//xsd:complexType[@name='SubstringFilter']/xsd:sequence/xsd:element[@name='final']">
+ <property>
+ <baseType name="java.lang.Object"/>
+ </property>
+ </bindings>
+ <bindings
+node="//xsd:complexType[@name='MatchingRuleAssertion']/xsd:sequence/xsd:element[@name='value']">
+ <property>
+ <baseType name="java.lang.Object"/>
+ </property>
+ </bindings>
+ <bindings
+node="//xsd:complexType[@name='DsmlAttr']/xsd:sequence/xsd:element[@name='value']">
+ <property>
+ <baseType name="java.lang.Object"/>
+ </property>
+ </bindings>
+ <bindings
+node="//xsd:complexType[@name='DsmlModification']/xsd:sequence/xsd:element[@name='value']">
+ <property>
+ <baseType name="java.lang.Object"/>
+ </property>
+ </bindings>
+ <!--
+ <bindings node="//xsd:complexType[@name='ResultCode']">
+ <property>
+ <baseType name="org.opends.dsml.protocol.SafeResultCode"/>
+ </property>
+ </bindings>
+ <bindings node="//xsd:complexType[@name='LDAPResult']/xsd:complexContent/xsd:extension[@base='DsmlMessage']/xsd:sequence/xsd:element[@name='resultCode']">
+ <property>
+ <baseType name="org.opends.dsml.protocol.SafeResultCode"/>
+ </property>
+ </bindings>
+ -->
+ <bindings node="//xsd:complexType[@name='ExtendedRequest']/xsd:complexContent/xsd:extension[@base='DsmlMessage']/xsd:sequence/xsd:element[@name='requestValue']">
+ <property>
+ <baseType name="java.lang.Object"/>
+ </property>
+ </bindings>
+ <bindings node="//xsd:complexType[@name='ExtendedResponse']/xsd:complexContent/xsd:extension[@base='LDAPResult']/xsd:sequence/xsd:element[@name='response']">
+ <property>
+ <baseType name="java.lang.Object"/>
+ </property>
+ </bindings>
+</bindings>
diff --git a/opends/src/dsml/org/opends/dsml/protocol/ByteStringUtility.java b/opends/src/dsml/org/opends/dsml/protocol/ByteStringUtility.java
new file mode 100644
index 0000000..c0498df
--- /dev/null
+++ b/opends/src/dsml/org/opends/dsml/protocol/ByteStringUtility.java
@@ -0,0 +1,95 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2012 ForgeRock AS.
+ */
+package org.opends.dsml.protocol;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+
+import org.opends.server.types.ByteString;
+import org.opends.server.types.ByteStringBuilder;
+import org.w3c.dom.Element;
+
+/**
+ * A utility class to assist in converting DsmlValues (in Objects) into
+ * the required ByteStrings.
+ */
+public class ByteStringUtility
+{
+ /**
+ * Returns a ByteString from a DsmlValue Object.
+ *
+ * @param obj
+ * the DsmlValue object.
+ * @return a new ByteString object with the value, or null if val was null,
+ * or if it could not be converted.
+ * @throws IOException if any problems occurred retrieving an anyURI value.
+ */
+ public static ByteString convertValue(Object obj)
+ throws IOException, MalformedURLException
+ {
+ ByteString bs = null;
+ if (obj != null)
+ {
+ if (obj instanceof String)
+ {
+ bs = ByteString.valueOf((String)obj);
+ }
+ else if (obj instanceof byte [])
+ {
+ bs = ByteString.wrap((byte [])obj);
+ }
+ else if (obj instanceof URI)
+ {
+ // read raw content and return as a byte[].
+ InputStream is = null;
+ try
+ {
+ is = ((URI) obj).toURL().openStream();
+ ByteStringBuilder bsb = new ByteStringBuilder();
+ while (bsb.append(is, 2048) != -1)
+ {
+ // do nothing
+ }
+ bs = bsb.toByteString();
+ }
+ finally
+ {
+ is.close();
+ }
+ }
+ else if (obj instanceof Element)
+ {
+ Element element = (Element) obj;
+ bs = ByteString.valueOf(element.getTextContent());
+ }
+ }
+ return bs;
+ }
+
+}
diff --git a/opends/src/dsml/org/opends/dsml/protocol/DSMLAddOperation.java b/opends/src/dsml/org/opends/dsml/protocol/DSMLAddOperation.java
index 7b32cbd..ef8a3e4 100644
--- a/opends/src/dsml/org/opends/dsml/protocol/DSMLAddOperation.java
+++ b/opends/src/dsml/org/opends/dsml/protocol/DSMLAddOperation.java
@@ -98,10 +98,10 @@
for(DsmlAttr attr : addList)
{
ArrayList<ByteString> values = new ArrayList<ByteString>();
- List<String> vals = attr.getValue();
- for(String val : vals)
+ List<Object> vals = attr.getValue();
+ for(Object val : vals)
{
- values.add(ByteString.valueOf(val));
+ values.add(ByteStringUtility.convertValue(val));
}
LDAPAttribute ldapAttribute = new LDAPAttribute(attr.getName(), values);
attributes.add(ldapAttribute);
diff --git a/opends/src/dsml/org/opends/dsml/protocol/DSMLCompareOperation.java b/opends/src/dsml/org/opends/dsml/protocol/DSMLCompareOperation.java
index c8c4706..b01e399 100644
--- a/opends/src/dsml/org/opends/dsml/protocol/DSMLCompareOperation.java
+++ b/opends/src/dsml/org/opends/dsml/protocol/DSMLCompareOperation.java
@@ -91,7 +91,8 @@
// Read the attribute name and value for the compare request.
AttributeValueAssertion attrValAssertion = compareRequest.getAssertion();
String attrName = attrValAssertion.getName();
- ByteString attrValue = ByteString.valueOf(attrValAssertion.getValue());
+ Object assertion = attrValAssertion.getValue();
+ ByteString attrValue = ByteStringUtility.convertValue(assertion);
ByteString dnStr = ByteString.valueOf(compareRequest.getDn());
// Create and send the LDAP compare request to the server.
diff --git a/opends/src/dsml/org/opends/dsml/protocol/DSMLExtendedOperation.java b/opends/src/dsml/org/opends/dsml/protocol/DSMLExtendedOperation.java
index 59681b7..4179833 100644
--- a/opends/src/dsml/org/opends/dsml/protocol/DSMLExtendedOperation.java
+++ b/opends/src/dsml/org/opends/dsml/protocol/DSMLExtendedOperation.java
@@ -43,8 +43,6 @@
import org.opends.server.types.ByteString;
import org.opends.server.types.LDAPException;
-import org.w3c.dom.Element;
-
/**
* This class provides the functionality for the performing an
@@ -114,33 +112,7 @@
String requestName = extendedRequest.getRequestName();
Object value = extendedRequest.getRequestValue();
- ByteString asnValue = null;
- // value is optional in the request
- if (value != null)
- {
- /*
- * The processing of the value is tricky, because the schema defines
- * the requestValue with type="xsd:anyType".
- *
- * Consequently if we have:
- * <requestValue xsi:type="xsd:base64Binary">(base64)</requestValue>
- * then JAXB returns us a byte [] containing the decoded data.
- */
- if (value instanceof byte [])
- {
- asnValue = ByteString.wrap((byte [])value);
- }
- else
- {
- /*
- * On the other hand if we have:
- * <requestValue>arbitrary text</requestValue>
- * then we get an Element which we have to extract the text from.
- */
- Element content = (Element)value;
- asnValue = ByteString.valueOf(content.getTextContent());
- }
- }
+ ByteString asnValue = ByteStringUtility.convertValue(value);
// Create and send the LDAP request to the server.
ProtocolOp op = new ExtendedRequestProtocolOp(requestName, asnValue);
diff --git a/opends/src/dsml/org/opends/dsml/protocol/DSMLModifyOperation.java b/opends/src/dsml/org/opends/dsml/protocol/DSMLModifyOperation.java
index 3361549..364d154 100644
--- a/opends/src/dsml/org/opends/dsml/protocol/DSMLModifyOperation.java
+++ b/opends/src/dsml/org/opends/dsml/protocol/DSMLModifyOperation.java
@@ -114,10 +114,10 @@
String attrType = attr.getName();
ArrayList<ByteString> values = new ArrayList<ByteString> ();
- List<String> vals = attr.getValue();
- for(String val : vals)
+ List<Object> vals = attr.getValue();
+ for(Object val : vals)
{
- values.add(ByteString.valueOf(val));
+ values.add(ByteStringUtility.convertValue(val));
}
LDAPAttribute ldapAttr = new LDAPAttribute(attrType, values);
diff --git a/opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java b/opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java
index e7325a2..a0b2337 100644
--- a/opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java
+++ b/opends/src/dsml/org/opends/dsml/protocol/DSMLSearchOperation.java
@@ -93,9 +93,10 @@
* @throws LDAPException
* an LDAPException is thrown if the creation of a filter
* component fails.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
private static LDAPFilter createANDFilter(FilterSet filterSet)
- throws LDAPException
+ throws LDAPException, IOException
{
List<JAXBElement<?>> list = filterSet.getFilterGroup();
ArrayList<RawFilter> filters = new ArrayList<RawFilter>(list.size());
@@ -118,11 +119,13 @@
* filter.
* @return a new Approximate search filter with the provided
* information.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
private static LDAPFilter createApproximateFilter(AttributeValueAssertion ava)
+ throws IOException
{
- return LDAPFilter.createApproximateFilter(ava.getName(), ByteString
- .valueOf(ava.getValue()));
+ return LDAPFilter.createApproximateFilter(ava.getName(),
+ ByteStringUtility.convertValue(ava.getValue()));
}
@@ -135,11 +138,13 @@
* the attribute value assertion for this Equality filter.
* @return a new Equality search filter with the provided
* information.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
private static LDAPFilter createEqualityFilter(AttributeValueAssertion ava)
+ throws IOException
{
- return LDAPFilter.createEqualityFilter(ava.getName(), ByteString
- .valueOf(ava.getValue()));
+ return LDAPFilter.createEqualityFilter(ava.getName(),
+ ByteStringUtility.convertValue(ava.getValue()));
}
@@ -152,11 +157,14 @@
* the matching rule assertion for this Extensible filter.
* @return a new Extensible search filter with the provided
* information.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
private static LDAPFilter createExtensibleFilter(MatchingRuleAssertion mra)
+ throws IOException
{
return LDAPFilter.createExtensibleFilter(mra.getMatchingRule(), mra
- .getName(), ByteString.valueOf(mra.getValue()), mra.isDnAttributes());
+ .getName(), ByteStringUtility.convertValue(mra.getValue()),
+ mra.isDnAttributes());
}
@@ -170,12 +178,14 @@
* filter.
* @return a new GreaterOrEqual search filter with the provided
* information.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
private static LDAPFilter createGreaterOrEqualFilter(
AttributeValueAssertion ava)
+ throws IOException
{
- return LDAPFilter.createGreaterOrEqualFilter(ava.getName(), ByteString
- .valueOf(ava.getValue()));
+ return LDAPFilter.createGreaterOrEqualFilter(ava.getName(),
+ ByteStringUtility.convertValue(ava.getValue()));
}
@@ -189,11 +199,13 @@
* filter.
* @return a new LessOrEqual search filter with the provided
* information.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
private static LDAPFilter createLessOrEqualFilter(AttributeValueAssertion ava)
+ throws IOException
{
- return LDAPFilter.createLessOrEqualFilter(ava.getName(), ByteString
- .valueOf(ava.getValue()));
+ return LDAPFilter.createLessOrEqualFilter(ava.getName(),
+ ByteStringUtility.convertValue(ava.getValue()));
}
@@ -207,8 +219,10 @@
* @throws LDAPException
* an LDAPException is thrown if the creation of the
* provided filter fails.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
- private static LDAPFilter createNOTFilter(Filter filter) throws LDAPException
+ private static LDAPFilter createNOTFilter(Filter filter)
+ throws LDAPException, IOException
{
return LDAPFilter.createNOTFilter(createFilter(filter));
}
@@ -226,9 +240,10 @@
* @throws LDAPException
* an LDAPException is thrown if the creation of a filter
* component fails.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
private static LDAPFilter createORFilter(FilterSet filterSet)
- throws LDAPException
+ throws LDAPException, IOException
{
List<JAXBElement<?>> list = filterSet.getFilterGroup();
ArrayList<RawFilter> filters = new ArrayList<RawFilter>(list.size());
@@ -271,17 +286,19 @@
* the substring filter for this Substring filter.
* @return a new Substring search filter with the provided
* information.
+ * @throws LDAPException if the filter could not be decoded.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
private static LDAPFilter createSubstringFilter(SubstringFilter sf)
- throws LDAPException
+ throws LDAPException, IOException
{
- List<String> anys = sf.getAny();
- ArrayList<ByteString> subAnyElements = new ArrayList<ByteString>(anys
+ List<Object> anyo = sf.getAny();
+ ArrayList<ByteString> subAnyElements = new ArrayList<ByteString>(anyo
.size());
- for (String s : anys)
+ for (Object o : anyo)
{
- subAnyElements.add(ByteString.valueOf(s));
+ subAnyElements.add(ByteStringUtility.convertValue(o));
}
if(sf.getInitial() == null && subAnyElements.isEmpty()
&& sf.getFinal()==null)
@@ -289,9 +306,12 @@
Message message = ERR_LDAP_FILTER_DECODE_NULL.get();
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
- return LDAPFilter.createSubstringFilter(sf.getName(), sf.getInitial()==null?
- null:ByteString.valueOf(sf.getInitial()), subAnyElements,
- sf.getFinal()==null?null:ByteString.valueOf(sf.getFinal()));
+ return LDAPFilter.createSubstringFilter(sf.getName(),
+ sf.getInitial() == null ? null : ByteStringUtility
+ .convertValue(sf.getInitial()),
+ subAnyElements,
+ sf.getFinal() == null ? null : ByteStringUtility
+ .convertValue(sf.getFinal()));
}
@@ -310,9 +330,10 @@
* @throws LDAPException
* an LDAPException is thrown if the creation of the
* targeted filter fails.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
private static LDAPFilter createFilter(JAXBElement<?> xmlElement)
- throws LDAPException
+ throws LDAPException, IOException
{
LDAPFilter result = null;
@@ -395,8 +416,10 @@
* @throws LDAPException
* an LDAPException is thrown if the creation of the
* targeted filter fails.
+ * @throws IOException if a value is an anyURI and cannot be fetched.
*/
- private static LDAPFilter createFilter(Filter filter) throws LDAPException
+ private static LDAPFilter createFilter(Filter filter)
+ throws LDAPException, IOException
{
LDAPFilter result = null;
@@ -561,11 +584,11 @@
DsmlAttr dsmlAttr = objFactory.createDsmlAttr();
dsmlAttr.setName(nm);
- List<String> dsmlAttrVal = dsmlAttr.getValue();
+ List<Object> dsmlAttrVal = dsmlAttr.getValue();
ArrayList<ByteString> vals = attr.getValues();
for (ByteString val : vals)
{
- dsmlAttrVal.add(val.toString());
+ dsmlAttrVal.add(val);
}
attrList.add(dsmlAttr);
}
diff --git a/opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java b/opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java
index 83191ae..e127c91 100644
--- a/opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java
+++ b/opends/src/dsml/org/opends/dsml/protocol/DSMLServlet.java
@@ -124,6 +124,7 @@
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 UNRESOLVABLE_URI = "unresolvableURI";
private static final String UNKNOWN_ERROR = "Unknown error";
@@ -199,11 +200,10 @@
* and if the value's true then mark that OID (1.2.3.4.5) as one returning
* a string value.
*/
- Enumeration<String> names = config.getServletContext()
- .getInitParameterNames();
+ Enumeration names = config.getServletContext().getInitParameterNames();
while (names.hasMoreElements())
{
- String name = names.nextElement().toString();
+ String name = (String) names.nextElement();
if (name.startsWith(EXOPSTRINGPREFIX) &&
Boolean.valueOf(config.getServletContext().getInitParameter(name)))
{
@@ -650,6 +650,8 @@
}
} else if ( t instanceof LDAPConnectionException ) {
errorResponse.setType(COULD_NOT_CONNECT);
+ } else if ( t instanceof IOException ) {
+ errorResponse.setType(UNRESOLVABLE_URI);
} else {
errorResponse.setType(GATEWAY_INTERNAL_ERROR);
}
--
Gitblit v1.10.0