Package com.day.ldap.controls

Source Code of com.day.ldap.controls.LDAPSortControl

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation.  Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package com.day.ldap.controls;

import java.io.*;
import com.day.ldap.LDAPControl;
import com.day.ldap.LDAPSortKey;
import com.day.ldap.client.JDAPBERTagDecoder;
import com.day.ldap.LDAPException;
import com.day.ldap.ber.stream.*;

/**
* Represents an LDAP v3 server control that specifies that you want
* the server to return sorted search results.  (The OID for this
* control is 1.2.840.113556.1.4.473.)
* <P>
*
* When constructing an <CODE>LDAPSortControl</CODE> object, you can
* specify the order in which you want the results sorted.
* You can also specify whether or not this control is critical
* to the search operation.
* <P>
*
* To specify the sort order, you construct an <CODE>LDAPSortKey</CODE>
* object and pass it to the <CODE>LDAPSortControl</CODE> constructor.
* The <CODE>LDAPSortKey</CODE> object represents a list of the attribute
* types used for sorting (a "sort key list").
* <P>
*
* You can include the control in a search request by constructing
* an <CODE>LDAPSearchConstraints</CODE> object and calling the
* <CODE>setServerControls</CODE> method.  You can then pass this
* <CODE>LDAPSearchConstraints</CODE> object to the <CODE>search</CODE>
* method of an <CODE>LDAPConnection</CODE> object.
* <P>
*
* For example:
* <PRE>
* ...
* LDAPConnection ld = new LDAPConnection();
* try {
*     // Connect to server.
*     ld.connect( 3, hostname, portnumber, "", "" );
*
*     // Create a sort key that specifies the sort order.
*     LDAPSortKey sortOrder = new LDAPSortKey( attrname );
*
*     // Create a "critical" server control using that sort key.
*     LDAPSortControl sortCtrl = new LDAPSortControl(sortOrder,true);
*
*     // Create search constraints to use that control.
*     LDAPSearchConstraints cons = new LDAPSearchConstraints();
*     cons.setServerControls( sortCtrl );
*
*     // Send the search request.
*     LDAPSearchResults res = ld.search( "o=Airius.com",
*        LDAPv3.SCOPE_SUB, "(cn=Barbara*)", null, false, cons );
*
*     ...
*
* </PRE>
*
* The LDAP server sends back a sort response control to indicate
* the result of the sorting operation. (The OID for this control
* is 1.2.840.113556.1.4.474.)
* <P>
*
* This control contains:
* <P>
*
* <UL>
* <LI>the result code from the sorting operation
* <LI>optionally, the first attribute type in the sort key list
* that resulted in an error (for example, if the attribute does
* not exist)
* </UL>
* <P>
*
* To retrieve the data from this control, use the <CODE>getResultCode</CODE>
* and <CODE>getFailedAttribute</CODE> methods.
* <P>
*
* The following table lists what kinds of results to expect from the
* LDAP server under different situations:
* <P>
*
* <TABLE BORDER=1 COLS=4>
* <TR VALIGN=BASELINE>
*     <TH>Does the Server Support the Sorting Control?</TH>
*     <TH>Is the Sorting Control Marked As Critical?</TH>
*     <TH>Other Conditions</TH>
*     <TH>Results from LDAP Server</TH>
* </TR>
* <TR VALIGN=BASELINE>
*     <TD ROWSPAN=2>
*     No
*     </TD>
*     <TD>
*     Yes
*     </TD>
*     <TD>
*     None
*     </TD>
*     <TD>
*     <UL>
*     <LI>The server does not send back any entries.
*     <LI>An LDAPException.UNAVAILABLE_CRITICAL_EXTENSION
*     exception is thrown.
*     </UL>
*     </TD>
* </TR>
* <TR VALIGN=BASELINE>
*     <TD>
*     No
*     </TD>
*     <TD>
*     None
*     </TD>
*     <TD>
*     <UL>
*     <LI>The server ignores the sorting control and
*     returns the entries unsorted.
*     </UL>
*     <P>
*     </TD>
* </TR>
* <TR VALIGN=BASELINE>
*     <TD ROWSPAN=4>
*     Yes
*     </TD>
*     <TD>
*     Yes
*     </TD>
*     <TD ROWSPAN=2>
*     The server cannot sort the results using the specified
*     sort key list.
*     </TD>
*     <TD>
*     <UL>
*     <LI>The server does not send back any entries.
*     <LI>An LDAPException.UNAVAILABLE_CRITICAL_EXTENSION
*     exception is thrown.
*     <LI>The server sends back the sorting response control, which
*     specifies the result code of the sort attempt and (optionally)
*     the attribute type that caused the error.
*     </UL>
*     </TD>
* </TR>
* <TR VALIGN=BASELINE>
*     <TD>
*     No
*     </TD>
*     <TD>
*     <UL>
*     <LI>The server returns the entries unsorted.
*     <LI>The server sends back the sorting response control, which
*     specifies the result code of the sort attempt and (optionally)
*     the attribute type that caused the error.
*     </UL>
*     </TD>
* </TR>
* <TR VALIGN=BASELINE>
*     <TD ROWSPAN=2>
*     N/A (could either be marked as critical or not)
*     </TD>
*     <TD>
*     The server successfully sorted the entries.
*     </TD>
*     <TD>
*     <UL>
*     <LI>The server sends back the sorted entries.
*     <LI>The server sends back the sorting response control, which
*     specifies the result code of the sort attempt
*     (LDAPException.SUCCESS).
*     </UL>
*     </TD>
* </TR>
* <TR VALIGN=BASELINE>
*     <TD>
*     The search itself failed (for any reason).
*     </TD>
*     <TD>
*     <UL>
*     <LI>The server sends back a result code for the search
*     operation.
*     <LI>The server does not send back the sorting response control.
*     </UL>
*     </TD>
* </TR>
* </TABLE>
* <P>
*
* @version 1.0
* @see com.day.ldap.LDAPSortKey
* @see com.day.ldap.LDAPControl
* @see com.day.ldap.LDAPConstraints
* @see com.day.ldap.LDAPSearchConstraints
* @see com.day.ldap.LDAPConstraints#setServerControls(LDAPControl)
*/
public class LDAPSortControl extends LDAPControl {
    public final static String SORTREQUEST  = "1.2.840.113556.1.4.473";
    public final static String SORTRESPONSE = "1.2.840.113556.1.4.474";

    // Response varibales
    private String m_failedAttribute = null;
    private int m_resultCode = 0;
   
    // Request variables
    private LDAPSortKey[] m_keys;

    /**
     * Constructs a sort response <CODE>LDAPSortControl</CODE> object.
     * This constructor is used by <CODE>LDAPControl.register</CODE> to
     * instantiate sort response controls.
     * <P>
     * To retrieve the result code of the sort operation, call
     * <CODE>getResultCode</CODE>.
     * <P>
     * To retrieve the attribute that caused the sort operation to fail, call
     * <CODE>getFailedAttribute</CODE>.
     * @param oid the oid for this control. This must be
     * <CODE>LDAPSortControl.SORTRESPONSE</CODE> or an <CODE>LDAPException</CODE>
     * is thrown.
     * @param critical <code>true</code> if this control is critical to the operation
     * @param value the value associated with this control
     * @exception com.day.ldap.LDAPException If oid is not
     * <CODE>LDAPSortControl.SORTRESPONSE</CODE>.
     * @exception java.io.IOException If value contains an invalid BER sequence.
     * @see com.day.ldap.LDAPControl#register
     */
    public LDAPSortControl( String oid, boolean critical, byte[] value )
        throws LDAPException, IOException {
  super( oid, critical, value );

  if ( !oid.equals( SORTRESPONSE )) {
      throw new LDAPException( "oid must be LDAPSortControl.SORTRESPONSE",
             LDAPException.PARAM_ERROR);
  }

        ByteArrayInputStream inStream = new ByteArrayInputStream( value );
        BERSequence ber = new BERSequence();
        JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
        int[] nRead = { 0 };

  /* A sequence */
  BERSequence seq = (BERSequence)BERElement.getElement(decoder, inStream,
                   nRead );
  /* First is result code */
  int m_resultCode = ((BEREnumerated)seq.elementAt( 0 )).getValue();
  /* Then, possibly an attribute that failed sorting */
  if(seq.size() == 1) {
      return;
  }
  /* If this is not an octet string, let there be an exception */
  BEROctetString t = (BEROctetString)seq.elementAt(1);
  try {
      m_failedAttribute = new String(t.getValue(), "UTF8");
  } catch (UnsupportedEncodingException e) {
  }

    }

    /**
     * @return the attribute that caused the sort operation to fail.
     */
    public String getFailedAttribute() {
  return m_failedAttribute;
    }

    /**
     * @return the result code from the search operation.
     */
    public int getResultCode() {
  return m_resultCode;
    }
   
    /**
     * Constructs an <CODE>LDAPSortControl</CODE> object with a single
     * sorting key.
     * @param key a single attribute by which to sort
     * @param critical <CODE>true</CODE> if the LDAP operation should be
     * discarded when the server does not support this control (in other
     * words, this control is critical to the LDAP operation)
     * @see com.day.ldap.LDAPControl
     * @see com.day.ldap.LDAPSortKey
     */
    public LDAPSortControl(LDAPSortKey key,
                           boolean critical) {
        super( SORTREQUEST, critical, null );
        LDAPSortKey[] keys = new LDAPSortKey[1];
        keys[0] = key;
        m_value = createSortSpecification( m_keys = keys );
       
    }

    /**
     * Constructs an <CODE>LDAPSortControl</CODE> object with an array of
     * sorting keys.
     * @param keys the attributes by which to sort
     * @param critical <CODE>true</CODE> if the LDAP operation should be
     * discarded when the server does not support this control (in other
     * words, this control is critical to the LDAP operation)
     * @see com.day.ldap.LDAPControl
     * @see com.day.ldap.LDAPSortKey
     */
    public LDAPSortControl(LDAPSortKey[] keys,
                           boolean critical) {
        super( SORTREQUEST, critical, null );
        m_value = createSortSpecification( m_keys = keys );
    }

    /**
     * Parses the sorting response control sent by the server and
     * retrieves the result code from the sorting operation and
     * the attribute that caused sorting to fail (if specified by
     * the server).
     * <P>
     *
     * You can get the controls returned by the server by using the
     * <CODE>getResponseControls</CODE> method of the
     * <CODE>LDAPConnection</CODE> class.
     * <P>
     *
     * This method returns the attribute that caused the sort operation
     * to fail (or null, if the server did not specify any attribute).
     * The result code of the sorting operation is returned in the
     * <CODE>results</CODE> argument.  This argument is an array of
     * integers; the result code is specified in the first element of
     * this array.
     * <P>
     *
     * For example:
     * <PRE>
     * ...
     * LDAPConnection ld = new LDAPConnection();
     * try {
     *     // Connect to the server, set up the sorting control,
     *     // and set up the search constraints.
     *     ...
     *
     *     // Search the directory.
     *     LDAPSearchResults res = ld.search( "o=Airius.com",
     *         LDAPv3.SCOPE_SUB, "(cn=Barbara*)", attrs, false, cons );
     *
     *     // Determine if the server sent a control back to you.
     *     LDAPControl[] returnedControls = ld.getResponseControls();
     *     if ( returnedControls != null ) {
     *         int[] resultCodes = new int[1];
     *         String failedAttr = LDAPSortControl.parseResponse(
     *             returnedControls, resultCodes );
     *
     *         // Check if the result code indicated an error occurred.
     *         if ( resultCodes[0] != 0 ) {
     *             System.out.println( "Result code: " + resultCodes[0] );
     *             if ( failedAttr != null ) {
     *                 System.out.println( "Sorting operation failed on " +
     *                     failedAttr );
     *             } else {
     *                 System.out.println( "Server did not indicate which " +
     *                     "attribute caused sorting to fail." );
     *             }
     *         }
     *     }
     *     ...
     * }
     * ...
     *
     * </PRE>
     *
     * The following table lists some of the possible result codes
     * for the sorting operation.
     * <P>
     *
     * <TABLE BORDER=1 COLS=2>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.SUCCESS</CODE>
     *     </TD>
     *     <TD>
     *     The server successfully sorted the results.
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.OPERATION_ERROR</CODE>
     *     </TD>
     *     <TD>
     *     An internal server error occurred.
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.TIME_LIMIT_EXCEEDED</CODE>
     *     </TD>
     *     <TD>
     *     The maximum time allowed for a search was exceeded
     *     before the server finished sorting the results.
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.STRONG_AUTH_REQUIRED</CODE>
     *     </TD>
     *     <TD>
     *     The server refused to send back the sorted search
     *     results because it requires you to use a stronger
     *     authentication method.
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.ADMIN_LIMIT_EXCEEDED</CODE>
     *     </TD>
     *     <TD>
     *     There are too many entries for the server to sort.
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.NO_SUCH_ATTRIBUTE</CODE>
     *     </TD>
     *     <TD>
     *     The sort key list specifies an attribute that does not exist.
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.INAPPROPRIATE_MATCHING</CODE>
     *     </TD>
     *     <TD>
     *     The sort key list specifies a matching rule that is
     *     not recognized or appropriate
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.INSUFFICIENT_ACCESS_RIGHTS</CODE>
     *     </TD>
     *     <TD>
     *     The server did not send the sorted results because the
     *     client has insufficient access rights.
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.BUSY</CODE>
     *     </TD>
     *     <TD>
     *     The server is too busy to sort the results.
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.UNWILLING_TO_PERFORM</CODE>
     *     </TD>
     *     <TD>
     *     The server is unable to sort the results.
     *     </TD>
     * </TR>
     * <TR VALIGN=BASELINE>
     *     <TD>
     *     <CODE>LDAPException.OTHER</CODE>
     *     </TD>
     *     <TD>
     *     This general result code indicates that the server
     *     failed to sort the results for a reason other than
     *     the ones listed above.
     *     </TD>
     * </TR>
     * </TABLE>
     * <P>
     *
     * @param controls an array of <CODE>LDAPControl</CODE> objects,
     * representing the controls returned by the server
     * after a search. To get these controls, use the
     * <CODE>getResponseControls</CODE> method of the
     * <CODE>LDAPConnection</CODE> class.
     * @param results an array of integers.  The first element of this array
     * specifies the result code of the sorting operation.
     * @return the attribute that caused the error, or null if the server did
     * not specify which attribute caused the error.
     * @see com.day.ldap.LDAPConnection#getResponseControls
     * @deprecated LDAPSortControl response controls are now automatically
     * instantiated.
     */
    public static String parseResponse( LDAPControl[] controls, int[] results ) {
        String attr = null;
        LDAPControl sort = null;
        /* See if there is a sort control in the array */
        for( int i = 0; (controls != null) && (i < controls.length); i++ ) {
            if ( controls[i].getID().equals( SORTRESPONSE ) ) {
                sort = controls[i];
                break;
            }
        }
        if ( sort != null ) {
            /* Suck out the data and return it */
            ByteArrayInputStream inStream =
                new ByteArrayInputStream( sort.getValue() );
            BERSequence ber = new BERSequence();
            JDAPBERTagDecoder decoder = new JDAPBERTagDecoder();
            int[] nRead = new int[1];
            nRead[0] = 0;
            try  {
                /* A sequence */
                BERSequence seq = (BERSequence)BERElement.getElement(
                                                     decoder, inStream,
                                                     nRead );
                /* First is result code */
                int result = ((BEREnumerated)seq.elementAt( 0 )).getValue();
                if ( (results != null) && (results.length > 0) )
                    results[0] = result;
                /* Then, possibly an attribute that failed sorting */
                /* If this is not an octet string, let there be an exception */
                BEROctetString t = (BEROctetString)seq.elementAt(1);
                attr = new String(t.getValue(), "UTF8");
            } catch(Exception x) {
            }
        }
        return attr;
    }

    /**
     * Create a "flattened" BER encoding of the requested sort keys,
     * and return it as a byte array.
     * @param keys the attributes by which to sort
     * @return the byte array of encoded data.
     */
    private byte[] createSortSpecification( LDAPSortKey[] keys ) {
        /* A sequence of sequences */
        BERSequence ber = new BERSequence();
        /* Add each sort key as a sequence */
        for( int i = 0; i < keys.length; i++ ) {
            BERSequence seq = new BERSequence();
            /* The attribute name */
            seq.addElement(new BEROctetString(keys[i].getKey()));
            /* Optional matching rule */
            if ( keys[i].getMatchRule() != null )
                seq.addElement(new BERTag(
                    BERTag.CONTEXT|0,
                    new BEROctetString(keys[i].getMatchRule()),
                    true));
            /* Optional reverse-order sort */
            if ( keys[i].getReverse() )
                seq.addElement(new BERTag(
                    BERTag.CONTEXT|1,
                    new BEREnumerated(LDAPSortKey.REVERSE),
                    true));
            ber.addElement( seq );
        }
        /* Suck out the data and return it */
        return flattenBER( ber );
    }
   
    public String toString() {
        return (getID() == SORTREQUEST) ? reqToString() : rspToString();
    }
   
    String reqToString() {
       
        StringBuffer sb = new StringBuffer("{SortCtrl:");
       
        sb.append(" isCritical=");
        sb.append(isCritical());
       
        sb.append(" ");
        for (int i=0; i < m_keys.length; i++) {
            sb.append(m_keys[i]);
        }           
       
        sb.append("}");

        return sb.toString();
    }

    String rspToString() {
       
        StringBuffer sb = new StringBuffer("{SortResponseCtrl:");
       
        sb.append(" isCritical=");
        sb.append(isCritical());
       
        if (m_failedAttribute != null) {
            sb.append(" failedAttr=");
            sb.append(m_failedAttribute);
        }
       
        sb.append(" resultCode=");
        sb.append(m_resultCode);

        sb.append("}");

        return sb.toString();
    }
}
TOP

Related Classes of com.day.ldap.controls.LDAPSortControl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.