| | |
| | | |
| | | 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.*; |
| | |
| | | |
| | | /** |
| | | * 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 { |
| | |
| | | * </PRE> |
| | | */ |
| | | public class ServerSideSortRequestControl |
| | | extends Control |
| | | extends Control |
| | | { |
| | | /** |
| | | * The BER type to use when encoding the orderingRule element. |
| | |
| | | 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(); |
| | |
| | | |
| | | 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) |
| | |
| | | |
| | | 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 |
| | |
| | | * |
| | | * @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(); |
| | | } |
| | | } |
| | | |