From 22094368c2865dcfb6daf8366425212b721a4657 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Thu, 05 Feb 2009 17:42:14 +0000
Subject: [PATCH] Merge ASN1 branch to trunk
---
opends/src/server/org/opends/server/controls/ServerSideSortRequestControl.java | 614 ++++++++++++++++++++++++++++++++-----------------------
1 files changed, 354 insertions(+), 260 deletions(-)
diff --git a/opends/src/server/org/opends/server/controls/ServerSideSortRequestControl.java b/opends/src/server/org/opends/server/controls/ServerSideSortRequestControl.java
index 068a14a..2c71b03 100644
--- a/opends/src/server/org/opends/server/controls/ServerSideSortRequestControl.java
+++ b/opends/src/server/org/opends/server/controls/ServerSideSortRequestControl.java
@@ -31,19 +31,15 @@
import java.util.ArrayList;
import java.util.StringTokenizer;
+import java.io.IOException;
import org.opends.server.api.OrderingMatchingRule;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.protocols.asn1.ASN1Boolean;
-import org.opends.server.protocols.asn1.ASN1Element;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.protocols.asn1.ASN1Sequence;
+import org.opends.server.protocols.asn1.*;
+import static org.opends.server.protocols.asn1.ASN1Constants.
+ UNIVERSAL_OCTET_STRING_TYPE;
import org.opends.server.protocols.ldap.LDAPResultCode;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.Control;
-import org.opends.server.types.LDAPException;
-import org.opends.server.types.SortKey;
-import org.opends.server.types.SortOrder;
+import org.opends.server.types.*;
import static org.opends.messages.ProtocolMessages.*;
import static org.opends.server.util.ServerConstants.*;
@@ -53,7 +49,10 @@
/**
* This class implements the server-side sort request control as defined in RFC
- * 2891 section 1.1. The ASN.1 description for the control value is:
+ * 2891 section 1.1. The subclass ServerSideSortRequestControl.ClientRequest
+ * should be used when encoding this control from a sort order string. This is
+ * suitable for client tools that want to encode this control without a
+ * SortOrder object. The ASN.1 description for the control value is:
* <BR><BR>
* <PRE>
* SortKeyList ::= SEQUENCE OF SEQUENCE {
@@ -63,7 +62,7 @@
* </PRE>
*/
public class ServerSideSortRequestControl
- extends Control
+ extends Control
{
/**
* The BER type to use when encoding the orderingRule element.
@@ -78,140 +77,165 @@
private static final byte TYPE_REVERSE_ORDER = (byte) 0x81;
+ /**
+ * ControlDecoder implentation to decode this control from a ByteString.
+ */
+ private final static class Decoder
+ implements ControlDecoder<ServerSideSortRequestControl>
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public ServerSideSortRequestControl decode(boolean isCritical,
+ ByteString value)
+ throws DirectoryException
+ {
+ if (value == null)
+ {
+ Message message = INFO_SORTREQ_CONTROL_NO_VALUE.get();
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message);
+ }
+
+ ASN1Reader reader = ASN1.getReader(value);
+ try
+ {
+ reader.readStartSequence();
+ if (!reader.hasNextElement())
+ {
+ Message message = INFO_SORTREQ_CONTROL_NO_SORT_KEYS.get();
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message);
+ }
+
+ ArrayList<SortKey> sortKeys = new ArrayList<SortKey>();
+ while(reader.hasNextElement())
+ {
+ reader.readStartSequence();
+ String attrName = toLowerCase(reader.readOctetStringAsString());
+ AttributeType attrType =
+ DirectoryServer.getAttributeType(attrName, false);
+ if (attrType == null)
+ {
+ Message message = INFO_SORTREQ_CONTROL_UNDEFINED_ATTR.get(attrName);
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message);
+ }
+
+ OrderingMatchingRule orderingRule = null;
+ boolean ascending = true;
+
+ while(reader.hasNextElement())
+ {
+ switch (reader.peekType())
+ {
+ case TYPE_ORDERING_RULE_ID:
+ String orderingRuleID =
+ toLowerCase(reader.readOctetStringAsString());
+ orderingRule =
+ DirectoryServer.getOrderingMatchingRule(orderingRuleID);
+ if (orderingRule == null)
+ {
+ Message message =
+ INFO_SORTREQ_CONTROL_UNDEFINED_ORDERING_RULE.
+ get(orderingRuleID);
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
+ message);
+ }
+ break;
+
+ case TYPE_REVERSE_ORDER:
+ ascending = ! reader.readBoolean();
+ break;
+
+ default:
+ Message message = INFO_SORTREQ_CONTROL_INVALID_SEQ_ELEMENT_TYPE.
+ get(byteToHex(reader.peekType()));
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
+ message);
+ }
+ }
+
+ if ((orderingRule == null) &&
+ (attrType.getOrderingMatchingRule() == null))
+ {
+ Message message =
+ INFO_SORTREQ_CONTROL_NO_ORDERING_RULE_FOR_ATTR.get(attrName);
+ throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
+ message);
+ }
+
+ sortKeys.add(new SortKey(attrType, ascending, orderingRule));
+ }
+
+ return new ServerSideSortRequestControl(isCritical,
+ new SortOrder(sortKeys.toArray(new SortKey[0])));
+ }
+ catch (DirectoryException de)
+ {
+ throw de;
+ }
+ catch (Exception e)
+ {
+ Message message =
+ INFO_SORTREQ_CONTROL_CANNOT_DECODE_VALUE.get(
+ getExceptionMessage(e));
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e);
+ }
+ }
+
+ public String getOID()
+ {
+ return OID_SERVER_SIDE_SORT_REQUEST_CONTROL;
+ }
+
+ }
+
+ /**
+ * The Control Decoder that can be used to decode this control.
+ */
+ public static final ControlDecoder<ServerSideSortRequestControl> DECODER =
+ new Decoder();
+
+ // The sort order associated with this control represented by strings.
+ private ArrayList<String[]> decodedKeyList;
// The sort order associated with this control.
private SortOrder sortOrder;
-
-
/**
- * Creates a new server-side sort request control based on the provided sort
- * order.
+ * Creates a new server-side sort request control based on the definition in
+ * the provided sort order string.
*
- * @param sortOrder The sort order to use for this control.
+ * @param sortOrderString The string representation of the sort order to
+ * use for the control.
+ * @throws LDAPException If the provided sort order string could not be
+ * decoded.
*/
- public ServerSideSortRequestControl(SortOrder sortOrder)
+ public ServerSideSortRequestControl(String sortOrderString)
+ throws LDAPException
{
- super(OID_SERVER_SIDE_SORT_REQUEST_CONTROL, false,
- encodeControlValue(sortOrder));
-
- this.sortOrder = sortOrder;
+ this(false, sortOrderString);
}
-
-
/**
* Creates a new server-side sort request control based on the definition in
- * the provided sort order string. This is only intended for client-side use,
- * and controls created with this constructor should not attempt to use the
- * generated sort order for any purpose.
+ * the provided sort order string.
*
- * @param sortOrderString The string representation of the sort order to use
- * for the control.
- *
- * @throws LDAPException If the provided sort order string could not be
- * decoded.
+ * @param isCritical Indicates whether support for this control
+ * should be considered a critical part of the
+ * server processing.
+ * @param sortOrderString The string representation of the sort order to
+ * use for the control.
+ * @throws LDAPException If the provided sort order string could not be
+ * decoded.
*/
- public ServerSideSortRequestControl(String sortOrderString)
- throws LDAPException
+ public ServerSideSortRequestControl(boolean isCritical,
+ String sortOrderString)
+ throws LDAPException
{
- super(OID_SERVER_SIDE_SORT_REQUEST_CONTROL, false,
- encodeControlValue(sortOrderString));
+ super(OID_SERVER_SIDE_SORT_REQUEST_CONTROL, isCritical);
- this.sortOrder = null;
- }
-
-
-
- /**
- * Creates a new server-side sort request control with the provided
- * information.
- *
- * @param oid The OID to use for this control.
- * @param isCritical Indicates whether support for this control should be
- * considered a critical part of the server processing.
- * @param controlValue The encoded value for this control.
- * @param sortOrder sort order associated with this server-side sort
- * control.
- */
- private ServerSideSortRequestControl(String oid, boolean isCritical,
- ASN1OctetString controlValue,
- SortOrder sortOrder)
- {
- super(oid, isCritical, controlValue);
-
- this.sortOrder = sortOrder;
- }
-
-
-
- /**
- * Retrieves the sort order for this server-side sort request control.
- *
- * @return The sort order for this server-side sort request control.
- */
- public SortOrder getSortOrder()
- {
- return sortOrder;
- }
-
-
-
- /**
- * Encodes the provided sort order object in a manner suitable for use as the
- * value of this control.
- *
- * @param sortOrder The sort order to be encoded.
- *
- * @return The ASN.1 octet string containing the encoded sort order.
- */
- private static ASN1OctetString encodeControlValue(SortOrder sortOrder)
- {
- SortKey[] sortKeys = sortOrder.getSortKeys();
- ArrayList<ASN1Element> keyList =
- new ArrayList<ASN1Element>(sortKeys.length);
- for (SortKey sortKey : sortKeys)
- {
- ArrayList<ASN1Element> elementList = new ArrayList<ASN1Element>(3);
- elementList.add(new ASN1OctetString(
- sortKey.getAttributeType().getNameOrOID()));
-
- if (sortKey.getOrderingRule() != null)
- {
- elementList.add(new ASN1OctetString(TYPE_ORDERING_RULE_ID,
- sortKey.getOrderingRule().getNameOrOID()));
- }
-
- if (! sortKey.ascending())
- {
- elementList.add(new ASN1Boolean(TYPE_REVERSE_ORDER, true));
- }
-
- keyList.add(new ASN1Sequence(elementList));
- }
-
- return new ASN1OctetString(new ASN1Sequence(keyList).encode());
- }
-
-
-
- /**
- * Encodes the provided sort order string in a manner suitable for use as the
- * value of this control.
- *
- * @param sortOrderString The sort order string to be encoded.
- *
- * @return The ASN.1 octet string containing the encoded sort order.
- *
- * @throws LDAPException If the provided sort order string cannot be decoded
- * to create the control value.
- */
- private static ASN1OctetString encodeControlValue(String sortOrderString)
- throws LDAPException
- {
StringTokenizer tokenizer = new StringTokenizer(sortOrderString, ",");
- ArrayList<ASN1Element> keyList = new ArrayList<ASN1Element>();
+ decodedKeyList = new ArrayList<String[]>();
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken().trim();
@@ -238,16 +262,11 @@
if (reverseOrder)
{
- ArrayList<ASN1Element> elementList = new ArrayList<ASN1Element>(2);
- elementList.add(new ASN1OctetString(token));
- elementList.add(new ASN1Boolean(TYPE_REVERSE_ORDER, reverseOrder));
- keyList.add(new ASN1Sequence(elementList));
+ decodedKeyList.add(new String[]{token, null, "r"});
}
else
{
- ArrayList<ASN1Element> elementList = new ArrayList<ASN1Element>(1);
- elementList.add(new ASN1OctetString(token));
- keyList.add(new ASN1Sequence(elementList));
+ decodedKeyList.add(new String[]{token, null, null});
}
}
else if (colonPos == 0)
@@ -269,160 +288,91 @@
if (reverseOrder)
{
- ArrayList<ASN1Element> elementList = new ArrayList<ASN1Element>(3);
- elementList.add(new ASN1OctetString(attrName));
- elementList.add(new ASN1OctetString(TYPE_ORDERING_RULE_ID, ruleID));
- elementList.add(new ASN1Boolean(TYPE_REVERSE_ORDER, reverseOrder));
- keyList.add(new ASN1Sequence(elementList));
+ decodedKeyList.add(new String[]{attrName, ruleID, "r"});
}
else
{
- ArrayList<ASN1Element> elementList = new ArrayList<ASN1Element>(2);
- elementList.add(new ASN1OctetString(attrName));
- elementList.add(new ASN1OctetString(TYPE_ORDERING_RULE_ID, ruleID));
- keyList.add(new ASN1Sequence(elementList));
+ decodedKeyList.add(new String[]{attrName, ruleID, null});
}
}
}
- if (keyList.isEmpty())
+ if (decodedKeyList.isEmpty())
{
Message message = INFO_SORTREQ_CONTROL_NO_SORT_KEYS.get();
throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
}
-
- return new ASN1OctetString(new ASN1Sequence(keyList).encode());
}
-
/**
- * Creates a new server-side sort request control from the contents of the
- * provided control.
+ * Creates a new server-side sort request control based on the provided sort
+ * order.
*
- * @param control The generic control containing the information to use to
- * create this server-side sort request control. It must not
- * be {@code null}.
- *
- * @return The server-side sort request control decoded from the provided
- * control.
- *
- * @throws LDAPException If this control cannot be decoded as a valid
- * server-side sort request control.
+ * @param sortOrder The sort order to use for this control.
*/
- public static ServerSideSortRequestControl decodeControl(Control control)
- throws LDAPException
+ public ServerSideSortRequestControl(SortOrder sortOrder)
{
- ASN1OctetString controlValue = control.getValue();
- if (controlValue == null)
- {
- Message message = INFO_SORTREQ_CONTROL_NO_VALUE.get();
- throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
- }
-
- try
- {
- ASN1Sequence orderSequence =
- ASN1Sequence.decodeAsSequence(controlValue.value());
- ArrayList<ASN1Element> orderElements = orderSequence.elements();
- SortKey[] sortKeys = new SortKey[orderElements.size()];
- if (sortKeys.length == 0)
- {
- Message message = INFO_SORTREQ_CONTROL_NO_SORT_KEYS.get();
- throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
- }
-
- for (int i=0; i < sortKeys.length; i++)
- {
- ASN1Sequence keySequence = orderElements.get(i).decodeAsSequence();
- ArrayList<ASN1Element> keyElements = keySequence.elements();
-
- String attrName =
- keyElements.get(0).decodeAsOctetString().stringValue().
- toLowerCase();
- AttributeType attrType = DirectoryServer.getAttributeType(attrName,
- false);
- if (attrType == null)
- {
- Message message = INFO_SORTREQ_CONTROL_UNDEFINED_ATTR.get(attrName);
- throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
- }
-
- OrderingMatchingRule orderingRule = null;
- boolean ascending = true;
-
- for (int j=1; j < keyElements.size(); j++)
- {
- ASN1Element e = keyElements.get(j);
- switch (e.getType())
- {
- case TYPE_ORDERING_RULE_ID:
- String orderingRuleID =
- e.decodeAsOctetString().stringValue().toLowerCase();
- orderingRule =
- DirectoryServer.getOrderingMatchingRule(orderingRuleID);
- if (orderingRule == null)
- {
- Message message = INFO_SORTREQ_CONTROL_UNDEFINED_ORDERING_RULE.
- get(orderingRuleID);
- throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
- }
- break;
-
- case TYPE_REVERSE_ORDER:
- ascending = ! e.decodeAsBoolean().booleanValue();
- break;
-
- default:
- Message message = INFO_SORTREQ_CONTROL_INVALID_SEQ_ELEMENT_TYPE.
- get(byteToHex(e.getType()));
- throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
- }
- }
-
- if ((orderingRule == null) &&
- (attrType.getOrderingMatchingRule() == null))
- {
- Message message =
- INFO_SORTREQ_CONTROL_NO_ORDERING_RULE_FOR_ATTR.get(attrName);
- throw new LDAPException(LDAPResultCode.CONSTRAINT_VIOLATION, message);
- }
-
- sortKeys[i] = new SortKey(attrType, ascending, orderingRule);
- }
-
- return new ServerSideSortRequestControl(control.getOID(),
- control.isCritical(),
- controlValue,
- new SortOrder(sortKeys));
- }
- catch (LDAPException le)
- {
- throw le;
- }
- catch (Exception e)
- {
- Message message =
- INFO_SORTREQ_CONTROL_CANNOT_DECODE_VALUE.get(getExceptionMessage(e));
- throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message, e);
- }
+ this(false, sortOrder);
}
+ /**
+ * Creates a new server-side sort request control with the provided
+ * information.
+ *
+ * @param isCritical Indicates whether support for this control should be
+ * considered a critical part of the server processing.
+ * @param sortOrder sort order associated with this server-side sort
+ * control.
+ */
+ public ServerSideSortRequestControl(boolean isCritical, SortOrder sortOrder)
+ {
+ super(OID_SERVER_SIDE_SORT_REQUEST_CONTROL, isCritical);
+
+ this.sortOrder = sortOrder;
+ }
/**
- * Retrieves a string representation of this server-side sort request control.
+ * Retrieves the sort order for this server-side sort request control.
*
- * @return A string representation of this server-side sort request control.
+ * @return The sort order for this server-side sort request control.
+ * @throws DirectoryException if an error occurs while retriving the
+ * sort order.
*/
- public String toString()
+ public SortOrder getSortOrder() throws DirectoryException
{
- StringBuilder buffer = new StringBuilder();
- toString(buffer);
- return buffer.toString();
+ if(sortOrder == null)
+ {
+ sortOrder = decodeSortOrderFromString();
+ }
+
+ return sortOrder;
}
+ /**
+ * Writes this control's value to an ASN.1 writer. The value (if any) must
+ * be written as an ASN1OctetString.
+ *
+ * @param writer The ASN.1 writer to use.
+ * @throws IOException If a problem occurs while writing to the stream.
+ */
+ @Override
+ protected void writeValue(ASN1Writer writer) throws IOException {
+ if(decodedKeyList != null)
+ {
+ // This control was created with a sort order string so encode using
+ // that.
+ writeValueFromString(writer);
+ }
+ else
+ {
+ // This control must have been created with a typed sort order object
+ // so encode using that.
+ writeValueFromSortOrder(writer);
+ }
+ }
/**
* Appends a string representation of this server-side sort request control
@@ -430,16 +380,160 @@
*
* @param buffer The buffer to which the information should be appended.
*/
+ @Override
public void toString(StringBuilder buffer)
{
buffer.append("ServerSideSortRequestControl(");
+ if(sortOrder == null)
+ {
+ buffer.append("SortOrder(");
- if (sortOrder != null)
+ if (decodedKeyList.size() > 0)
+ {
+ decodedKeyToString(decodedKeyList.get(0), buffer);
+
+ for (int i=1; i < decodedKeyList.size(); i++)
+ {
+ buffer.append(",");
+ decodedKeyToString(decodedKeyList.get(i), buffer);
+ }
+ }
+ buffer.append(")");
+ }
+ else
{
buffer.append(sortOrder);
}
+ buffer.append(")");
+ }
+
+ private void decodedKeyToString(String[] decodedKey, StringBuilder buffer)
+ {
+ buffer.append("SortKey(");
+ if (decodedKey[2] == null)
+ {
+ buffer.append("+");
+ }
+ else
+ {
+ buffer.append("-");
+ }
+ buffer.append(decodedKey[0]);
+
+ if (decodedKey[1] != null)
+ {
+ buffer.append(":");
+ buffer.append(decodedKey[1]);
+ }
buffer.append(")");
}
+
+ private SortOrder decodeSortOrderFromString() throws DirectoryException
+ {
+ ArrayList<SortKey> sortKeys = new ArrayList<SortKey>();
+ for(String[] decodedKey : decodedKeyList)
+ {
+ AttributeType attrType =
+ DirectoryServer.getAttributeType(decodedKey[0].toLowerCase(), false);
+ if (attrType == null)
+ {
+ Message message =
+ INFO_SORTREQ_CONTROL_UNDEFINED_ATTR.get(decodedKey[0]);
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message);
+ }
+
+ OrderingMatchingRule orderingRule = null;
+ if(decodedKey[1] != null)
+ {
+ orderingRule =
+ DirectoryServer.getOrderingMatchingRule(
+ decodedKey[1].toLowerCase());
+ if (orderingRule == null)
+ {
+ Message message =
+ INFO_SORTREQ_CONTROL_UNDEFINED_ORDERING_RULE.
+ get(decodedKey[1]);
+ throw new DirectoryException(ResultCode.PROTOCOL_ERROR,
+ message);
+ }
+ }
+
+ boolean ascending = true;
+ if(decodedKey[2] != null && decodedKey[2].equals("r"))
+ {
+ ascending = false;
+ }
+
+ if ((orderingRule == null) &&
+ (attrType.getOrderingMatchingRule() == null))
+ {
+ Message message =
+ INFO_SORTREQ_CONTROL_NO_ORDERING_RULE_FOR_ATTR.get(
+ decodedKey[0]);
+ throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
+ message);
+ }
+
+ sortKeys.add(new SortKey(attrType, ascending, orderingRule));
+ }
+
+ return new SortOrder(sortKeys.toArray(new SortKey[0]));
+ }
+
+ private void writeValueFromString(ASN1Writer writer) throws IOException
+ {
+ writer.writeStartSequence(UNIVERSAL_OCTET_STRING_TYPE);
+
+ writer.writeStartSequence();
+ for(String[] strs : decodedKeyList)
+ {
+ writer.writeStartSequence();
+ // Attr name will always be present
+ writer.writeOctetString(strs[0]);
+ // Rule ID might not be present
+ if(strs[1] != null)
+ {
+ writer.writeOctetString(TYPE_ORDERING_RULE_ID, strs[1]);
+ }
+ // Reverse if present
+ if(strs[2] != null)
+ {
+ writer.writeBoolean(TYPE_REVERSE_ORDER, true);
+ }
+ writer.writeEndSequence();
+ }
+ writer.writeEndSequence();
+
+ writer.writeEndSequence();
+ }
+
+ private void writeValueFromSortOrder(ASN1Writer writer) throws IOException
+ {
+ writer.writeStartSequence(UNIVERSAL_OCTET_STRING_TYPE);
+
+ writer.writeStartSequence();
+ for (SortKey sortKey : sortOrder.getSortKeys())
+ {
+ writer.writeStartSequence();
+ writer.writeOctetString(sortKey.getAttributeType().getNameOrOID());
+
+ if (sortKey.getOrderingRule() != null)
+ {
+ writer.writeOctetString(TYPE_ORDERING_RULE_ID,
+ sortKey.getOrderingRule().getNameOrOID());
+ }
+
+ if (! sortKey.ascending())
+ {
+ writer.writeBoolean(TYPE_REVERSE_ORDER, true);
+ }
+
+ writer.writeEndSequence();
+ }
+ writer.writeEndSequence();
+
+ writer.writeEndSequence();
+ }
}
--
Gitblit v1.10.0