mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

matthew_swift
11.45.2009 2bc8d15a28fafab97cefafede06d6b7e738ae0fe
Various incremental improvements.
2 files copied
1 files deleted
4 files added
3 files renamed
39 files modified
5924 ■■■■ changed files
sdk/src/com/sun/opends/sdk/ldap/LDAPConnection.java 13 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/messages/messages.properties 4 ●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Collections2.java 225 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Functions.java 55 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/ResultChain.java 315 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/ResultTransformer.java 202 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractAsynchronousConnection.java 315 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractConnection.java 233 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractFilterVisitor.java 16 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AsynchronousConnection.java 271 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java 74 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/CancelledResultException.java 13 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Connection.java 570 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ConnectionPool.java 551 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/EntryNotFoundException.java 15 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ErrorResultException.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Filter.java 293 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/FilterVisitor.java 16 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java 448 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Matcher.java 219 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/MultipleEntriesFoundException.java 11 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ResultCode.java 31 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ResultFuture.java 27 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ResultHandler.java 8 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/RootDSE.java 802 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/SynchronousConnection.java 23 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/TimeoutResultException.java 4 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/MatchedValuesControl.java 4 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldap/LDAPUtils.java 35 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AbstractMatchingRuleImpl.java 2 ●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AbstractSubstringMatchingRuleImpl.java 2 ●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AttributeType.java 25 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CoreSchema.java 2 ●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CoreSchemaImpl.java 60 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/GenerateCoreSchema.java 10 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/MatchingRule.java 2 ●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/MatchingRuleImpl.java 2 ●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/Schema.java 434 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SchemaBuilder.java 444 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SchemaNotFoundException.java 94 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTest.java 2 ●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTest.java 3 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTest.java 3 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/ApproximateMatchingRuleTest.java 3 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/EnumSyntaxTestCase.java 3 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleTest.java 3 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OrderingMatchingRuleTest.java 3 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstringMatchingRuleTest.java 5 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SyntaxTestCase.java 3 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPConnection.java
@@ -69,7 +69,8 @@
 * <p>
 * TODO: handle illegal state exceptions.
 */
public final class LDAPConnection implements AsynchronousConnection
public final class LDAPConnection extends
    AbstractAsynchronousConnection implements AsynchronousConnection
{
  private final class LDAPMessageHandlerImpl extends
@@ -919,16 +920,6 @@
  }
  /**
   * {@inheritDoc}
   */
  public void close()
  {
    close(Requests.newUnbindRequest(), null);
  }
  /**
   * {@inheritDoc}
   */
sdk/src/com/sun/opends/sdk/messages/messages.properties
@@ -1240,7 +1240,7 @@
INFO_RESULT_CLIENT_SIDE_NOT_SUPPORTED=Operation Not Supported
INFO_RESULT_CLIENT_SIDE_CONTROL_NOT_FOUND=Control Not Found
INFO_RESULT_CLIENT_SIDE_NO_RESULTS_RETURNED=No Results Returned
INFO_RESULT_CLIENT_SIDE_MORE_RESULTS_TO_RETURN=More Results to Return
INFO_RESULT_CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED=Unexpected Results Returned
INFO_RESULT_CLIENT_SIDE_CLIENT_LOOP=Referral Loop Detected
INFO_RESULT_CLIENT_SIDE_REFERRAL_LIMIT_EXCEEDED=Referral Hop Limit Exceeded
INFO_RESULT_AUTHORIZATION_DENIED=Authorization Denied
@@ -2644,6 +2644,8 @@
 decode the control value:  %s
MILD_ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED=Cannot encode the end of the ASN.1 \
 sequence or set because the start of the sequence was not written
MILD_ERR_NO_SEARCH_RESULT_ENTRIES=The search request succeeded \
 but did not return any search result entries when one was expected
MILD_ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES=The search request succeeded \
 but returned %d search result entry when only one was expected
MILD_ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES=The search request succeeded \
sdk/src/com/sun/opends/sdk/util/Collections2.java
New file
@@ -0,0 +1,225 @@
/*
 * 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 2009 Sun Microsystems, Inc.
 */
package com.sun.opends.sdk.util;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
/**
 * Additional {@code Collection} based utility methods.
 */
public final class Collections2
{
  private static final class TransformedCollection<M, N, P> extends
      AbstractCollection<N> implements Collection<N>
  {
    private final Collection<M> collection;
    private final Function<? super M, ? extends N, P> funcMtoN;
    private final Function<? super N, ? extends M, P> funcNtoM;
    private final P p;
    private TransformedCollection(Collection<M> collection,
        Function<? super M, ? extends N, P> funcMtoN,
        Function<? super N, ? extends M, P> funcNtoM, P p)
    {
      this.collection = collection;
      this.funcMtoN = funcMtoN;
      this.funcNtoM = funcNtoM;
      this.p = p;
    }
    /**
     * {@inheritDoc}
     */
    public boolean add(N e)
    {
      return collection.add(funcNtoM.apply(e, p));
    }
    /**
     * {@inheritDoc}
     */
    public void clear()
    {
      collection.clear();
    }
    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public boolean contains(Object o)
    {
      N tmp = (N) o;
      return collection.contains(funcNtoM.apply(tmp, p));
    }
    /**
     * {@inheritDoc}
     */
    public boolean isEmpty()
    {
      return collection.isEmpty();
    }
    /**
     * {@inheritDoc}
     */
    public Iterator<N> iterator()
    {
      return Iterators.transform(collection.iterator(), funcMtoN, p);
    }
    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public boolean remove(Object o)
    {
      N tmp = (N) o;
      return collection.remove(funcNtoM.apply(tmp, p));
    }
    /**
     * {@inheritDoc}
     */
    public int size()
    {
      return collection.size();
    }
  }
  /**
   * Returns a view of {@code collection} whose values have been mapped
   * to elements of type {@code N} using {@code funcMtoN}. The returned
   * collection supports all operations.
   *
   * @param <M>
   *          The type of elements contained in {@code collection}.
   * @param <N>
   *          The type of elements contained in the returned collection.
   * @param <P>
   *          The type of the additional parameter to the function's
   *          {@code apply} method. Use {@link java.lang.Void} for
   *          functions that do not need an additional parameter.
   * @param collection
   *          The collection to be transformed.
   * @param funcMtoN
   *          A function which maps values of type {@code M} to values
   *          of type {@code N}. This function will be used when
   *          retrieving values from {@code collection}.
   * @param funcNtoM
   *          A function which maps values of type {@code N} to values
   *          of type {@code M}. This function will be used when
   *          performing queries and adding values to {@code collection}
   *          .
   * @param p
   *          A predicate specified parameter.
   * @return A view of {@code collection} whose values have been mapped
   *         to elements of type {@code N} using {@code funcMtoN}.
   */
  public static <M, N, P> Collection<N> transform(
      Collection<M> collection,
      Function<? super M, ? extends N, P> funcMtoN,
      Function<? super N, ? extends M, P> funcNtoM, P p)
  {
    return new TransformedCollection<M, N, P>(collection, funcMtoN,
        funcNtoM, p);
  }
  /**
   * Returns a view of {@code collection} whose values have been mapped
   * to elements of type {@code N} using {@code funcMtoN}. The returned
   * collection supports all operations.
   *
   * @param <M>
   *          The type of elements contained in {@code collection}.
   * @param <N>
   *          The type of elements contained in the returned collection.
   * @param collection
   *          The collection to be transformed.
   * @param funcMtoN
   *          A function which maps values of type {@code M} to values
   *          of type {@code N}. This function will be used when
   *          retrieving values from {@code collection}.
   * @param funcNtoM
   *          A function which maps values of type {@code N} to values
   *          of type {@code M}. This function will be used when
   *          performing queries and adding values to {@code collection}
   *          .
   * @return A view of {@code collection} whose values have been mapped
   *         to elements of type {@code N} using {@code funcMtoN}.
   */
  public static <M, N> Collection<N> transform(
      Collection<M> collection,
      Function<? super M, ? extends N, Void> funcMtoN,
      Function<? super N, ? extends M, Void> funcNtoM)
  {
    return new TransformedCollection<M, N, Void>(collection, funcMtoN,
        funcNtoM, null);
  }
  // Prevent instantiation
  private Collections2()
  {
    // Do nothing.
  }
}
sdk/src/com/sun/opends/sdk/util/Functions.java
@@ -46,6 +46,7 @@
      Function<M, N, Void>
  {
    private final Function<M, N, P> function;
    private final P parameter;
@@ -68,8 +69,9 @@
  }
  private static final Function<ByteString, AttributeDescription, Schema> BYTESTRING_TO_ATTRIBUTE_DESCRIPTION =
      new Function<ByteString, AttributeDescription, Schema>()
  private static final Function<ByteString, AttributeDescription, Schema> BYTESTRING_TO_ATTRIBUTE_DESCRIPTION = new Function<ByteString, AttributeDescription, Schema>()
      {
        public AttributeDescription apply(ByteString value, Schema p)
@@ -79,23 +81,20 @@
        }
      };
  private static final Function<ByteString, Boolean, Void> BYTESTRING_TO_BOOLEAN =
      new Function<ByteString, Boolean, Void>()
  private static final Function<ByteString, Boolean, Void> BYTESTRING_TO_BOOLEAN = new Function<ByteString, Boolean, Void>()
      {
        public Boolean apply(ByteString value, Void p)
        {
          String valueString =
              StaticUtils.toLowerCase(value.toString());
      String valueString = StaticUtils.toLowerCase(value.toString());
          if (valueString.equals("true") || valueString.equals("yes")
              || valueString.equals("on") || valueString.equals("1"))
          {
            return Boolean.TRUE;
          }
          else if (valueString.equals("false")
              || valueString.equals("no") || valueString.equals("off")
              || valueString.equals("0"))
      else if (valueString.equals("false") || valueString.equals("no")
          || valueString.equals("off") || valueString.equals("0"))
          {
            return Boolean.FALSE;
          }
@@ -107,8 +106,7 @@
        }
      };
  private static final Function<ByteString, DN, Schema> BYTESTRING_TO_DN =
      new Function<ByteString, DN, Schema>()
  private static final Function<ByteString, DN, Schema> BYTESTRING_TO_DN = new Function<ByteString, DN, Schema>()
      {
        public DN apply(ByteString value, Schema p)
@@ -120,8 +118,7 @@
        }
      };
  private static final Function<ByteString, Integer, Void> BYTESTRING_TO_INTEGER =
      new Function<ByteString, Integer, Void>()
  private static final Function<ByteString, Integer, Void> BYTESTRING_TO_INTEGER = new Function<ByteString, Integer, Void>()
      {
        public Integer apply(ByteString value, Void p)
@@ -131,8 +128,7 @@
        }
      };
  private static final Function<ByteString, Long, Void> BYTESTRING_TO_LONG =
      new Function<ByteString, Long, Void>()
  private static final Function<ByteString, Long, Void> BYTESTRING_TO_LONG = new Function<ByteString, Long, Void>()
      {
        public Long apply(ByteString value, Void p)
@@ -142,8 +138,7 @@
        }
      };
  private static final Function<ByteString, String, Void> BYTESTRING_TO_STRING =
      new Function<ByteString, String, Void>()
  private static final Function<ByteString, String, Void> BYTESTRING_TO_STRING = new Function<ByteString, String, Void>()
      {
        public String apply(ByteString value, Void p)
@@ -152,8 +147,16 @@
        }
      };
  private static final Function<String, String, Void> NORMALIZE_STRING =
      new Function<String, String, Void>()
  private static final Function<Object, ByteString, Void> OBJECT_TO_BYTESTRING = new Function<Object, ByteString, Void>()
  {
    public ByteString apply(Object value, Void p)
    {
      return ByteString.valueOf(value);
    }
  };
  private static final Function<String, String, Void> NORMALIZE_STRING = new Function<String, String, Void>()
      {
        public String apply(String value, Void p)
@@ -337,6 +340,20 @@
  /**
   * Returns a function which converts an {@code Object} to a {@code
   * ByteString} using the {@link ByteString#valueOf(Object)} method.
   *
   * @return A function which converts an {@code Object} to a {@code
   *         ByteString}.
   */
  public static Function<Object, ByteString, Void> objectToByteString()
  {
    return OBJECT_TO_BYTESTRING;
  }
  // Prevent instantiation
  private Functions()
  {
sdk/src/com/sun/opends/sdk/util/ResultChain.java
New file
@@ -0,0 +1,315 @@
/*
 * 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 2009 Sun Microsystems, Inc.
 */
package com.sun.opends.sdk.util;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.opends.sdk.ErrorResultException;
import org.opends.sdk.ResultFuture;
import org.opends.sdk.ResultHandler;
/**
 * A base class which can be used to transform the result of an inner
 * asynchronous request to another result type.
 * <p>
 * FIXME: I don't think that this is right. There's too much locking for
 * a start.
 *
 * @param <M>
 *          The type of the inner result.
 * @param <N>
 *          The type of the outer result.
 * @param <P>
 *          The type of the additional parameter to the handler's
 *          methods.
 */
public abstract class ResultChain<M, N, P> implements ResultFuture<N>,
    ResultHandler<M, P>
{
  private ErrorResultException errorResult;
  private final ResultHandler<? super N, P> handler;
  private final Object stateLock = new Object();
  private final CountDownLatch latch = new CountDownLatch(1);
  private ResultFuture<N> outerFuture = null;
  private boolean cancelled = false;
  private volatile ResultFuture<M> innerFuture = null;
  /**
   * Creates a new asynchronous result chain which will chain an outer
   * asynchronous request once the inner asynchronous request completes.
   *
   * @param handler
   *          The outer result handler.
   */
  protected ResultChain(ResultHandler<? super N, P> handler)
  {
    this.handler = handler;
  }
  /**
   * {@inheritDoc}
   */
  public boolean cancel(boolean mayInterruptIfRunning)
  {
    synchronized (stateLock)
    {
      if (!isDone())
      {
        cancelled = true;
        innerFuture.cancel(mayInterruptIfRunning);
        if (outerFuture != null)
        {
          outerFuture.cancel(mayInterruptIfRunning);
        }
        latch.countDown();
        return true;
      }
      else
      {
        return false;
      }
    }
  }
  /**
   * {@inheritDoc}
   */
  public N get() throws ErrorResultException, CancellationException,
      InterruptedException
  {
    latch.await();
    return get0();
  }
  /**
   * {@inheritDoc}
   */
  public N get(long timeout, TimeUnit unit)
      throws ErrorResultException, TimeoutException,
      CancellationException, InterruptedException
  {
    if (!latch.await(timeout, unit))
    {
      throw new TimeoutException();
    }
    return get0();
  }
  /**
   * {@inheritDoc}
   */
  public int getMessageID()
  {
    // Best effort.
    synchronized (stateLock)
    {
      if (outerFuture != null)
      {
        return outerFuture.getMessageID();
      }
      else
      {
        return innerFuture.getMessageID();
      }
    }
  }
  /**
   * {@inheritDoc}
   */
  public void handleErrorResult(P p, ErrorResultException error)
  {
    synchronized (stateLock)
    {
      try
      {
        outerFuture = chainErrorResult(error, handler);
      }
      catch (ErrorResultException e)
      {
        errorResult = e;
        if (handler != null)
        {
          handler.handleErrorResult(p, errorResult);
        }
        latch.countDown();
      }
    }
  }
  /**
   * {@inheritDoc}
   */
  public void handleResult(P p, M result)
  {
    synchronized (stateLock)
    {
      try
      {
        outerFuture = chainResult(result, handler);
      }
      catch (ErrorResultException e)
      {
        errorResult = e;
        if (handler != null)
        {
          handler.handleErrorResult(p, errorResult);
        }
        latch.countDown();
      }
    }
  }
  /**
   * {@inheritDoc}
   */
  public boolean isCancelled()
  {
    return isDone() && cancelled;
  }
  /**
   * {@inheritDoc}
   */
  public boolean isDone()
  {
    return latch.getCount() == 0;
  }
  /**
   * Sets the inner future for this result chain. This must be done
   * before this future is published.
   *
   * @param future
   *          The inner future.
   */
  public final void setInnerResultFuture(ResultFuture<M> future)
  {
    innerFuture = future;
  }
  private N get0() throws ErrorResultException, CancellationException,
      InterruptedException
  {
    synchronized (stateLock)
    {
      if (cancelled)
      {
        throw new CancellationException();
      }
      if (errorResult != null)
      {
        throw errorResult;
      }
      return outerFuture.get();
    }
  }
  /**
   * Invokes the outer request based on the error result of the inner
   * request and returns a future representing the result of the outer
   * request.
   * <p>
   * The default implementation is to terminate further processing by
   * re-throwing the inner error result.
   *
   * @param innerError
   *          The error result of the inner request.
   * @param handler
   *          The result handler to be used for the outer request.
   * @return A future representing the result of the outer request.
   * @throws ErrorResultException
   *           If the outer request could not be invoked and processing
   *           should terminate.
   */
  protected ResultFuture<N> chainErrorResult(
      ErrorResultException innerError,
      ResultHandler<? super N, P> handler) throws ErrorResultException
  {
    throw innerError;
  }
  /**
   * Invokes the outer request based on the result of the inner request
   * and returns a future representing the result of the outer request.
   *
   * @param innerResult
   *          The result of the inner request.
   * @param handler
   *          The result handler to be used for the outer request.
   * @return A future representing the result of the outer request.
   * @throws ErrorResultException
   *           If the outer request could not be invoked and processing
   *           should terminate.
   */
  protected abstract ResultFuture<N> chainResult(M innerResult,
      ResultHandler<? super N, P> handler) throws ErrorResultException;
}
sdk/src/com/sun/opends/sdk/util/ResultTransformer.java
New file
@@ -0,0 +1,202 @@
/*
 * 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 2009 Sun Microsystems, Inc.
 */
package com.sun.opends.sdk.util;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.opends.sdk.ErrorResultException;
import org.opends.sdk.ResultFuture;
import org.opends.sdk.ResultHandler;
/**
 * A base class which can be used to transform the result of an inner
 * asynchronous request to another result type.
 *
 * @param <M>
 *          The type of the inner result.
 * @param <N>
 *          The type of the outer result.
 * @param <P>
 *          The type of the additional parameter to the handler's
 *          methods.
 */
public abstract class ResultTransformer<M, N, P> implements
    ResultFuture<N>, ResultHandler<M, P>
{
  private final ResultHandler<? super N, P> handler;
  private volatile ResultFuture<M> future = null;
  /**
   * Sets the inner future for this result transformer. This must be
   * done before this future is published.
   *
   * @param future
   *          The inner future.
   */
  public final void setResultFuture(ResultFuture<M> future)
  {
    this.future = future;
  }
  /**
   * Transforms the inner result to an outer result, possibly throwing
   * an {@code ErrorResultException} if the transformation fails for
   * some reason.
   *
   * @param result
   *          The inner result.
   * @return The outer result.
   * @throws ErrorResultException
   *           If the transformation fails for some reason.
   */
  protected abstract N transformResult(M result)
      throws ErrorResultException;
  /**
   * Creates a new result transformer which will transform the results
   * of an inner asynchronous request.
   *
   * @param handler
   *          The outer result handler.
   */
  protected ResultTransformer(ResultHandler<? super N, P> handler)
  {
    this.handler = handler;
  }
  /**
   * {@inheritDoc}
   */
  public final void handleErrorResult(P p, ErrorResultException error)
  {
    if (handler != null)
    {
      handler.handleErrorResult(p, error);
    }
  }
  /**
   * {@inheritDoc}
   */
  public final void handleResult(P p, M result)
  {
    if (handler != null)
    {
      try
      {
        handler.handleResult(p, transformResult(result));
      }
      catch (ErrorResultException e)
      {
        handler.handleErrorResult(p, e);
      }
    }
  }
  /**
   * {@inheritDoc}
   */
  public final boolean cancel(boolean mayInterruptIfRunning)
  {
    return future.cancel(mayInterruptIfRunning);
  }
  /**
   * {@inheritDoc}
   */
  public final N get() throws ErrorResultException,
      CancellationException, InterruptedException
  {
    return transformResult(future.get());
  }
  /**
   * {@inheritDoc}
   */
  public final N get(long timeout, TimeUnit unit)
      throws ErrorResultException, TimeoutException,
      CancellationException, InterruptedException
  {
    return transformResult(future.get(timeout, unit));
  }
  /**
   * {@inheritDoc}
   */
  public final int getMessageID()
  {
    return future.getMessageID();
  }
  /**
   * {@inheritDoc}
   */
  public final boolean isCancelled()
  {
    return future.isCancelled();
  }
  /**
   * {@inheritDoc}
   */
  public final boolean isDone()
  {
    return future.isDone();
  }
}
sdk/src/org/opends/sdk/AbstractAsynchronousConnection.java
New file
@@ -0,0 +1,315 @@
/*
 * 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 2009 Sun Microsystems, Inc.
 */
package org.opends.sdk;
import static com.sun.opends.sdk.messages.Messages.*;
import java.util.Collection;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.opends.sdk.requests.Requests;
import org.opends.sdk.requests.SearchRequest;
import org.opends.sdk.responses.Responses;
import org.opends.sdk.responses.Result;
import org.opends.sdk.responses.SearchResultEntry;
import org.opends.sdk.responses.SearchResultReference;
import org.opends.sdk.schema.Schema;
/**
 * This class provides a skeletal implementation of the {@code
 * AsynchronousConnection} interface, to minimize the effort required to
 * implement this interface.
 */
public abstract class AbstractAsynchronousConnection implements
    AsynchronousConnection
{
  private static final class SingleEntryFuture<P> implements
      ResultFuture<SearchResultEntry>, ResultHandler<Result, P>,
      SearchResultHandler<P>
  {
    private final ResultHandler<? super SearchResultEntry, P> handler;
    private volatile SearchResultEntry firstEntry = null;
    private volatile SearchResultReference firstReference = null;
    private volatile int entryCount = 0;
    private volatile ResultFuture<Result> future = null;
    private SingleEntryFuture(
        ResultHandler<? super SearchResultEntry, P> handler)
    {
      this.handler = handler;
    }
    public boolean cancel(boolean mayInterruptIfRunning)
    {
      return future.cancel(mayInterruptIfRunning);
    }
    public SearchResultEntry get() throws ErrorResultException,
        CancellationException, InterruptedException
    {
      future.get();
      return get0();
    }
    public SearchResultEntry get(long timeout, TimeUnit unit)
        throws ErrorResultException, TimeoutException,
        CancellationException, InterruptedException
    {
      future.get(timeout, unit);
      return get0();
    }
    private SearchResultEntry get0() throws ErrorResultException
    {
      if (entryCount == 0)
      {
        // Did not find any entries.
        Result result = Responses.newResult(
            ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
            .setDiagnosticMessage(
                ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
        throw ErrorResultException.wrap(result);
      }
      else if (entryCount > 1)
      {
        // Got more entries than expected.
        Result result = Responses.newResult(
            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
            .setDiagnosticMessage(
                ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(entryCount)
                    .toString());
        throw ErrorResultException.wrap(result);
      }
      else if (firstReference != null)
      {
        // Got an unexpected search result reference.
        Result result = Responses.newResult(
            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
            .setDiagnosticMessage(
                ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
                    firstReference.getURIs().iterator().next())
                    .toString());
        throw ErrorResultException.wrap(result);
      }
      else
      {
        return firstEntry;
      }
    }
    public int getMessageID()
    {
      return future.getMessageID();
    }
    public void handleEntry(P p, SearchResultEntry entry)
    {
      if (firstEntry == null)
      {
        firstEntry = entry;
      }
      entryCount++;
    }
    public void handleErrorResult(P p, ErrorResultException error)
    {
      if (handler != null)
      {
        handler.handleErrorResult(p, error);
      }
    }
    public void handleReference(P p, SearchResultReference reference)
    {
      if (firstReference == null)
      {
        firstReference = reference;
      }
    }
    public void handleResult(P p, Result result)
    {
      if (handler != null)
      {
        try
        {
          handler.handleResult(p, get0());
        }
        catch (ErrorResultException e)
        {
          handler.handleErrorResult(p, e);
        }
      }
    }
    public boolean isCancelled()
    {
      return future.isCancelled();
    }
    public boolean isDone()
    {
      return future.isDone();
    }
    private void setResultFuture(ResultFuture<Result> future)
    {
      this.future = future;
    }
  }
  /**
   * Creates a new abstract connection.
   */
  protected AbstractAsynchronousConnection()
  {
    // No implementation required.
  }
  /**
   * {@inheritDoc}
   */
  public void close()
  {
    close(Requests.newUnbindRequest(), null);
  }
  /**
   * {@inheritDoc}
   */
  public <P> ResultFuture<SearchResultEntry> readEntry(DN name,
      Collection<String> attributeDescriptions,
      ResultHandler<? super SearchResultEntry, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    SearchRequest request = Requests.newSearchRequest(name,
        SearchScope.BASE_OBJECT, Filter.getObjectClassPresentFilter())
        .addAttribute(attributeDescriptions);
    return searchSingleEntry(request, handler, p);
  }
  /**
   * {@inheritDoc}
   */
  public <P> ResultFuture<RootDSE> readRootDSE(
      ResultHandler<RootDSE, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException
  {
    return RootDSE.readRootDSE(this, handler, p);
  }
  /**
   * {@inheritDoc}
   */
  public <P> ResultFuture<Schema> readSchema(DN name,
      ResultHandler<Schema, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException
  {
    return Schema.readSchema(this, name, handler, p);
  }
  /**
   * {@inheritDoc}
   */
  public <P> ResultFuture<Schema> readSchemaForEntry(DN name,
      ResultHandler<Schema, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException
  {
    return Schema.readSchema(this, name, handler, p);
  }
  /**
   * {@inheritDoc}
   */
  public <P> ResultFuture<SearchResultEntry> searchSingleEntry(
      SearchRequest request,
      ResultHandler<? super SearchResultEntry, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final SingleEntryFuture<P> innerFuture = new SingleEntryFuture<P>(
        handler);
    final ResultFuture<Result> future = search(request, innerFuture,
        innerFuture, p);
    innerFuture.setResultFuture(future);
    return innerFuture;
  }
}
sdk/src/org/opends/sdk/AbstractConnection.java
@@ -38,6 +38,7 @@
import org.opends.sdk.requests.Requests;
import org.opends.sdk.requests.SearchRequest;
import org.opends.sdk.responses.*;
import org.opends.sdk.schema.Schema;
import com.sun.opends.sdk.util.Validator;
@@ -51,35 +52,14 @@
public abstract class AbstractConnection implements Connection
{
  /**
   * Creates a new abstract connection.
   */
  protected AbstractConnection()
  {
    // No implementation required.
  }
  private static final class SingleEntryHandler implements
      SearchResultHandler<Void>
  {
    // FIXME: does this need to be thread safe?
    private SearchResultEntry firstEntry = null;
    private volatile SearchResultEntry firstEntry = null;
    private SearchResultReference firstReference = null;
    private volatile SearchResultReference firstReference = null;
    private int entryCount = 0;
    public void handleReference(Void p, SearchResultReference reference)
    {
      if (firstReference == null)
      {
        firstReference = reference;
      }
    }
    private volatile int entryCount = 0;
@@ -92,6 +72,26 @@
      entryCount++;
    }
    public void handleReference(Void p, SearchResultReference reference)
    {
      if (firstReference == null)
      {
        firstReference = reference;
      }
    }
  }
  /**
   * Creates a new abstract connection.
   */
  protected AbstractConnection()
  {
    // No implementation required.
  }
@@ -178,37 +178,99 @@
  public Result search(SearchRequest request,
      final Collection<? super SearchResultEntry> entries,
      final Collection<? super SearchResultReference> references)
      throws ErrorResultException, InterruptedException,
  public SearchResultEntry readEntry(DN baseObject,
      String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    SearchRequest request = Requests.newSearchRequest(baseObject,
        SearchScope.BASE_OBJECT, Filter.getObjectClassPresentFilter(),
        attributeDescriptions);
    return searchSingleEntry(request);
  }
  public SearchResultEntry readEntry(String baseObject,
      String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    Validator.ensureNotNull(request, entries);
    // FIXME: does this need to be thread safe?
    SearchResultHandler<Void> handler = new SearchResultHandler<Void>()
    {
      public void handleReference(Void p,
          SearchResultReference reference)
      {
        if (references != null)
        {
          references.add(reference);
        }
    return readEntry(DN.valueOf(baseObject));
      }
      public void handleEntry(Void p, SearchResultEntry entry)
  /**
   * {@inheritDoc}
   */
  public RootDSE readRootDSE() throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException
      {
        entries.add(entry);
    return RootDSE.readRootDSE(this);
      }
    };
    return search(request, handler, null);
  /**
   * {@inheritDoc}
   */
  public Schema readSchema(DN name) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException
  {
    return Schema.readSchema(this, name);
  }
  /**
   * {@inheritDoc}
   */
  public Schema readSchema(String name) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException
  {
    return readSchema(DN.valueOf(name));
  }
  /**
   * {@inheritDoc}
   */
  public Schema readSchemaForEntry(DN name)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException
  {
    return Schema.readSchemaForEntry(this, name);
  }
  /**
   * {@inheritDoc}
   */
  public Schema readSchemaForEntry(String name)
      throws ErrorResultException, InterruptedException,
      LocalizedIllegalArgumentException, UnsupportedOperationException,
      IllegalStateException
  {
    return readSchemaForEntry(DN.valueOf(name));
  }
  /**
   * {@inheritDoc}
   */
  public Schema readSchemaForRootDSE() throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException
  {
    return readSchemaForEntry(DN.rootDN());
  }
@@ -227,6 +289,41 @@
  public Result search(SearchRequest request,
      final Collection<? super SearchResultEntry> entries,
      final Collection<? super SearchResultReference> references)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    Validator.ensureNotNull(request, entries);
    // FIXME: does this need to be thread safe?
    SearchResultHandler<Void> handler = new SearchResultHandler<Void>()
    {
      public void handleEntry(Void p, SearchResultEntry entry)
      {
        entries.add(entry);
      }
      public void handleReference(Void p,
          SearchResultReference reference)
      {
        if (references != null)
        {
          references.add(reference);
        }
      }
    };
    return search(request, handler, null);
  }
  public List<SearchResultEntry> search(String baseObject,
      SearchScope scope, String filter, String... attributeDescriptions)
      throws ErrorResultException, InterruptedException,
@@ -249,20 +346,32 @@
  {
    SingleEntryHandler handler = new SingleEntryHandler();
    search(request, handler, null);
    if (handler.entryCount > 1)
    if (handler.entryCount == 0)
    {
      // Did not find any entries.
      Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
          .setDiagnosticMessage(
              ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
      throw ErrorResultException.wrap(result);
    }
    else if (handler.entryCount > 1)
    {
      // Got more entries than expected.
      Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_MORE_RESULTS_TO_RETURN).setDiagnosticMessage(
          ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(handler.entryCount)
              .toString());
          ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
          .setDiagnosticMessage(
              ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(
                  handler.entryCount).toString());
      throw ErrorResultException.wrap(result);
    }
    else if (handler.firstReference != null)
    {
      // Got an unexpected search result reference.
      Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
          ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
          .setDiagnosticMessage(
          ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
              handler.firstReference.getURIs().iterator().next())
              .toString());
@@ -287,28 +396,4 @@
    return searchSingleEntry(request);
  }
  public SearchResultEntry readEntry(String baseObject,
      String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    return readEntry(DN.valueOf(baseObject));
  }
  public SearchResultEntry readEntry(DN baseObject,
      String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException
  {
    SearchRequest request = Requests.newSearchRequest(baseObject,
        SearchScope.BASE_OBJECT, Filter.getObjectClassPresentFilter(),
        attributeDescriptions);
    return searchSingleEntry(request);
  }
}
sdk/src/org/opends/sdk/AbstractFilterVisitor.java
@@ -83,7 +83,7 @@
   * {@link #visitDefaultFilter(Object)}.
   */
  public R visitApproxMatchFilter(P p, String attributeDescription,
      ByteSequence assertionValue)
      ByteString assertionValue)
  {
    return visitDefaultFilter(p);
  }
@@ -114,7 +114,7 @@
   * {@link #visitDefaultFilter(Object)}.
   */
  public R visitEqualityMatchFilter(P p, String attributeDescription,
      ByteSequence assertionValue)
      ByteString assertionValue)
  {
    return visitDefaultFilter(p);
  }
@@ -128,7 +128,7 @@
   * {@link #visitDefaultFilter(Object)}.
   */
  public R visitExtensibleMatchFilter(P p, String matchingRule,
      String attributeDescription, ByteSequence assertionValue,
      String attributeDescription, ByteString assertionValue,
      boolean dnAttributes)
  {
    return visitDefaultFilter(p);
@@ -143,7 +143,7 @@
   * {@link #visitDefaultFilter(Object)}.
   */
  public R visitGreaterOrEqualFilter(P p, String attributeDescription,
      ByteSequence assertionValue)
      ByteString assertionValue)
  {
    return visitDefaultFilter(p);
  }
@@ -157,7 +157,7 @@
   * {@link #visitDefaultFilter(Object)}.
   */
  public R visitLessOrEqualFilter(P p, String attributeDescription,
      ByteSequence assertionValue)
      ByteString assertionValue)
  {
    return visitDefaultFilter(p);
  }
@@ -210,8 +210,8 @@
   * {@link #visitDefaultFilter(Object)}.
   */
  public R visitSubstringsFilter(P p, String attributeDescription,
      ByteSequence initialSubstring, List<ByteSequence> anySubstrings,
      ByteSequence finalSubstring)
      ByteString initialSubstring, List<ByteString> anySubstrings,
      ByteString finalSubstring)
  {
    return visitDefaultFilter(p);
  }
@@ -225,7 +225,7 @@
   * {@link #visitDefaultFilter(Object)}.
   */
  public R visitUnrecognizedFilter(P p, byte filterTag,
      ByteSequence filterBytes)
      ByteString filterBytes)
  {
    return visitDefaultFilter(p);
  }
sdk/src/org/opends/sdk/AsynchronousConnection.java
@@ -30,11 +30,14 @@
import java.io.Closeable;
import java.util.Collection;
import org.opends.sdk.requests.*;
import org.opends.sdk.responses.BindResult;
import org.opends.sdk.responses.CompareResult;
import org.opends.sdk.responses.Result;
import org.opends.sdk.responses.SearchResultEntry;
import org.opends.sdk.schema.Schema;
@@ -190,6 +193,25 @@
  /**
   * Registers the provided connection event listener so that it will be
   * notified when this connection is closed by the application,
   * receives an unsolicited notification, or experiences a fatal error.
   *
   * @param listener
   *          The listener which wants to be notified when events occur
   *          on this connection.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   */
  void addConnectionEventListener(ConnectionEventListener listener)
      throws IllegalStateException, NullPointerException;
  /**
   * Authenticates to the Directory Server using the provided bind
   * request.
   *
@@ -367,6 +389,19 @@
  /**
   * Indicates whether or not this connection has been explicitly closed
   * by calling {@code close}. This method will not return {@code true}
   * if a fatal error has occurred on the connection unless {@code
   * close} has been called.
   *
   * @return {@code true} if this connection has been explicitly closed
   *         by calling {@code close}, or {@code false} otherwise.
   */
  boolean isClosed();
  /**
   * Modifies an entry in the Directory Server using the provided modify
   * request.
   *
@@ -429,6 +464,174 @@
  /**
   * Reads the named entry from the Directory Server.
   * <p>
   * If the requested entry is not returned by the Directory Server then
   * the request will fail with an {@link EntryNotFoundException}. More
   * specifically, the returned future will never return {@code null}.
   * <p>
   * This method is equivalent to the following code:
   *
   * <pre>
   * SearchRequest request = new SearchRequest(name,
   *     SearchScope.BASE_OBJECT, &quot;(objectClass=*)&quot;, attributeDescriptions);
   * connection.searchSingleEntry(request, resultHandler, p);
   * </pre>
   *
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param name
   *          The distinguished name of the entry to be read.
   * @param attributeDescriptions
   *          The names of the attributes to be included with the entry,
   *          which may be {@code null} or empty indicating that all
   *          user attributes should be returned.
   * @param handler
   *          A result handler which can be used to asynchronously
   *          process the operation result when it is received, may be
   *          {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code name} was {@code null}.
   */
  <P> ResultFuture<SearchResultEntry> readEntry(DN name,
      Collection<String> attributeDescriptions,
      ResultHandler<? super SearchResultEntry, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Reads the Root DSE from the Directory Server.
   * <p>
   * If the Root DSE is not returned by the Directory Server then the
   * request will fail with an {@link EntryNotFoundException}. More
   * specifically, the returned future will never return {@code null}.
   *
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param handler
   *          A result handler which can be used to asynchronously
   *          process the operation result when it is received, may be
   *          {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   */
  <P> ResultFuture<RootDSE> readRootDSE(
      ResultHandler<RootDSE, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException;
  /**
   * Reads the schema from the Directory Server contained in the named
   * subschema sub-entry.
   * <p>
   * If the requested schema is not returned by the Directory Server
   * then the request will fail with an {@link EntryNotFoundException}.
   * More specifically, the returned future will never return {@code
   * null}.
   * <p>
   * Implementations may choose to perform optimizations such as
   * caching.
   *
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param name
   *          The distinguished name of the subschema sub-entry.
   * @param handler
   *          A result handler which can be used to asynchronously
   *          process the operation result when it is received, may be
   *          {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   */
  <P> ResultFuture<Schema> readSchema(DN name,
      ResultHandler<Schema, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException;
  /**
   * Reads the schema from the Directory Server which applies to the
   * named entry.
   * <p>
   * If the requested entry or its associated schema are not returned by
   * the Directory Server then the request will fail with an
   * {@link EntryNotFoundException}. More specifically, the returned
   * future will never return {@code null}.
   * <p>
   * A typical implementation will first read the {@code
   * subschemaSubentry} attribute of the entry in order to locate the
   * schema. However, implementations may choose to perform other
   * optimizations, such as caching.
   *
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param name
   *          The distinguished name of the entry whose schema is to be
   *          located.
   * @param handler
   *          A result handler which can be used to asynchronously
   *          process the operation result when it is received, may be
   *          {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   */
  <P> ResultFuture<Schema> readSchemaForEntry(DN name,
      ResultHandler<Schema, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException;
  /**
   * Removes the provided connection event listener from this connection
   * so that it will no longer be notified when this connection is
   * closed by the application, receives an unsolicited notification, or
   * experiences a fatal error.
   *
   * @param listener
   *          The listener which no longer wants to be notified when
   *          events occur on this connection.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   */
  void removeConnectionEventListener(ConnectionEventListener listener)
      throws NullPointerException;
  /**
   * Searches the Directory Server using the provided search request.
   *
   * @param <P>
@@ -464,49 +667,39 @@
  /**
   * Registers the provided connection event listener so that it will be
   * notified when this connection is closed by the application,
   * receives an unsolicited notification, or experiences a fatal error.
   * Searches the Directory Server for a single entry using the provided
   * search request.
   * <p>
   * If the requested entry is not returned by the Directory Server then
   * the request will fail with an {@link EntryNotFoundException}. More
   * specifically, the returned future will never return {@code null}.
   * If multiple matching entries are returned by the Directory Server
   * then the request will fail with an
   * {@link MultipleEntriesFoundException}.
   *
   * @param listener
   *          The listener which wants to be notified when events occur
   *          on this connection.
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param request
   *          The search request.
   * @param handler
   *          A result handler which can be used to asynchronously
   *          process the operation result when it is received, may be
   *          {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   *           If the {@code request} was {@code null}.
   */
  void addConnectionEventListener(ConnectionEventListener listener)
      throws IllegalStateException, NullPointerException;
  /**
   * Removes the provided connection event listener from this connection
   * so that it will no longer be notified when this connection is
   * closed by the application, receives an unsolicited notification, or
   * experiences a fatal error.
   *
   * @param listener
   *          The listener which no longer wants to be notified when
   *          events occur on this connection.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   */
  void removeConnectionEventListener(ConnectionEventListener listener)
      throws NullPointerException;
  /**
   * Indicates whether or not this connection has been explicitly closed
   * by calling {@code close}. This method will not return {@code true}
   * if a fatal error has occurred on the connection unless {@code
   * close} has been called.
   *
   * @return {@code true} if this connection has been explicitly closed
   *         by calling {@code close}, or {@code false} otherwise.
   */
  boolean isClosed();
  <P> ResultFuture<SearchResultEntry> searchSingleEntry(
      SearchRequest request,
      ResultHandler<? super SearchResultEntry, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException;
}
sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java
@@ -29,6 +29,7 @@
import java.util.Collection;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -38,6 +39,8 @@
import org.opends.sdk.responses.BindResult;
import org.opends.sdk.responses.CompareResult;
import org.opends.sdk.responses.Result;
import org.opends.sdk.responses.SearchResultEntry;
import org.opends.sdk.schema.Schema;
import com.sun.opends.sdk.util.Validator;
@@ -106,7 +109,8 @@
        ConnectionResultHandler<? super AuthenticatedAsynchronousConnection, P> handler,
        P p)
    {
      // TODO: bug here? if allowRebind= false then bind will never happen
      // TODO: bug here? if allowRebind= false then bind will never
      // happen
      ConnectionFutureImpl<P> future = new ConnectionFutureImpl<P>(
          allowRebinds ? request : null, handler, p);
      future.connectFuture = parentFactory.getAsynchronousConnection(
@@ -465,6 +469,8 @@
          searchResulthandler, p);
    }
    /**
     * {@inheritDoc}
     */
@@ -472,6 +478,72 @@
    {
      return connection.isClosed();
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<RootDSE> readRootDSE(
        ResultHandler<RootDSE, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException
    {
      return connection.readRootDSE(handler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<SearchResultEntry> readEntry(DN name,
        Collection<String> attributeDescriptions,
        ResultHandler<? super SearchResultEntry, P> resultHandler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return connection.readEntry(name, attributeDescriptions,
          resultHandler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<SearchResultEntry> searchSingleEntry(
        SearchRequest request,
        ResultHandler<? super SearchResultEntry, P> resultHandler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return connection.searchSingleEntry(request, resultHandler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<Schema> readSchemaForEntry(DN name,
        ResultHandler<Schema, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException
    {
      return connection.readSchemaForEntry(name, handler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<Schema> readSchema(DN name,
        ResultHandler<Schema, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException
    {
      return connection.readSchema(name, handler, p);
    }
  }
sdk/src/org/opends/sdk/CancelledResultException.java
File was renamed from sdk/src/org/opends/sdk/CancelledException.java
@@ -35,12 +35,19 @@
/**
 * Thrown when the result code returned in a Result indicates that the
 * Request was cancelled.
 * Request was cancelled. More specifically, this exception is used for
 * the following error result codes:
 * <ul>
 * <li>{@link ResultCode#CANCELLED} - the requested operation was
 * cancelled.
 * <li>{@link ResultCode#CLIENT_SIDE_USER_CANCELLED} - the requested
 * operation was cancelled by the user.
 * </ul>
 */
@SuppressWarnings("serial")
public class CancelledException extends ErrorResultException
public class CancelledResultException extends ErrorResultException
{
  CancelledException(Result result)
  CancelledResultException(Result result)
  {
    super(result);
  }
sdk/src/org/opends/sdk/Connection.java
@@ -35,6 +35,7 @@
import org.opends.sdk.requests.*;
import org.opends.sdk.responses.*;
import org.opends.sdk.schema.Schema;
@@ -123,6 +124,38 @@
  /**
   * Adds the provided entry to the Directory Server.
   * <p>
   * This method is equivalent to the following code:
   *
   * <pre>
   * AddRequest request = new AddRequest(entry);
   * connection.add(request);
   * </pre>
   *
   * @param entry
   *          The entry to be added.
   * @return The result of the operation.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support add operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code entry} was {@code null} .
   */
  Result add(Entry entry) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException;
  /**
   * Adds an entry to the Directory Server using the provided lines of
   * LDIF.
   * <p>
@@ -161,34 +194,21 @@
  /**
   * Adds the provided entry to the Directory Server.
   * <p>
   * This method is equivalent to the following code:
   * Registers the provided connection event listener so that it will be
   * notified when this connection is closed by the application,
   * receives an unsolicited notification, or experiences a fatal error.
   *
   * <pre>
   * AddRequest request = new AddRequest(entry);
   * connection.add(request);
   * </pre>
   *
   * @param entry
   *          The entry to be added.
   * @return The result of the operation.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support add operations.
   * @param listener
   *          The listener which wants to be notified when events occur
   *          on this connection.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code entry} was {@code null} .
   *           If the {@code listener} was {@code null}.
   */
  Result add(Entry entry) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException;
  void addConnectionEventListener(ConnectionEventListener listener)
      throws IllegalStateException, NullPointerException;
@@ -513,19 +533,6 @@
  /**
   * Indicates whether or not this connection has been explicitly closed
   * by calling {@code close}. This method will not return {@code true}
   * if a fatal error has occurred on the connection unless {@code
   * close} has been called.
   *
   * @return {@code true} if this connection has been explicitly closed
   *         by calling {@code close}, or {@code false} otherwise.
   */
  boolean isClosed();
  //
  //
  //
@@ -581,6 +588,19 @@
  // throws InterruptedException, TimeoutException;
  /**
   * Indicates whether or not this connection has been explicitly closed
   * by calling {@code close}. This method will not return {@code true}
   * if a fatal error has occurred on the connection unless {@code
   * close} has been called.
   *
   * @return {@code true} if this connection has been explicitly closed
   *         by calling {@code close}, or {@code false} otherwise.
   */
  boolean isClosed();
  /**
   * Modifies an entry in the Directory Server using the provided modify
   * request.
   *
@@ -710,23 +730,27 @@
  /**
   * Searches the Directory Server using the provided search request.
   * Any matching entries returned by the search as well as any search
   * result references will be passed to the provided search result
   * handler.
   * Reads the named entry from the Directory Server.
   * <p>
   * If the requested entry is not returned by the Directory Server then
   * the request will fail with an {@link EntryNotFoundException}. More
   * specifically, this method will never return {@code null}.
   * <p>
   * This method is equivalent to the following code:
   *
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param request
   *          The search request.
   * @param handler
   *          A search result handler which can be used to process the
   *          search result entries and references as they are received,
   *          may be {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return The result of the operation.
   * <pre>
   * SearchRequest request = new SearchRequest(name,
   *     SearchScope.BASE_OBJECT, &quot;(objectClass=*)&quot;, attributeDescriptions);
   * connection.searchSingleEntry(request);
   * </pre>
   *
   * @param name
   *          The distinguished name of the entry to be read.
   * @param attributeDescriptions
   *          The names of the attributes to be included with the entry,
   *          which may be {@code null} or empty indicating that all
   *          user attributes should be returned.
   * @return The single search result entry returned from the search.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
@@ -738,12 +762,276 @@
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   *           If the {@code name} was {@code null}.
   */
  <P> Result search(SearchRequest request,
      SearchResultHandler<P> handler, P p) throws ErrorResultException,
  SearchResultEntry readEntry(DN name, String... attributeDescriptions)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Reads the named entry from the Directory Server.
   * <p>
   * If the requested entry is not returned by the Directory Server then
   * the request will fail with an {@link EntryNotFoundException}. More
   * specifically, this method will never return {@code null}.
   * <p>
   * This method is equivalent to the following code:
   *
   * <pre>
   * SearchRequest request = new SearchRequest(name,
   *     SearchScope.BASE_OBJECT, &quot;(objectClass=*)&quot;, attributeDescriptions);
   * connection.searchSingleEntry(request);
   * </pre>
   *
   * @param name
   *          The distinguished name of the entry to be read.
   * @param attributeDescriptions
   *          The names of the attributes to be included with the entry.
   * @return The single search result entry returned from the search.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws LocalizedIllegalArgumentException
   *           If {@code baseObject} could not be decoded using the
   *           default schema.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code name} was {@code null}.
   */
  SearchResultEntry readEntry(String name,
      String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Reads the Root DSE from the Directory Server.
   * <p>
   * If the Root DSE is not returned by the Directory Server then the
   * request will fail with an {@link EntryNotFoundException}. More
   * specifically, this method will never return {@code null}.
   *
   * @return The Directory Server's Root DSE.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   */
  RootDSE readRootDSE() throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException;
      IllegalStateException;
  /**
   * Reads the schema from the Directory Server contained in the named
   * subschema sub-entry.
   * <p>
   * If the requested schema is not returned by the Directory Server
   * then the request will fail with an {@link EntryNotFoundException}.
   * More specifically, this method will never return {@code null}.
   * <p>
   * Implementations may choose to perform optimizations such as
   * caching.
   *
   * @param name
   *          The distinguished name of the subschema sub-entry.
   * @return The schema from the Directory Server.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   */
  Schema readSchema(DN name) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException;
  /**
   * Reads the schema from the Directory Server contained in the named
   * subschema sub-entry.
   * <p>
   * If the requested schema is not returned by the Directory Server
   * then the request will fail with an {@link EntryNotFoundException}.
   * More specifically, this method will never return {@code null}.
   * <p>
   * Implementations may choose to perform optimizations such as
   * caching.
   *
   * @param name
   *          The distinguished name of the subschema sub-entry.
   * @return The schema from the Directory Server.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws LocalizedIllegalArgumentException
   *           If {@code name} could not be decoded using the default
   *           schema.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   */
  Schema readSchema(String name) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException;
  /**
   * Reads the schema from the Directory Server which applies to the
   * named entry.
   * <p>
   * If the requested entry or its associated schema are not returned by
   * the Directory Server then the request will fail with an
   * {@link EntryNotFoundException}. More specifically, this method will
   * never return {@code null}.
   * <p>
   * A typical implementation will first read the {@code
   * subschemaSubentry} attribute of the entry in order to locate the
   * schema. However, implementations may choose to perform other
   * optimizations, such as caching.
   *
   * @param name
   *          The distinguished name of the entry whose schema is to be
   *          located.
   * @return The schema from the Directory Server which applies to the
   *         named entry.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   */
  Schema readSchemaForEntry(DN name) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException;
  /**
   * Reads the schema from the Directory Server which applies to the
   * named entry.
   * <p>
   * If the requested entry or its associated schema are not returned by
   * the Directory Server then the request will fail with an
   * {@link EntryNotFoundException}. More specifically, this method will
   * never return {@code null}.
   * <p>
   * A typical implementation will first read the {@code
   * subschemaSubentry} attribute of the entry in order to locate the
   * schema. However, implementations may choose to perform other
   * optimizations, such as caching.
   *
   * @param name
   *          The distinguished name of the entry whose schema is to be
   *          located.
   * @return The schema from the Directory Server which applies to the
   *         named entry.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws LocalizedIllegalArgumentException
   *           If {@code name} could not be decoded using the default
   *           schema.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   */
  Schema readSchemaForEntry(String name) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException;
  /**
   * Reads the schema from the Directory Server which applies to the
   * Root DSE.
   * <p>
   * If the requested schema is not returned by the Directory Server
   * then the request will fail with an {@link EntryNotFoundException}.
   * More specifically, this method will never return {@code null}.
   * <p>
   * A typical implementation will first read the {@code
   * subschemaSubentry} attribute of the Root DSE in order to locate the
   * schema. However, implementations may choose to perform other
   * optimizations, such as caching.
   * <p>
   * This method is equivalent to the following code:
   *
   * <pre>
   * connection.readSchemaForEntry(DN.rootDN());
   * </pre>
   *
   * @return The schema from the Directory Server which applies to the
   *         named entry.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   */
  Schema readSchemaForRootDSE() throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException;
  /**
   * Removes the provided connection event listener from this connection
   * so that it will no longer be notified when this connection is
   * closed by the application, receives an unsolicited notification, or
   * experiences a fatal error.
   *
   * @param listener
   *          The listener which no longer wants to be notified when
   *          events occur on this connection.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   */
  void removeConnectionEventListener(ConnectionEventListener listener)
      throws NullPointerException;
@@ -833,6 +1121,44 @@
  /**
   * Searches the Directory Server using the provided search request.
   * Any matching entries returned by the search as well as any search
   * result references will be passed to the provided search result
   * handler.
   *
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param request
   *          The search request.
   * @param handler
   *          A search result handler which can be used to process the
   *          search result entries and references as they are received,
   *          may be {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return The result of the operation.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If {@code request} was {@code null}.
   */
  <P> Result search(SearchRequest request,
      SearchResultHandler<P> handler, P p) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException;
  /**
   * Searches the Directory Server using the provided search parameters.
   * Any matching entries returned by the search will be added to a
   * {@code List} which is returned if the search succeeds. Search
@@ -892,9 +1218,13 @@
  /**
   * Searches the Directory Server for a single entry using the provided
   * search request. If the search returns more than one entry then an
   * {@code ErrorResultException} is thrown. If no entry is found then
   * this method returns {@code null}.
   * search request.
   * <p>
   * If the requested entry is not returned by the Directory Server then
   * the request will fail with an {@link EntryNotFoundException}. More
   * specifically, this method will never return {@code null}. If
   * multiple matching entries are returned by the Directory Server then
   * the request will fail with an {@link MultipleEntriesFoundException}.
   *
   * @param request
   *          The search request.
@@ -921,9 +1251,13 @@
  /**
   * Searches the Directory Server for a single entry using the provided
   * search parameters. If the search returns more than one entry then
   * an {@code ErrorResultException} is thrown. If no entry is found
   * then this method returns {@code null}.
   * search parameters.
   * <p>
   * If the requested entry is not returned by the Directory Server then
   * the request will fail with an {@link EntryNotFoundException}. More
   * specifically, this method will never return {@code null}. If
   * multiple matching entries are returned by the Directory Server then
   * the request will fail with an {@link MultipleEntriesFoundException}.
   * <p>
   * This method is equivalent to the following code:
   *
@@ -968,118 +1302,4 @@
      throws ErrorResultException, InterruptedException,
      LocalizedIllegalArgumentException, UnsupportedOperationException,
      IllegalStateException, NullPointerException;
  /**
   * Reads the named entry from the Directory Server. If no entry is
   * found then this method returns {@code null}.
   * <p>
   * This method is equivalent to the following code:
   *
   * <pre>
   * SearchRequest request = new SearchRequest(baseObject,
   *     SearchScope.BASE_OBJECT, &quot;(objectClass=*)&quot;, attributeDescriptions);
   * connection.searchSingleEntry(request);
   * </pre>
   *
   * @param baseObject
   *          The distinguished name of the entry to be read.
   * @param attributeDescriptions
   *          The names of the attributes to be included with the entry.
   * @return The single search result entry returned from the search.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws LocalizedIllegalArgumentException
   *           If {@code baseObject} could not be decoded using the
   *           default schema.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code baseObject} was {@code null}.
   */
  SearchResultEntry readEntry(String baseObject,
      String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException;
  /**
   * Reads the named entry from the Directory Server. If no entry is
   * found then this method returns {@code null}.
   * <p>
   * This method is equivalent to the following code:
   *
   * <pre>
   * SearchRequest request = new SearchRequest(baseObject,
   *     SearchScope.BASE_OBJECT, &quot;(objectClass=*)&quot;, attributeDescriptions);
   * connection.searchSingleEntry(request);
   * </pre>
   *
   * @param baseObject
   *          The distinguished name of the entry to be read.
   * @param attributeDescriptions
   *          The names of the attributes to be included with the entry.
   * @return The single search result entry returned from the search.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code baseObject} was {@code null}.
   */
  SearchResultEntry readEntry(DN baseObject,
      String... attributeDescriptions) throws ErrorResultException,
      InterruptedException, UnsupportedOperationException,
      IllegalStateException, NullPointerException;
  /**
   * Registers the provided connection event listener so that it will be
   * notified when this connection is closed by the application,
   * receives an unsolicited notification, or experiences a fatal error.
   *
   * @param listener
   *          The listener which wants to be notified when events occur
   *          on this connection.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   */
  void addConnectionEventListener(ConnectionEventListener listener)
      throws IllegalStateException, NullPointerException;
  /**
   * Removes the provided connection event listener from this connection
   * so that it will no longer be notified when this connection is
   * closed by the application, receives an unsolicited notification, or
   * experiences a fatal error.
   *
   * @param listener
   *          The listener which no longer wants to be notified when
   *          events occur on this connection.
   * @throws NullPointerException
   *           If the {@code listener} was {@code null}.
   */
  void removeConnectionEventListener(ConnectionEventListener listener)
      throws NullPointerException;
}
sdk/src/org/opends/sdk/ConnectionPool.java
@@ -27,6 +27,9 @@
package org.opends.sdk;
import java.util.Collection;
import java.util.Stack;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
@@ -35,95 +38,128 @@
import java.util.logging.Level;
import org.opends.sdk.requests.*;
import org.opends.sdk.responses.BindResult;
import org.opends.sdk.responses.CompareResult;
import org.opends.sdk.responses.GenericExtendedResult;
import org.opends.sdk.responses.Result;
import org.opends.sdk.responses.*;
import org.opends.sdk.schema.Schema;
import com.sun.opends.sdk.util.StaticUtils;
/**
 * A simple connection pool implementation.
 */
public class ConnectionPool
    extends AbstractConnectionFactory<AsynchronousConnection> {
public class ConnectionPool extends
    AbstractConnectionFactory<AsynchronousConnection>
{
  private final ConnectionFactory<?> connectionFactory;
  private volatile int numConnections;
  private final int poolSize;
  // FIXME: should use a better collection than this - CLQ?
  private final Stack<AsynchronousConnection> pool;
  private final ConcurrentLinkedQueue<PendingConnectionFuture<?>> pendingFutures;
  private final Object lock = new Object();
  private final class PooledConnectionWapper
      implements AsynchronousConnection, ConnectionEventListener {
  private final class PooledConnectionWapper implements
      AsynchronousConnection, ConnectionEventListener
  {
    private AsynchronousConnection connection;
    private PooledConnectionWapper(AsynchronousConnection connection) {
    private PooledConnectionWapper(AsynchronousConnection connection)
    {
      this.connection = connection;
      this.connection.addConnectionEventListener(this);
    }
    public void abandon(AbandonRequest request)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      if (connection == null) {
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      connection.abandon(request);
    }
    public <P> ResultFuture<Result> add(
        AddRequest request,
    public <P> ResultFuture<Result> add(AddRequest request,
        ResultHandler<Result, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      if (connection == null) {
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.add(request, handler, p);
    }
    public <P> ResultFuture<BindResult> bind(
        BindRequest request, ResultHandler<? super BindResult, P> handler, P p)
    public <P> ResultFuture<BindResult> bind(BindRequest request,
        ResultHandler<? super BindResult, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      if (connection == null) {
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.bind(request, handler, p);
    }
    public void close() {
      synchronized (lock) {
        try {
    public void close()
    {
      synchronized (lock)
      {
        try
        {
          // Don't put closed connections back in the pool.
          if (connection.isClosed()) {
          if (connection.isClosed())
          {
            if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
            {
              StaticUtils.DEBUG_LOG.finest(String
                  .format("Dead connection released to pool. " +
                  "numConnections: %d, poolSize: %d, pendingFutures: %d",
                  numConnections, pool.size(), pendingFutures.size()));
              StaticUtils.DEBUG_LOG
                  .finest(String
                      .format(
                          "Dead connection released to pool. "
                              + "numConnections: %d, poolSize: %d, pendingFutures: %d",
                          numConnections, pool.size(), pendingFutures
                              .size()));
            }
            return;
          }
          // See if there waiters pending
          PendingConnectionFuture<?> future = pendingFutures.poll();
          if (future != null) {
            PooledConnectionWapper pooledConnection =
                new PooledConnectionWapper(connection);
          if (future != null)
          {
            PooledConnectionWapper pooledConnection = new PooledConnectionWapper(
                connection);
            future.connection(pooledConnection);
            if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
            {
              StaticUtils.DEBUG_LOG.finest(String
                  .format("Connection released to pool and directly " +
                  "given to waiter. numConnections: %d, poolSize: %d, " +
                  "pendingFutures: %d", numConnections, pool.size(),
                  pendingFutures.size()));
              StaticUtils.DEBUG_LOG
                  .finest(String
                      .format(
                          "Connection released to pool and directly "
                              + "given to waiter. numConnections: %d, poolSize: %d, "
                              + "pendingFutures: %d", numConnections,
                          pool.size(), pendingFutures.size()));
            }
            return;
          }
@@ -132,99 +168,229 @@
          pool.push(connection);
          if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
          {
            StaticUtils.DEBUG_LOG.finest(String
                .format("Connection released to pool. " +
                "numConnections: %d, poolSize: %d, pendingFutures: %d",
                numConnections, pool.size(), pendingFutures.size()));
            StaticUtils.DEBUG_LOG
                .finest(String
                    .format(
                        "Connection released to pool. "
                            + "numConnections: %d, poolSize: %d, pendingFutures: %d",
                        numConnections, pool.size(), pendingFutures
                            .size()));
          }
        }
        finally {
        finally
        {
          // Null out the underlying connection to prevent further use.
          connection = null;
        }
      }
    }
    public void close(UnbindRequest request, String reason)
        throws NullPointerException {
        throws NullPointerException
    {
      close();
    }
    public <P> ResultFuture<CompareResult> compare(
        CompareRequest request, ResultHandler<? super CompareResult, P> handler,
        P p) throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      if (connection == null) {
        CompareRequest request,
        ResultHandler<? super CompareResult, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.compare(request, handler, p);
    }
    public <P> ResultFuture<Result> delete(
        DeleteRequest request, ResultHandler<Result, P> handler, P p)
    public <P> ResultFuture<Result> delete(DeleteRequest request,
        ResultHandler<Result, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      if (connection == null) {
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.delete(request, handler, p);
    }
    public <R extends Result, P> ResultFuture<R> extendedRequest(
        ExtendedRequest<R> request, ResultHandler<? super R, P> handler, P p)
        ExtendedRequest<R> request,
        ResultHandler<? super R, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      if (connection == null) {
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.extendedRequest(request, handler, p);
    }
    public <P> ResultFuture<Result> modify(
        ModifyRequest request, ResultHandler<Result, P> handler, P p)
    public <P> ResultFuture<Result> modify(ModifyRequest request,
        ResultHandler<Result, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      if (connection == null) {
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.modify(request, handler, p);
    }
    public <P> ResultFuture<Result> modifyDN(
        ModifyDNRequest request, ResultHandler<Result, P> handler, P p)
    public <P> ResultFuture<Result> modifyDN(ModifyDNRequest request,
        ResultHandler<Result, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      if (connection == null) {
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.modifyDN(request, handler, p);
    }
    public <P> ResultFuture<Result> search(
        SearchRequest request, ResultHandler<Result, P> resultHandler,
    public <P> ResultFuture<Result> search(SearchRequest request,
        ResultHandler<Result, P> resultHandler,
        SearchResultHandler<P> searchResulthandler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      if (connection == null) {
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.search(request, resultHandler, searchResulthandler, p);
      return connection.search(request, resultHandler,
          searchResulthandler, p);
    }
    public void addConnectionEventListener(ConnectionEventListener listener)
        throws IllegalStateException, NullPointerException {
      if (connection == null) {
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<SearchResultEntry> readEntry(DN name,
        Collection<String> attributeDescriptions,
        ResultHandler<? super SearchResultEntry, P> resultHandler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.readEntry(name, attributeDescriptions,
          resultHandler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<SearchResultEntry> searchSingleEntry(
        SearchRequest request,
        ResultHandler<? super SearchResultEntry, P> resultHandler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.searchSingleEntry(request, resultHandler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<RootDSE> readRootDSE(
        ResultHandler<RootDSE, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.readRootDSE(handler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<Schema> readSchemaForEntry(DN name,
        ResultHandler<Schema, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.readSchemaForEntry(name, handler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<Schema> readSchema(DN name,
        ResultHandler<Schema, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
      return connection.readSchema(name, handler, p);
    }
    public void addConnectionEventListener(
        ConnectionEventListener listener) throws IllegalStateException,
        NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
    }
    public void removeConnectionEventListener(ConnectionEventListener listener)
        throws NullPointerException {
      if (connection == null) {
    public void removeConnectionEventListener(
        ConnectionEventListener listener) throws NullPointerException
    {
      if (connection == null)
      {
        throw new IllegalStateException();
      }
    }
    /**
     * {@inheritDoc}
     */
@@ -233,14 +399,21 @@
      return connection == null;
    }
    public void connectionReceivedUnsolicitedNotification(
        GenericExtendedResult notification) {
        GenericExtendedResult notification)
    {
      // Ignore
    }
    public void connectionErrorOccurred(
        boolean isDisconnectNotification, ErrorResultException error) {
      synchronized (lock) {
        boolean isDisconnectNotification, ErrorResultException error)
    {
      synchronized (lock)
      {
        // Remove this connection from the pool if its in there
        pool.remove(this);
        numConnections--;
@@ -252,104 +425,166 @@
        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
        {
          StaticUtils.DEBUG_LOG.finest(String
              .format("Connection error occured: " + error.getMessage() +
              " numConnections: %d, poolSize: %d, pendingFutures: %d",
              numConnections, pool.size(), pendingFutures.size()));
          StaticUtils.DEBUG_LOG
              .finest(String
                  .format(
                      "Connection error occured: "
                          + error.getMessage()
                          + " numConnections: %d, poolSize: %d, pendingFutures: %d",
                      numConnections, pool.size(), pendingFutures
                          .size()));
        }
      }
    }
  }
  private static final class CompletedConnectionFuture
      implements ConnectionFuture<AsynchronousConnection> {
  private static final class CompletedConnectionFuture implements
      ConnectionFuture<AsynchronousConnection>
  {
    private final PooledConnectionWapper connection;
    private CompletedConnectionFuture(PooledConnectionWapper connection) {
    private CompletedConnectionFuture(PooledConnectionWapper connection)
    {
      this.connection = connection;
    }
    public boolean cancel(boolean mayInterruptIfRunning) {
    public boolean cancel(boolean mayInterruptIfRunning)
    {
      return false;
    }
    public AsynchronousConnection get()
        throws InterruptedException, ErrorResultException {
    public AsynchronousConnection get() throws InterruptedException,
        ErrorResultException
    {
      return connection;
    }
    public AsynchronousConnection get(long timeout, TimeUnit unit)
        throws InterruptedException, TimeoutException, ErrorResultException {
        throws InterruptedException, TimeoutException,
        ErrorResultException
    {
      return connection;
    }
    public boolean isCancelled() {
    public boolean isCancelled()
    {
      return false;
    }
    public boolean isDone() {
    public boolean isDone()
    {
      return true;
    }
  }
  private final class PendingConnectionFuture<P>
      implements ConnectionFuture<AsynchronousConnection> {
  private final class PendingConnectionFuture<P> implements
      ConnectionFuture<AsynchronousConnection>
  {
    private volatile boolean isCancelled;
    private volatile PooledConnectionWapper connection;
    private volatile ErrorResultException err;
    private final ConnectionResultHandler<? super AsynchronousConnection, P>
        handler;
    private final ConnectionResultHandler<? super AsynchronousConnection, P> handler;
    private final P p;
    private final CountDownLatch latch = new CountDownLatch(1);
    private PendingConnectionFuture(
        P p,
        ConnectionResultHandler<? super AsynchronousConnection, P> handler) {
        ConnectionResultHandler<? super AsynchronousConnection, P> handler)
    {
      this.handler = handler;
      this.p = p;
    }
    public synchronized boolean cancel(boolean mayInterruptIfRunning) {
    public synchronized boolean cancel(boolean mayInterruptIfRunning)
    {
      return pendingFutures.remove(this) && (isCancelled = true);
    }
    public AsynchronousConnection get()
        throws InterruptedException, ErrorResultException {
    public AsynchronousConnection get() throws InterruptedException,
        ErrorResultException
    {
      latch.await();
      if (err != null) {
      if (err != null)
      {
        throw err;
      }
      return connection;
    }
    public AsynchronousConnection get(long timeout, TimeUnit unit)
        throws InterruptedException, TimeoutException, ErrorResultException {
        throws InterruptedException, TimeoutException,
        ErrorResultException
    {
      latch.await(timeout, unit);
      if (err != null) {
      if (err != null)
      {
        throw err;
      }
      return connection;
    }
    public synchronized boolean isCancelled() {
    public synchronized boolean isCancelled()
    {
      return isCancelled;
    }
    public boolean isDone() {
    public boolean isDone()
    {
      return latch.getCount() == 0;
    }
    private void connection(PooledConnectionWapper connection) {
    private void connection(PooledConnectionWapper connection)
    {
      this.connection = connection;
      if (handler != null) {
      if (handler != null)
      {
        handler.handleConnection(p, connection);
      }
      latch.countDown();
    }
    private void error(ErrorResultException e) {
    private void error(ErrorResultException e)
    {
      this.err = e;
      if (handler != null) {
      if (handler != null)
      {
        handler.handleConnectionError(p, e);
      }
      latch.countDown();
@@ -368,83 +603,115 @@
   * @param poolSize
   *          The maximum size of the connection pool.
   */
  public ConnectionPool(ConnectionFactory<?> connectionFactory, int poolSize) {
  public ConnectionPool(ConnectionFactory<?> connectionFactory,
      int poolSize)
  {
    this.connectionFactory = connectionFactory;
    this.poolSize = poolSize;
    this.pool = new Stack<AsynchronousConnection>();
    this.pendingFutures = new ConcurrentLinkedQueue<PendingConnectionFuture<?>>();
  }
  private final class WrapConnectionResultHandler
      implements ConnectionResultHandler<AsynchronousConnection, Void> {
  private final class WrapConnectionResultHandler implements
      ConnectionResultHandler<AsynchronousConnection, Void>
  {
    private final PendingConnectionFuture<?> future;
    private WrapConnectionResultHandler(PendingConnectionFuture<?> future) {
    private WrapConnectionResultHandler(
        PendingConnectionFuture<?> future)
    {
      this.future = future;
    }
    public void handleConnection(
        java.lang.Void p,
        AsynchronousConnection connection) {
      PooledConnectionWapper pooledConnection =
          new PooledConnectionWapper(connection);
    public void handleConnection(java.lang.Void p,
        AsynchronousConnection connection)
    {
      PooledConnectionWapper pooledConnection = new PooledConnectionWapper(
          connection);
      future.connection(pooledConnection);
    }
    public void handleConnectionError(
        java.lang.Void p,
        ErrorResultException error) {
    public void handleConnectionError(java.lang.Void p,
        ErrorResultException error)
    {
      future.error(error);
    }
  }
  public <P> ConnectionFuture<AsynchronousConnection> getAsynchronousConnection(
      ConnectionResultHandler<? super AsynchronousConnection, P> handler, P p) {
    synchronized (lock) {
      ConnectionResultHandler<? super AsynchronousConnection, P> handler,
      P p)
  {
    synchronized (lock)
    {
      // Check to see if we have a connection in the pool
      if (!pool.isEmpty()) {
      if (!pool.isEmpty())
      {
        AsynchronousConnection conn = pool.pop();
        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
        {
          StaticUtils.DEBUG_LOG.finest(String
              .format("Connection aquired from pool. " +
              "numConnections: %d, poolSize: %d, pendingFutures: %d",
              numConnections, pool.size(), pendingFutures.size()));
          StaticUtils.DEBUG_LOG
              .finest(String
                  .format(
                      "Connection aquired from pool. "
                          + "numConnections: %d, poolSize: %d, pendingFutures: %d",
                      numConnections, pool.size(), pendingFutures
                          .size()));
        }
        PooledConnectionWapper pooledConnection =
            new PooledConnectionWapper(conn);
        if (handler != null) {
        PooledConnectionWapper pooledConnection = new PooledConnectionWapper(
            conn);
        if (handler != null)
        {
          handler.handleConnection(p, pooledConnection);
        }
        return new CompletedConnectionFuture(pooledConnection);
      }
      PendingConnectionFuture<P> pendingFuture =
          new PendingConnectionFuture<P>(p, handler);
      // Pool was empty. Maybe a new connection if pool size is not reached
      if (numConnections < poolSize) {
      PendingConnectionFuture<P> pendingFuture = new PendingConnectionFuture<P>(
          p, handler);
      // Pool was empty. Maybe a new connection if pool size is not
      // reached
      if (numConnections < poolSize)
      {
        numConnections++;
        WrapConnectionResultHandler wrapHandler =
            new WrapConnectionResultHandler(pendingFuture);
        WrapConnectionResultHandler wrapHandler = new WrapConnectionResultHandler(
            pendingFuture);
        connectionFactory.getAsynchronousConnection(wrapHandler, null);
        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
        {
          StaticUtils.DEBUG_LOG.finest(String
              .format("New connection established and aquired. " +
              "numConnections: %d, poolSize: %d, pendingFutures: %d",
              numConnections, pool.size(), pendingFutures.size()));
          StaticUtils.DEBUG_LOG
              .finest(String
                  .format(
                      "New connection established and aquired. "
                          + "numConnections: %d, poolSize: %d, pendingFutures: %d",
                      numConnections, pool.size(), pendingFutures
                          .size()));
        }
      } else {
      }
      else
      {
        // Have to wait
        pendingFutures.add(pendingFuture);
        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
        {
          StaticUtils.DEBUG_LOG.finest(String
              .format("No connections available. Wait-listed" +
              "numConnections: %d, poolSize: %d, pendingFutures: %d",
              numConnections, pool.size(), pendingFutures.size()));
          StaticUtils.DEBUG_LOG
              .finest(String
                  .format(
                      "No connections available. Wait-listed"
                          + "numConnections: %d, poolSize: %d, pendingFutures: %d",
                      numConnections, pool.size(), pendingFutures
                          .size()));
        }
      }
sdk/src/org/opends/sdk/EntryNotFoundException.java
copy from sdk/src/org/opends/sdk/CancelledException.java copy to sdk/src/org/opends/sdk/EntryNotFoundException.java
File was copied from sdk/src/org/opends/sdk/CancelledException.java
@@ -35,12 +35,21 @@
/**
 * Thrown when the result code returned in a Result indicates that the
 * Request was cancelled.
 * Request failed because the target entry was not found by the
 * Directory Server. More specifically, this exception is used for the
 * following error result codes:
 * <ul>
 * <li>{@link ResultCode#NO_SUCH_OBJECT} - the requested operation
 * failed because it referenced an entry that does not exist.
 * <li>{@link ResultCode#CLIENT_SIDE_NO_RESULTS_RETURNED} - the
 * requested single entry search operation or read operation failed
 * because the Directory Server did not return any matching entries.
 * </ul>
 */
@SuppressWarnings("serial")
public class CancelledException extends ErrorResultException
public class EntryNotFoundException extends ErrorResultException
{
  CancelledException(Result result)
  EntryNotFoundException(Result result)
  {
    super(result);
  }
sdk/src/org/opends/sdk/ErrorResultException.java
@@ -70,22 +70,34 @@
    // TODO: choose type of exception based on result code (e.g.
    // referral).
    if(result.getResultCode() == ResultCode.CLIENT_SIDE_SERVER_DOWN ||
        result.getResultCode() == ResultCode.CLIENT_SIDE_CONNECT_ERROR ||
        result.getResultCode() == ResultCode.CLIENT_SIDE_DECODING_ERROR ||
        result.getResultCode() == ResultCode.CLIENT_SIDE_ENCODING_ERROR)
    if (result.getResultCode() == ResultCode.CLIENT_SIDE_SERVER_DOWN
        || result.getResultCode() == ResultCode.CLIENT_SIDE_CONNECT_ERROR
        || result.getResultCode() == ResultCode.CLIENT_SIDE_DECODING_ERROR
        || result.getResultCode() == ResultCode.CLIENT_SIDE_ENCODING_ERROR)
    {
      return new ConnectionException(result);
    }
    if(result.getResultCode() == ResultCode.CLIENT_SIDE_TIMEOUT)
    {
      return new OperationTimeoutException(result);
      return new TimeoutResultException(result);
    }
    if(result.getResultCode() == ResultCode.CLIENT_SIDE_USER_CANCELLED)
    if (result.getResultCode() == ResultCode.CLIENT_SIDE_USER_CANCELLED
        || result.getResultCode() == ResultCode.CANCELLED)
    {
      return new CancelledException(result);
      return new CancelledResultException(result);
    }
    if (result.getResultCode() == ResultCode.NO_SUCH_OBJECT
        || result.getResultCode() == ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
    {
      return new EntryNotFoundException(result);
    }
    if (result.getResultCode() == ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
    {
      return new MultipleEntriesFoundException(result);
    }
    return new ErrorResultException(result);
sdk/src/org/opends/sdk/Filter.java
@@ -90,14 +90,14 @@
  private static final class ApproxMatchImpl extends Impl
  {
    private final ByteSequence assertionValue;
    private final ByteString assertionValue;
    private final String attributeDescription;
    public ApproxMatchImpl(String attributeDescription,
        ByteSequence assertionValue)
        ByteString assertionValue)
    {
      this.attributeDescription = attributeDescription;
      this.assertionValue = assertionValue;
@@ -119,14 +119,14 @@
  private static final class EqualityMatchImpl extends Impl
  {
    private final ByteSequence assertionValue;
    private final ByteString assertionValue;
    private final String attributeDescription;
    public EqualityMatchImpl(String attributeDescription,
        ByteSequence assertionValue)
        ByteString assertionValue)
    {
      this.attributeDescription = attributeDescription;
      this.assertionValue = assertionValue;
@@ -153,12 +153,12 @@
    private final String matchingRule;
    private final ByteSequence matchValue;
    private final ByteString matchValue;
    public ExtensibleMatchImpl(String matchingRule,
        String attributeDescription, ByteSequence matchValue,
        String attributeDescription, ByteString matchValue,
        boolean dnAttributes)
    {
      this.matchingRule = matchingRule;
@@ -183,14 +183,14 @@
  private static final class GreaterOrEqualImpl extends Impl
  {
    private final ByteSequence assertionValue;
    private final ByteString assertionValue;
    private final String attributeDescription;
    public GreaterOrEqualImpl(String attributeDescription,
        ByteSequence assertionValue)
        ByteString assertionValue)
    {
      this.attributeDescription = attributeDescription;
      this.assertionValue = assertionValue;
@@ -226,14 +226,14 @@
  private static final class LessOrEqualImpl extends Impl
  {
    private final ByteSequence assertionValue;
    private final ByteString assertionValue;
    private final String attributeDescription;
    public LessOrEqualImpl(String attributeDescription,
        ByteSequence assertionValue)
        ByteString assertionValue)
    {
      this.attributeDescription = attributeDescription;
      this.assertionValue = assertionValue;
@@ -325,19 +325,19 @@
  private static final class SubstringsImpl extends Impl
  {
    private final List<ByteSequence> anyStrings;
    private final List<ByteString> anyStrings;
    private final String attributeDescription;
    private final ByteSequence finalString;
    private final ByteString finalString;
    private final ByteSequence initialString;
    private final ByteString initialString;
    public SubstringsImpl(String attributeDescription,
        ByteSequence initialString, List<ByteSequence> anyStrings,
        ByteSequence finalString)
        ByteString initialString, List<ByteString> anyStrings,
        ByteString finalString)
    {
      this.attributeDescription = attributeDescription;
      this.initialString = initialString;
@@ -362,13 +362,13 @@
  private static final class UnrecognizedImpl extends Impl
  {
    private final ByteSequence filterBytes;
    private final ByteString filterBytes;
    private final byte filterTag;
    public UnrecognizedImpl(byte filterTag, ByteSequence filterBytes)
    public UnrecognizedImpl(byte filterTag, ByteString filterBytes)
    {
      this.filterTag = filterTag;
      this.filterBytes = filterBytes;
@@ -412,7 +412,7 @@
    public StringBuilder visitApproxMatchFilter(StringBuilder builder,
        String attributeDescription, ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      builder.append('(');
      builder.append(attributeDescription);
@@ -426,7 +426,7 @@
    public StringBuilder visitEqualityMatchFilter(
        StringBuilder builder, String attributeDescription,
        ByteSequence assertionValue)
        ByteString assertionValue)
    {
      builder.append('(');
      builder.append(attributeDescription);
@@ -440,7 +440,7 @@
    public StringBuilder visitExtensibleMatchFilter(
        StringBuilder builder, String matchingRule,
        String attributeDescription, ByteSequence assertionValue,
        String attributeDescription, ByteString assertionValue,
        boolean dnAttributes)
    {
      builder.append('(');
@@ -471,7 +471,7 @@
    public StringBuilder visitGreaterOrEqualFilter(
        StringBuilder builder, String attributeDescription,
        ByteSequence assertionValue)
        ByteString assertionValue)
    {
      builder.append('(');
      builder.append(attributeDescription);
@@ -484,7 +484,7 @@
    public StringBuilder visitLessOrEqualFilter(StringBuilder builder,
        String attributeDescription, ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      builder.append('(');
      builder.append(attributeDescription);
@@ -533,8 +533,8 @@
    public StringBuilder visitSubstringsFilter(StringBuilder builder,
        String attributeDescription, ByteSequence initialSubstring,
        List<ByteSequence> anySubstrings, ByteSequence finalSubstring)
        String attributeDescription, ByteString initialSubstring,
        List<ByteString> anySubstrings, ByteString finalSubstring)
    {
      builder.append('(');
      builder.append(attributeDescription);
@@ -543,7 +543,7 @@
      {
        valueToFilterString(builder, initialSubstring);
      }
      for (ByteSequence anySubstring : anySubstrings)
      for (ByteString anySubstring : anySubstrings)
      {
        builder.append('*');
        valueToFilterString(builder, anySubstring);
@@ -560,7 +560,7 @@
    public StringBuilder visitUnrecognizedFilter(StringBuilder builder,
        byte filterTag, ByteSequence filterBytes)
        byte filterTag, ByteString filterBytes)
    {
      // Fake up a representation.
      builder.append('(');
@@ -723,10 +723,9 @@
   * @return The newly created {@code approximate match} filter.
   */
  public static Filter newApproxMatchFilter(
      String attributeDescription, ByteSequence assertionValue)
      String attributeDescription, ByteString assertionValue)
  {
    Validator.ensureNotNull(attributeDescription);
    Validator.ensureNotNull(assertionValue);
    Validator.ensureNotNull(attributeDescription, assertionValue);
    return new Filter(new ApproxMatchImpl(attributeDescription,
        assertionValue));
  }
@@ -734,6 +733,30 @@
  /**
   * Creates a new {@code approximate match} filter using the provided
   * attribute description and assertion value.
   * <p>
   * If {@code assertionValue} is not an instance of {@code ByteString}
   * then it will be converted using the
   * {@link ByteString#valueOf(Object)} method.
   *
   * @param attributeDescription
   *          The attribute description.
   * @param assertionValue
   *          The assertion value.
   * @return The newly created {@code approximate match} filter.
   */
  public static Filter newApproxMatchFilter(
      String attributeDescription, Object assertionValue)
  {
    Validator.ensureNotNull(attributeDescription, assertionValue);
    return new Filter(new ApproxMatchImpl(attributeDescription,
        ByteString.valueOf(assertionValue)));
  }
  /**
   * Creates a new {@code equality match} filter using the provided
   * attribute description and assertion value.
   *
@@ -744,10 +767,9 @@
   * @return The newly created {@code equality match} filter.
   */
  public static Filter newEqualityMatchFilter(
      String attributeDescription, ByteSequence assertionValue)
      String attributeDescription, ByteString assertionValue)
  {
    Validator.ensureNotNull(attributeDescription);
    Validator.ensureNotNull(assertionValue);
    Validator.ensureNotNull(attributeDescription, assertionValue);
    return new Filter(new EqualityMatchImpl(attributeDescription,
        assertionValue));
  }
@@ -755,6 +777,30 @@
  /**
   * Creates a new {@code equality match} filter using the provided
   * attribute description and assertion value.
   * <p>
   * If {@code assertionValue} is not an instance of {@code ByteString}
   * then it will be converted using the
   * {@link ByteString#valueOf(Object)} method.
   *
   * @param attributeDescription
   *          The attribute description.
   * @param assertionValue
   *          The assertion value.
   * @return The newly created {@code equality match} filter.
   */
  public static Filter newEqualityMatchFilter(
      String attributeDescription, Object assertionValue)
  {
    Validator.ensureNotNull(attributeDescription, assertionValue);
    return new Filter(new EqualityMatchImpl(attributeDescription,
        ByteString.valueOf(assertionValue)));
  }
  /**
   * Creates a new {@code extensible match} filter.
   *
   * @param matchingRule
@@ -770,7 +816,7 @@
   * @return The newly created {@code extensible match} filter.
   */
  public static Filter newExtensibleMatchFilter(String matchingRule,
      String attributeDescription, ByteSequence assertionValue,
      String attributeDescription, ByteString assertionValue,
      boolean dnAttributes)
  {
    Validator.ensureTrue((matchingRule != null)
@@ -784,6 +830,40 @@
  /**
   * Creates a new {@code extensible match} filter.
   * <p>
   * If {@code assertionValue} is not an instance of {@code ByteString}
   * then it will be converted using the
   * {@link ByteString#valueOf(Object)} method.
   *
   * @param matchingRule
   *          The matching rule name, may be {@code null} if {@code
   *          attributeDescription} is specified.
   * @param attributeDescription
   *          The attribute description, may be {@code null} if {@code
   *          matchingRule} is specified.
   * @param assertionValue
   *          The assertion value.
   * @param dnAttributes
   *          Indicates whether DN matching should be performed.
   * @return The newly created {@code extensible match} filter.
   */
  public static Filter newExtensibleMatchFilter(String matchingRule,
      String attributeDescription, Object assertionValue,
      boolean dnAttributes)
  {
    Validator.ensureTrue((matchingRule != null)
        || (attributeDescription != null), "matchingRule and/or "
        + "attributeDescription must not be null");
    Validator.ensureNotNull(assertionValue);
    return new Filter(new ExtensibleMatchImpl(matchingRule,
        attributeDescription, ByteString.valueOf(assertionValue),
        dnAttributes));
  }
  /**
   * Creates a new {@code greater or equal} filter using the provided
   * attribute description and assertion value.
   *
@@ -794,10 +874,9 @@
   * @return The newly created {@code greater or equal} filter.
   */
  public static Filter newGreaterOrEqualFilter(
      String attributeDescription, ByteSequence assertionValue)
      String attributeDescription, ByteString assertionValue)
  {
    Validator.ensureNotNull(attributeDescription);
    Validator.ensureNotNull(assertionValue);
    Validator.ensureNotNull(attributeDescription, assertionValue);
    return new Filter(new GreaterOrEqualImpl(attributeDescription,
        assertionValue));
  }
@@ -805,6 +884,30 @@
  /**
   * Creates a new {@code greater or equal} filter using the provided
   * attribute description and assertion value.
   * <p>
   * If {@code assertionValue} is not an instance of {@code ByteString}
   * then it will be converted using the
   * {@link ByteString#valueOf(Object)} method.
   *
   * @param attributeDescription
   *          The attribute description.
   * @param assertionValue
   *          The assertion value.
   * @return The newly created {@code greater or equal} filter.
   */
  public static Filter newGreaterOrEqualFilter(
      String attributeDescription, Object assertionValue)
  {
    Validator.ensureNotNull(attributeDescription, assertionValue);
    return new Filter(new GreaterOrEqualImpl(attributeDescription,
        ByteString.valueOf(assertionValue)));
  }
  /**
   * Creates a new {@code less or equal} filter using the provided
   * attribute description and assertion value.
   *
@@ -815,10 +918,9 @@
   * @return The newly created {@code less or equal} filter.
   */
  public static Filter newLessOrEqualFilter(
      String attributeDescription, ByteSequence assertionValue)
      String attributeDescription, ByteString assertionValue)
  {
    Validator.ensureNotNull(attributeDescription);
    Validator.ensureNotNull(assertionValue);
    Validator.ensureNotNull(attributeDescription, assertionValue);
    return new Filter(new LessOrEqualImpl(attributeDescription,
        assertionValue));
  }
@@ -826,6 +928,30 @@
  /**
   * Creates a new {@code less or equal} filter using the provided
   * attribute description and assertion value.
   * <p>
   * If {@code assertionValue} is not an instance of {@code ByteString}
   * then it will be converted using the
   * {@link ByteString#valueOf(Object)} method.
   *
   * @param attributeDescription
   *          The attribute description.
   * @param assertionValue
   *          The assertion value.
   * @return The newly created {@code less or equal} filter.
   */
  public static Filter newLessOrEqualFilter(
      String attributeDescription, Object assertionValue)
  {
    Validator.ensureNotNull(attributeDescription, assertionValue);
    return new Filter(new LessOrEqualImpl(attributeDescription,
        ByteString.valueOf(assertionValue)));
  }
  /**
   * Creates a new {@code not} filter using the provided sub-filter.
   *
   * @param subFilter
@@ -965,31 +1091,31 @@
   * @return The newly created {@code substrings} filter.
   */
  public static Filter newSubstringsFilter(String attributeDescription,
      ByteSequence initialSubstring, ByteSequence[] anySubstrings,
      ByteSequence finalSubstring)
      ByteString initialSubstring,
      Collection<ByteString> anySubstrings, ByteString finalSubstring)
  {
    Validator.ensureNotNull(attributeDescription);
    Validator.ensureTrue((initialSubstring != null)
        || (finalSubstring != null)
        || ((anySubstrings != null) && (anySubstrings.length > 0)),
        || ((anySubstrings != null) && (anySubstrings.size() > 0)),
        "at least one substring (initial, any or final)"
            + " must be specified");
    List<ByteSequence> anySubstringList;
    if ((anySubstrings == null) || (anySubstrings.length == 0))
    List<ByteString> anySubstringList;
    if ((anySubstrings == null) || (anySubstrings.size() == 0))
    {
      anySubstringList = Collections.emptyList();
    }
    else if (anySubstrings.length == 1)
    else if (anySubstrings.size() == 1)
    {
      Validator.ensureNotNull(anySubstrings[0]);
      anySubstringList = Collections.singletonList(anySubstrings[0]);
      ByteString anySubstring = anySubstrings.iterator().next();
      Validator.ensureNotNull(anySubstring);
      anySubstringList = Collections.singletonList(anySubstring);
    }
    else
    {
      anySubstringList = new ArrayList<ByteSequence>(
          anySubstrings.length);
      for (ByteSequence anySubstring : anySubstrings)
      anySubstringList = new ArrayList<ByteString>(anySubstrings.size());
      for (ByteString anySubstring : anySubstrings)
      {
        Validator.ensureNotNull(anySubstring);
@@ -1008,6 +1134,9 @@
   * Creates a new {@code substrings} filter using the provided
   * attribute description, {@code initial}, {@code final}, and {@code
   * any} sub-strings.
   * <p>
   * Any substrings which are not instances of {@code ByteString} will
   * be converted using the {@link ByteString#valueOf(Object)} method.
   *
   * @param attributeDescription
   *          The attribute description.
@@ -1026,9 +1155,8 @@
   * @return The newly created {@code substrings} filter.
   */
  public static Filter newSubstringsFilter(String attributeDescription,
      ByteSequence initialSubstring,
      Collection<ByteSequence> anySubstrings,
      ByteSequence finalSubstring)
      Object initialSubstring, Collection<?> anySubstrings,
      Object finalSubstring)
  {
    Validator.ensureNotNull(attributeDescription);
    Validator.ensureTrue((initialSubstring != null)
@@ -1037,32 +1165,33 @@
        "at least one substring (initial, any or final)"
            + " must be specified");
    List<ByteSequence> anySubstringList;
    List<ByteString> anySubstringList;
    if ((anySubstrings == null) || (anySubstrings.size() == 0))
    {
      anySubstringList = Collections.emptyList();
    }
    else if (anySubstrings.size() == 1)
    {
      ByteSequence anySubstring = anySubstrings.iterator().next();
      Object anySubstring = anySubstrings.iterator().next();
      Validator.ensureNotNull(anySubstring);
      anySubstringList = Collections.singletonList(anySubstring);
      anySubstringList = Collections.singletonList(ByteString
          .valueOf(anySubstring));
    }
    else
    {
      anySubstringList = new ArrayList<ByteSequence>(anySubstrings
          .size());
      for (ByteSequence anySubstring : anySubstrings)
      anySubstringList = new ArrayList<ByteString>(anySubstrings.size());
      for (Object anySubstring : anySubstrings)
      {
        Validator.ensureNotNull(anySubstring);
        anySubstringList.add(anySubstring);
        anySubstringList.add(ByteString.valueOf(anySubstring));
      }
      anySubstringList = Collections.unmodifiableList(anySubstringList);
    }
    return new Filter(new SubstringsImpl(attributeDescription,
        initialSubstring, anySubstringList, finalSubstring));
        ByteString.valueOf(initialSubstring), anySubstringList,
        ByteString.valueOf(finalSubstring)));
  }
@@ -1079,7 +1208,7 @@
   * @return The newly created {@code unrecognized} filter.
   */
  public static Filter newUnrecognizedFilter(byte filterTag,
      ByteSequence filterBytes)
      ByteString filterBytes)
  {
    Validator.ensureNotNull(filterBytes);
    return new Filter(new UnrecognizedImpl(filterTag, filterBytes));
@@ -1121,8 +1250,8 @@
      }
      else
      {
        LocalizableMessage message = ERR_LDAP_FILTER_MISMATCHED_PARENTHESES.get(
            string, 1, string.length());
        LocalizableMessage message = ERR_LDAP_FILTER_MISMATCHED_PARENTHESES
            .get(string, 1, string.length());
        throw new LocalizedIllegalArgumentException(message);
      }
    }
@@ -1205,7 +1334,7 @@
      // Look at the character immediately before the equal sign,
      // because it may help determine the filter type.
      String attributeDescription;
      ByteSequence assertionValue;
      ByteString assertionValue;
      switch (string.charAt(equalPos - 1))
      {
@@ -1244,7 +1373,7 @@
  private static ByteSequence valueOfAssertionValue(String string,
  private static ByteString valueOfAssertionValue(String string,
      int startIndex, int endIndex)
      throws LocalizedIllegalArgumentException
  {
@@ -1271,8 +1400,8 @@
          // the binary value.
          if ((i + 2) >= valueBytes.length)
          {
            LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE.get(
                string, startIndex + i + 1);
            LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE
                .get(string, startIndex + i + 1);
            throw new LocalizedIllegalArgumentException(message);
          }
@@ -1333,8 +1462,8 @@
            byteValue = (byte) 0xF0;
            break;
          default:
            LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE.get(
                string, startIndex + i + 1);
            LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE
                .get(string, startIndex + i + 1);
            throw new LocalizedIllegalArgumentException(message);
          }
@@ -1394,8 +1523,8 @@
            byteValue |= (byte) 0x0F;
            break;
          default:
            LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE.get(
                string, startIndex + i + 1);
            LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE
                .get(string, startIndex + i + 1);
            throw new LocalizedIllegalArgumentException(message);
          }
@@ -1596,7 +1725,7 @@
    }
    // Parse out the attribute value.
    ByteSequence matchValue = valueOfAssertionValue(string,
    ByteString matchValue = valueOfAssertionValue(string,
        equalIndex + 1, endIndex);
    // Make sure that the filter has at least one of an attribute
@@ -1733,12 +1862,12 @@
    else
    {
      // Either an equality or substring filter.
      ByteSequence assertionValue = valueOfAssertionValue(string,
      ByteString assertionValue = valueOfAssertionValue(string,
          startIndex, endIndex);
      ByteSequence initialString = null;
      ByteSequence finalString = null;
      LinkedList<ByteSequence> anyStrings = null;
      ByteString initialString = null;
      ByteString finalString = null;
      LinkedList<ByteString> anyStrings = null;
      int lastAsteriskIndex = -1;
      int length = assertionValue.length();
@@ -1760,15 +1889,15 @@
            // Got an any substring.
            if (anyStrings == null)
            {
              anyStrings = new LinkedList<ByteSequence>();
              anyStrings = new LinkedList<ByteString>();
            }
            int s = lastAsteriskIndex + 1;
            if (s == i)
            {
              // A zero length substring.
              LocalizableMessage message = ERR_LDAP_FILTER_BAD_SUBSTRING.get(
                  string, string.subSequence(startIndex, endIndex));
              LocalizableMessage message = ERR_LDAP_FILTER_BAD_SUBSTRING
                  .get(string, string.subSequence(startIndex, endIndex));
              throw new LocalizedIllegalArgumentException(message);
            }
@@ -1793,7 +1922,7 @@
      }
      else
      {
        List<ByteSequence> tmp;
        List<ByteString> tmp;
        if (anyStrings == null)
        {
@@ -1830,7 +1959,7 @@
   *          The value to be appended to the builder.
   */
  private static void valueToFilterString(StringBuilder builder,
      ByteSequence value)
      ByteString value)
  {
    // Get the binary representation of the value and iterate through
    // it to see if there are any unsafe characters. If there are,
sdk/src/org/opends/sdk/FilterVisitor.java
@@ -82,7 +82,7 @@
   * @return Returns a visitor specified result.
   */
  R visitApproxMatchFilter(P p, String attributeDescription,
      ByteSequence assertionValue);
      ByteString assertionValue);
@@ -98,7 +98,7 @@
   * @return Returns a visitor specified result.
   */
  R visitEqualityMatchFilter(P p, String attributeDescription,
      ByteSequence assertionValue);
      ByteString assertionValue);
@@ -120,7 +120,7 @@
   * @return Returns a visitor specified result.
   */
  R visitExtensibleMatchFilter(P p, String matchingRule,
      String attributeDescription, ByteSequence assertionValue,
      String attributeDescription, ByteString assertionValue,
      boolean dnAttributes);
@@ -137,7 +137,7 @@
   * @return Returns a visitor specified result.
   */
  R visitGreaterOrEqualFilter(P p, String attributeDescription,
      ByteSequence assertionValue);
      ByteString assertionValue);
@@ -153,7 +153,7 @@
   * @return Returns a visitor specified result.
   */
  R visitLessOrEqualFilter(P p, String attributeDescription,
      ByteSequence assertionValue);
      ByteString assertionValue);
@@ -216,8 +216,8 @@
   * @return Returns a visitor specified result.
   */
  R visitSubstringsFilter(P p, String attributeDescription,
      ByteSequence initialSubstring, List<ByteSequence> anySubstrings,
      ByteSequence finalSubstring);
      ByteString initialSubstring, List<ByteString> anySubstrings,
      ByteString finalSubstring);
@@ -232,6 +232,6 @@
   *          The filter content.
   * @return Returns a visitor specified result.
   */
  R visitUnrecognizedFilter(P p, byte filterTag, ByteSequence filterBytes);
  R visitUnrecognizedFilter(P p, byte filterTag, ByteString filterBytes);
}
sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
@@ -27,6 +27,9 @@
package org.opends.sdk;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CancellationException;
@@ -35,46 +38,89 @@
import java.util.concurrent.TimeoutException;
import org.opends.sdk.requests.*;
import org.opends.sdk.responses.BindResult;
import org.opends.sdk.responses.CompareResult;
import org.opends.sdk.responses.GenericExtendedResult;
import org.opends.sdk.responses.Result;
import org.opends.sdk.responses.*;
import org.opends.sdk.schema.Schema;
import com.sun.opends.sdk.util.Validator;
/**
 * An heart beat connection factory can be used to create
 * connections that sends a periodic search request to a Directory Server.
 * An heart beat connection factory can be used to create connections
 * that sends a periodic search request to a Directory Server.
 */
public class HeartBeatConnectionFactory
    extends AbstractConnectionFactory<
    HeartBeatConnectionFactory.HeartBeatAsynchronousConnection> {
public class HeartBeatConnectionFactory extends
    AbstractConnectionFactory<AsynchronousConnection>
{
  private final SearchRequest heartBeat;
  private final int interval;
  private final List<HeartBeatAsynchronousConnection> activeConnections;
  private final List<AsynchronousConnectionImpl> activeConnections;
  private final ConnectionFactory<?> parentFactory;
  private boolean stopRequested;
  private volatile boolean stopRequested;
  // FIXME: use a single global scheduler?
  // FIXME: change timeout parameters to long+TimeUnit.
  /**
   * Creates a new heart-beat connection factory which will create
   * connections using the provided connection factory and periodically
   * ping any created connections in order to detect that they are still
   * alive.
   *
   * @param connectionFactory
   *          The connection factory to use for creating connections.
   * @param interval
   *          The period between keepalive pings.
   */
  public HeartBeatConnectionFactory(
      ConnectionFactory<?> parentFactory,
      int interval) {
    this(parentFactory, Requests.newSearchRequest("", SearchScope.BASE_OBJECT,
        "(objectClass=*)", "1.1"), interval);
      ConnectionFactory<?> connectionFactory, int interval)
  {
    this(connectionFactory, DEFAULT_SEARCH, interval);
  }
  private static final SearchRequest DEFAULT_SEARCH = Requests
      .newSearchRequest("", SearchScope.BASE_OBJECT, "(objectClass=*)",
          "1.1");
  /**
   * Creates a new heart-beat connection factory which will create
   * connections using the provided connection factory and periodically
   * ping any created connections using the specified search request in
   * order to detect that they are still alive.
   *
   * @param connectionFactory
   *          The connection factory to use for creating connections.
   * @param heartBeat
   *          The search request to use when pinging connections.
   * @param interval
   *          The period between keepalive pings.
   */
  public HeartBeatConnectionFactory(
      ConnectionFactory<?> parentFactory,
      SearchRequest heartBeat, int interval) {
    Validator.ensureNotNull(parentFactory, heartBeat);
      ConnectionFactory<?> connectionFactory, SearchRequest heartBeat,
      int interval)
  {
    Validator.ensureNotNull(connectionFactory, heartBeat);
    this.heartBeat = heartBeat;
    this.interval = interval;
    this.activeConnections = new LinkedList<HeartBeatAsynchronousConnection>();
    this.parentFactory = parentFactory;
    this.activeConnections = new LinkedList<AsynchronousConnectionImpl>();
    this.parentFactory = connectionFactory;
    Runtime.getRuntime().addShutdownHook(new Thread() {
    Runtime.getRuntime().addShutdownHook(new Thread()
    {
      @Override
      public void run() {
      public void run()
      {
        stopRequested = true;
      }
    });
@@ -82,116 +128,227 @@
    new HeartBeatThread().start();
  }
  /**
   * An asynchronous connection that sends heart beats and supports all
   * operations.
   */
  public final class HeartBeatAsynchronousConnection
      implements AsynchronousConnection, ConnectionEventListener,
      ResultHandler<Result, Void> {
  private final class AsynchronousConnectionImpl implements
      AsynchronousConnection, ConnectionEventListener,
      ResultHandler<Result, Void>
  {
    private final AsynchronousConnection connection;
    public HeartBeatAsynchronousConnection(AsynchronousConnection connection) {
    private AsynchronousConnectionImpl(AsynchronousConnection connection)
    {
      this.connection = connection;
    }
    public void abandon(AbandonRequest request)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
        NullPointerException
    {
      connection.abandon(request);
    }
    public <P> ResultFuture<Result> add(
        AddRequest request,
    public <P> ResultFuture<Result> add(AddRequest request,
        ResultHandler<Result, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
        NullPointerException
    {
      return connection.add(request, handler, p);
    }
    public <P> ResultFuture<BindResult> bind(
        BindRequest request, ResultHandler<? super BindResult, P> handler, P p)
    public <P> ResultFuture<BindResult> bind(BindRequest request,
        ResultHandler<? super BindResult, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
        NullPointerException
    {
      return connection.bind(request, handler, p);
    }
    public void close() {
      synchronized (activeConnections) {
    public void close()
    {
      synchronized (activeConnections)
      {
        connection.removeConnectionEventListener(this);
        activeConnections.remove(this);
      }
      connection.close();
    }
    public void close(UnbindRequest request, String reason)
        throws NullPointerException {
      synchronized (activeConnections) {
        throws NullPointerException
    {
      synchronized (activeConnections)
      {
        connection.removeConnectionEventListener(this);
        activeConnections.remove(this);
      }
      connection.close(request, reason);
    }
    public <P> ResultFuture<CompareResult> compare(
        CompareRequest request, ResultHandler<? super CompareResult, P> handler,
        P p) throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
        CompareRequest request,
        ResultHandler<? super CompareResult, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return connection.compare(request, handler, p);
    }
    public <P> ResultFuture<Result> delete(
        DeleteRequest request,
        ResultHandler<Result, P> handler,
        P p)
    public <P> ResultFuture<Result> delete(DeleteRequest request,
        ResultHandler<Result, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
        NullPointerException
    {
      return connection.delete(request, handler, p);
    }
    public <R extends Result, P> ResultFuture<R> extendedRequest(
        ExtendedRequest<R> request, ResultHandler<? super R, P> handler, P p)
        ExtendedRequest<R> request,
        ResultHandler<? super R, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
        NullPointerException
    {
      return connection.extendedRequest(request, handler, p);
    }
    public <P> ResultFuture<Result> modify(
        ModifyRequest request,
        ResultHandler<Result, P> handler,
        P p)
    public <P> ResultFuture<Result> modify(ModifyRequest request,
        ResultHandler<Result, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
        NullPointerException
    {
      return connection.modify(request, handler, p);
    }
    public <P> ResultFuture<Result> modifyDN(
        ModifyDNRequest request,
        ResultHandler<Result, P> handler,
        P p)
    public <P> ResultFuture<Result> modifyDN(ModifyDNRequest request,
        ResultHandler<Result, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
        NullPointerException
    {
      return connection.modifyDN(request, handler, p);
    }
    public <P> ResultFuture<Result> search(
        SearchRequest request, ResultHandler<Result, P> resultHandler,
    public <P> ResultFuture<Result> search(SearchRequest request,
        ResultHandler<Result, P> resultHandler,
        SearchResultHandler<P> searchResultHandler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException {
      return connection.search(request, resultHandler, searchResultHandler, p);
        NullPointerException
    {
      return connection.search(request, resultHandler,
          searchResultHandler, p);
    }
    public void addConnectionEventListener(ConnectionEventListener listener)
        throws IllegalStateException, NullPointerException {
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<SearchResultEntry> readEntry(DN name,
        Collection<String> attributeDescriptions,
        ResultHandler<? super SearchResultEntry, P> resultHandler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return connection.readEntry(name, attributeDescriptions,
          resultHandler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<SearchResultEntry> searchSingleEntry(
        SearchRequest request,
        ResultHandler<? super SearchResultEntry, P> resultHandler, P p)
        throws UnsupportedOperationException, IllegalStateException,
        NullPointerException
    {
      return connection.searchSingleEntry(request, resultHandler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<RootDSE> readRootDSE(
        ResultHandler<RootDSE, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException
    {
      return connection.readRootDSE(handler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<Schema> readSchemaForEntry(DN name,
        ResultHandler<Schema, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException
    {
      return connection.readSchemaForEntry(name, handler, p);
    }
    /**
     * {@inheritDoc}
     */
    public <P> ResultFuture<Schema> readSchema(DN name,
        ResultHandler<Schema, P> handler, P p)
        throws UnsupportedOperationException, IllegalStateException
    {
      return connection.readSchema(name, handler, p);
    }
    public void addConnectionEventListener(
        ConnectionEventListener listener) throws IllegalStateException,
        NullPointerException
    {
      connection.addConnectionEventListener(listener);
    }
    public void removeConnectionEventListener(ConnectionEventListener listener)
        throws NullPointerException {
    public void removeConnectionEventListener(
        ConnectionEventListener listener) throws NullPointerException
    {
      connection.removeConnectionEventListener(listener);
    }
    /**
     * {@inheritDoc}
     */
@@ -200,62 +357,93 @@
      return connection.isClosed();
    }
    public void connectionReceivedUnsolicitedNotification(
        GenericExtendedResult notification) {
        GenericExtendedResult notification)
    {
      // Do nothing
    }
    public void connectionErrorOccurred(
        boolean isDisconnectNotification,
        ErrorResultException error) {
      synchronized (activeConnections) {
        boolean isDisconnectNotification, ErrorResultException error)
    {
      synchronized (activeConnections)
      {
        connection.removeConnectionEventListener(this);
        activeConnections.remove(this);
      }
    }
    public void handleErrorResult(Void aVoid, ErrorResultException error) {
    public void handleErrorResult(Void aVoid, ErrorResultException error)
    {
      // TODO: I18N
      if(error instanceof OperationTimeoutException)
      if (error instanceof TimeoutResultException)
      {
        close(Requests.newUnbindRequest(), "Heart beat timed out");
      }
    }
    public void handleResult(Void aVoid, Result result) {
    public void handleResult(Void aVoid, Result result)
    {
      // Do nothing
    }
    private void sendHeartBeat() {
    private void sendHeartBeat()
    {
      search(heartBeat, this, null, null);
    }
  }
  private final class HeartBeatThread extends Thread {
    private HeartBeatThread() {
  private final class HeartBeatThread extends Thread
  {
    private HeartBeatThread()
    {
      super("Heart Beat Thread");
    }
    public void run() {
      while (!stopRequested) {
        synchronized (activeConnections) {
          for (HeartBeatAsynchronousConnection connection : activeConnections) {
    public void run()
    {
      while (!stopRequested)
      {
        synchronized (activeConnections)
        {
          for (AsynchronousConnectionImpl connection : activeConnections)
          {
            connection.sendHeartBeat();
          }
        }
        try {
        try
        {
          sleep(interval);
        } catch (InterruptedException e) {
        }
        catch (InterruptedException e)
        {
          // Ignore
        }
      }
    }
  }
  private final class ConnectionFutureImpl<P> implements
      ConnectionFuture<HeartBeatAsynchronousConnection>,
      ConnectionResultHandler<AsynchronousConnection, Void> {
    private volatile HeartBeatAsynchronousConnection heartBeatConnection;
      ConnectionFuture<AsynchronousConnection>,
      ConnectionResultHandler<AsynchronousConnection, Void>
  {
    private volatile AsynchronousConnectionImpl heartBeatConnection;
    private volatile ErrorResultException exception;
@@ -263,102 +451,124 @@
    private final CountDownLatch latch = new CountDownLatch(1);
    private final
    ConnectionResultHandler<? super HeartBeatAsynchronousConnection, P> handler;
    private final ConnectionResultHandler<? super AsynchronousConnectionImpl, P> handler;
    private final P p;
    private boolean cancelled;
    private ConnectionFutureImpl(
        ConnectionResultHandler<
            ? super HeartBeatAsynchronousConnection, P> handler,
        P p) {
        ConnectionResultHandler<? super AsynchronousConnectionImpl, P> handler,
        P p)
    {
      this.handler = handler;
      this.p = p;
    }
    public boolean cancel(boolean mayInterruptIfRunning) {
    public boolean cancel(boolean mayInterruptIfRunning)
    {
      cancelled = connectFuture.cancel(mayInterruptIfRunning);
      if (cancelled) {
      if (cancelled)
      {
        latch.countDown();
      }
      return cancelled;
    }
    public HeartBeatAsynchronousConnection get()
        throws InterruptedException, ErrorResultException {
    public AsynchronousConnectionImpl get()
        throws InterruptedException, ErrorResultException
    {
      latch.await();
      if (cancelled) {
      if (cancelled)
      {
        throw new CancellationException();
      }
      if (exception != null) {
      if (exception != null)
      {
        throw exception;
      }
      return heartBeatConnection;
    }
    public HeartBeatAsynchronousConnection get(
        long timeout,
        TimeUnit unit) throws InterruptedException, TimeoutException,
        ErrorResultException {
    public AsynchronousConnectionImpl get(long timeout, TimeUnit unit)
        throws InterruptedException, TimeoutException,
        ErrorResultException
    {
      latch.await(timeout, unit);
      if (cancelled) {
      if (cancelled)
      {
        throw new CancellationException();
      }
      if (exception != null) {
      if (exception != null)
      {
        throw exception;
      }
      return heartBeatConnection;
    }
    public boolean isCancelled() {
    public boolean isCancelled()
    {
      return cancelled;
    }
    public boolean isDone() {
    public boolean isDone()
    {
      return latch.getCount() == 0;
    }
    public void handleConnection(
        Void v,
        AsynchronousConnection connection) {
      heartBeatConnection = new HeartBeatAsynchronousConnection(connection);
      synchronized (activeConnections) {
    public void handleConnection(Void v,
        AsynchronousConnection connection)
    {
      heartBeatConnection = new AsynchronousConnectionImpl(connection);
      synchronized (activeConnections)
      {
        connection.addConnectionEventListener(heartBeatConnection);
        activeConnections.add(heartBeatConnection);
      }
      if (handler != null) {
      if (handler != null)
      {
        handler.handleConnection(p, heartBeatConnection);
      }
      latch.countDown();
    }
    public void handleConnectionError(Void v, ErrorResultException error) {
    public void handleConnectionError(Void v, ErrorResultException error)
    {
      exception = error;
      if (handler != null) {
      if (handler != null)
      {
        handler.handleConnectionError(p, error);
      }
      latch.countDown();
    }
  }
  public <P> ConnectionFuture<? extends HeartBeatAsynchronousConnection>
  getAsynchronousConnection(
      ConnectionResultHandler<? super
          HeartBeatAsynchronousConnection, P> pConnectionResultHandler, P p) {
    ConnectionFutureImpl<P> future =
        new ConnectionFutureImpl<P>(pConnectionResultHandler, p);
    future.connectFuture =
        parentFactory.getAsynchronousConnection(future, null);
  public <P> ConnectionFuture<AsynchronousConnection> getAsynchronousConnection(
      ConnectionResultHandler<? super AsynchronousConnection, P> handler,
      P p)
  {
    ConnectionFutureImpl<P> future = new ConnectionFutureImpl<P>(
        handler, p);
    future.connectFuture = parentFactory.getAsynchronousConnection(
        future, null);
    return future;
  }
}
sdk/src/org/opends/sdk/Matcher.java
@@ -43,6 +43,7 @@
import com.sun.opends.sdk.util.StaticUtils;
/**
 * An interface for determining whether entries match a {@code Filter}.
 */
@@ -83,9 +84,13 @@
  private static class AssertionMatcherImpl extends MatcherImpl
  {
    private final Assertion assertion;
    private final AttributeDescription attributeDescription;
    private final boolean dnAttributes;
    private final MatchingRule rule;
    private final MatchingRuleUse ruleUse;
@@ -117,8 +122,8 @@
        // If the type field is present and the matchingRule is present,
        // the matchValue is compared against the specified attribute
        // type and its subtypes.
        final ConditionResult p = Matcher.matches(
            entry.getAttribute(attributeDescription), rule, assertion);
        final ConditionResult p = Matcher.matches(entry
            .getAttribute(attributeDescription), rule, assertion);
        if (p == ConditionResult.TRUE)
        {
          return p;
@@ -135,7 +140,8 @@
          if (ruleUse.hasAttribute(a.getAttributeDescription()
              .getAttributeType()))
          {
            final ConditionResult p = Matcher.matches(a, rule, assertion);
            final ConditionResult p = Matcher.matches(a, rule,
                assertion);
            if (p == ConditionResult.TRUE)
            {
              return p;
@@ -160,8 +166,8 @@
          {
            if (ruleUse.hasAttribute(ava.getAttributeType()))
            {
              final ConditionResult p =
                  Matcher.matches(ava.getAttributeValue(), rule, assertion);
              final ConditionResult p = Matcher.matches(ava
                  .getAttributeValue(), rule, assertion);
              if (p == ConditionResult.TRUE)
              {
                return p;
@@ -307,14 +313,14 @@
      {
        if(DEBUG_LOG.isLoggable(Level.FINER))
        {
          DEBUG_LOG.finer("Empty add filter component. " +
                          "Will always return TRUE");
          DEBUG_LOG.finer("Empty add filter component. "
              + "Will always return TRUE");
        }
        return TRUE;
      }
      final List<MatcherImpl> subMatchers =
          new ArrayList<MatcherImpl>(subFilters.size());
      final List<MatcherImpl> subMatchers = new ArrayList<MatcherImpl>(
          subFilters.size());
      for (final Filter f : subFilters)
      {
        subMatchers.add(f.accept(this, schema));
@@ -325,7 +331,7 @@
    public MatcherImpl visitApproxMatchFilter(Schema schema,
                                              String attributeDescription, ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      AttributeDescription ad;
      MatchingRule rule;
@@ -339,9 +345,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "Attribute description " + attributeDescription  +
              " is not recognized: " + e.toString());
          DEBUG_LOG.warning("Attribute description "
              + attributeDescription + " is not recognized: "
              + e.toString());
        }
        return UNDEFINED;
      }
@@ -350,9 +356,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The attribute type " + attributeDescription +
              " does not define an approximate matching rule");
          DEBUG_LOG.warning("The attribute type "
              + attributeDescription
              + " does not define an approximate matching rule");
        }
        return UNDEFINED;
      }
@@ -365,9 +371,8 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The assertion value " + assertionValue + " is invalid: " +
              de.toString());
          DEBUG_LOG.warning("The assertion value " + assertionValue
              + " is invalid: " + de.toString());
        }
        return UNDEFINED;
      }
@@ -377,7 +382,7 @@
    public MatcherImpl visitEqualityMatchFilter(Schema schema,
                                                String attributeDescription, ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      AttributeDescription ad;
      MatchingRule rule;
@@ -391,9 +396,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "Attribute description " + attributeDescription  +
              " is not recognized: " + e.toString());
          DEBUG_LOG.warning("Attribute description "
              + attributeDescription + " is not recognized: "
              + e.toString());
        }
        return UNDEFINED;
      }
@@ -402,9 +407,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The attribute type " + attributeDescription +
              " does not define an equality matching rule");
          DEBUG_LOG.warning("The attribute type "
              + attributeDescription
              + " does not define an equality matching rule");
        }
        return UNDEFINED;
      }
@@ -417,9 +422,8 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The assertion value " + assertionValue + " is invalid: " +
              de.toString());
          DEBUG_LOG.warning("The assertion value " + assertionValue
              + " is invalid: " + de.toString());
        }
        return UNDEFINED;
      }
@@ -429,10 +433,8 @@
    public MatcherImpl visitExtensibleMatchFilter(Schema schema,
                                                  String matchingRule,
                                                  String attributeDescription,
                                                  ByteSequence assertionValue,
                                                  boolean dnAttributes)
        String matchingRule, String attributeDescription,
        ByteString assertionValue, boolean dnAttributes)
    {
      AttributeDescription ad = null;
      MatchingRule rule = null;
@@ -449,9 +451,8 @@
        {
          if(DEBUG_LOG.isLoggable(Level.WARNING))
          {
            DEBUG_LOG.warning(
                "Matching rule " + matchingRule  + " is not recognized: " +
                e.toString());
            DEBUG_LOG.warning("Matching rule " + matchingRule
                + " is not recognized: " + e.toString());
          }
          return UNDEFINED;
        }
@@ -461,17 +462,16 @@
      {
        try
        {
          ad =
              AttributeDescription
                  .valueOf(attributeDescription, schema);
          ad = AttributeDescription.valueOf(attributeDescription,
              schema);
        }
        catch (final LocalizedIllegalArgumentException e)
        {
          if(DEBUG_LOG.isLoggable(Level.WARNING))
          {
            DEBUG_LOG.warning(
                "Attribute description " + attributeDescription  +
                " is not recognized: " + e.toString());
            DEBUG_LOG.warning("Attribute description "
                + attributeDescription + " is not recognized: "
                + e.toString());
          }
          return UNDEFINED;
        }
@@ -482,9 +482,9 @@
          {
            if(DEBUG_LOG.isLoggable(Level.WARNING))
            {
              DEBUG_LOG.warning(
                  "The attribute type " + attributeDescription +
                  " does not define an equality matching rule");
              DEBUG_LOG.warning("The attribute type "
                  + attributeDescription
                  + " does not define an equality matching rule");
            }
            return UNDEFINED;
          }
@@ -499,8 +499,8 @@
          {
            if(DEBUG_LOG.isLoggable(Level.WARNING))
            {
              DEBUG_LOG.warning("No matching rule use is defined for " +
                                "matching rule " + matchingRule);
              DEBUG_LOG.warning("No matching rule use is defined for "
                  + "matching rule " + matchingRule);
              return UNDEFINED;
            }
          }
@@ -508,9 +508,9 @@
          {
            if(DEBUG_LOG.isLoggable(Level.WARNING))
            {
              DEBUG_LOG.warning("The matching rule " + matchingRule +
                                " is not valid for attribute type " +
                                attributeDescription);
              DEBUG_LOG.warning("The matching rule " + matchingRule
                  + " is not valid for attribute type "
                  + attributeDescription);
            }
            return UNDEFINED;
          }
@@ -526,8 +526,8 @@
        {
          if(DEBUG_LOG.isLoggable(Level.WARNING))
          {
            DEBUG_LOG.warning("No matching rule use is defined for " +
                              "matching rule " + matchingRule);
            DEBUG_LOG.warning("No matching rule use is defined for "
                + "matching rule " + matchingRule);
          }
          return UNDEFINED;
        }
@@ -541,9 +541,8 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The assertion value " + assertionValue + " is invalid: " +
              de.toString());
          DEBUG_LOG.warning("The assertion value " + assertionValue
              + " is invalid: " + de.toString());
        }
        return UNDEFINED;
      }
@@ -554,8 +553,7 @@
    public MatcherImpl visitGreaterOrEqualFilter(Schema schema,
                                                 String attributeDescription,
                                                 ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      AttributeDescription ad;
      MatchingRule rule;
@@ -569,9 +567,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "Attribute description " + attributeDescription  +
              " is not recognized: " + e.toString());
          DEBUG_LOG.warning("Attribute description "
              + attributeDescription + " is not recognized: "
              + e.toString());
        }
        return UNDEFINED;
      }
@@ -580,9 +578,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The attribute type " + attributeDescription +
              " does not define an ordering matching rule");
          DEBUG_LOG.warning("The attribute type "
              + attributeDescription
              + " does not define an ordering matching rule");
        }
        return UNDEFINED;
      }
@@ -595,9 +593,8 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The assertion value " + assertionValue + " is invalid: " +
              de.toString());
          DEBUG_LOG.warning("The assertion value " + assertionValue
              + " is invalid: " + de.toString());
        }
        return UNDEFINED;
      }
@@ -607,8 +604,7 @@
    public MatcherImpl visitLessOrEqualFilter(Schema schema,
                                              String attributeDescription,
                                              ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      AttributeDescription ad;
      MatchingRule rule;
@@ -622,9 +618,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "Attribute description " + attributeDescription  +
              " is not recognized: " + e.toString());
          DEBUG_LOG.warning("Attribute description "
              + attributeDescription + " is not recognized: "
              + e.toString());
        }
        return UNDEFINED;
      }
@@ -633,9 +629,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The attribute type " + attributeDescription +
              " does not define an ordering matching rule");
          DEBUG_LOG.warning("The attribute type "
              + attributeDescription
              + " does not define an ordering matching rule");
        }
        return UNDEFINED;
      }
@@ -648,9 +644,8 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The assertion value " + assertionValue + " is invalid: " +
              de.toString());
          DEBUG_LOG.warning("The assertion value " + assertionValue
              + " is invalid: " + de.toString());
        }
        return UNDEFINED;
      }
@@ -674,14 +669,14 @@
      {
        if(DEBUG_LOG.isLoggable(Level.FINER))
        {
          DEBUG_LOG.finer("Empty or filter component. " +
                          "Will always return FALSE");
          DEBUG_LOG.finer("Empty or filter component. "
              + "Will always return FALSE");
        }
        return FALSE;
      }
      final List<MatcherImpl> subMatchers =
          new ArrayList<MatcherImpl>(subFilters.size());
      final List<MatcherImpl> subMatchers = new ArrayList<MatcherImpl>(
          subFilters.size());
      for (final Filter f : subFilters)
      {
        subMatchers.add(f.accept(this, schema));
@@ -703,9 +698,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "Attribute description " + attributeDescription  +
              " is not recognized: " + e.toString());
          DEBUG_LOG.warning("Attribute description "
              + attributeDescription + " is not recognized: "
              + e.toString());
        }
        return UNDEFINED;
      }
@@ -716,10 +711,8 @@
    public MatcherImpl visitSubstringsFilter(Schema schema,
                                             String attributeDescription,
                                             ByteSequence initialSubstring,
                                             List<ByteSequence> anySubstrings,
                                             ByteSequence finalSubstring)
        String attributeDescription, ByteString initialSubstring,
        List<ByteString> anySubstrings, ByteString finalSubstring)
    {
      AttributeDescription ad;
      MatchingRule rule;
@@ -733,9 +726,9 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "Attribute description " + attributeDescription  +
              " is not recognized: " + e.toString());
          DEBUG_LOG.warning("Attribute description "
              + attributeDescription + " is not recognized: "
              + e.toString());
        }
        return UNDEFINED;
      }
@@ -744,26 +737,25 @@
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The attribute type " + attributeDescription +
              " does not define an substring matching rule");
          DEBUG_LOG.warning("The attribute type "
              + attributeDescription
              + " does not define an substring matching rule");
        }
        return UNDEFINED;
      }
      try
      {
        assertion =
            rule.getAssertion(initialSubstring, anySubstrings,
        assertion = rule.getAssertion(initialSubstring, anySubstrings,
                              finalSubstring);
      }
      catch (final DecodeException de)
      {
        if(DEBUG_LOG.isLoggable(Level.WARNING))
        {
          DEBUG_LOG.warning(
              "The substring assertion values contain an invalid value: " +
              de.toString());
          DEBUG_LOG
              .warning("The substring assertion values contain an invalid value: "
                  + de.toString());
        }
        return UNDEFINED;
      }
@@ -773,28 +765,26 @@
    public MatcherImpl visitUnrecognizedFilter(Schema schema,
                                               byte filterTag,
                                               ByteSequence filterBytes)
        byte filterTag, ByteString filterBytes)
    {
      if(DEBUG_LOG.isLoggable(Level.WARNING))
      {
        DEBUG_LOG.warning("The type of filtering requested with tag " +
                          StaticUtils.byteToHex(filterTag) +
                          " is not implemented");
        DEBUG_LOG.warning("The type of filtering requested with tag "
            + StaticUtils.byteToHex(filterTag) + " is not implemented");
      }
      return UNDEFINED;
    }
  }
  private static final MatcherImpl FALSE = new FalseMatcherImpl();
  private static final MatcherImpl TRUE = new TrueMatcherImpl();
  private static final MatcherImpl UNDEFINED =
      new UndefinedMatcherImpl();
  private static final MatcherImpl UNDEFINED = new UndefinedMatcherImpl();
  private static final FilterVisitor<MatcherImpl, Schema> VISITOR =
      new Visitor();
  private static final FilterVisitor<MatcherImpl, Schema> VISITOR = new Visitor();
@@ -826,22 +816,25 @@
  {
    try
    {
      final ByteString normalizedValue =
          rule.normalizeAttributeValue(v);
      final ByteString normalizedValue = rule
          .normalizeAttributeValue(v);
      return assertion.matches(normalizedValue);
    }
    catch (final DecodeException de)
    {
      if(DEBUG_LOG.isLoggable(Level.WARNING))
      {
        DEBUG_LOG.warning("The attribute value " + v.toString() + " is " +
                         "invalid for matching rule " + rule.getNameOrOID() +
                         ". Possible schema error? : " + de.toString());
        DEBUG_LOG.warning("The attribute value " + v.toString()
            + " is " + "invalid for matching rule "
            + rule.getNameOrOID() + ". Possible schema error? : "
            + de.toString());
      }
      return ConditionResult.UNDEFINED;
    }
  }
  private final MatcherImpl impl;
sdk/src/org/opends/sdk/MultipleEntriesFoundException.java
copy from sdk/src/org/opends/sdk/CancelledException.java copy to sdk/src/org/opends/sdk/MultipleEntriesFoundException.java
File was copied from sdk/src/org/opends/sdk/CancelledException.java
@@ -35,12 +35,17 @@
/**
 * Thrown when the result code returned in a Result indicates that the
 * Request was cancelled.
 * requested single entry search operation or read operation failed
 * because the Directory Server returned multiple matching entries (or
 * search references) when only a single matching entry was expected.
 * More specifically, this exception is used for the
 * {@link ResultCode#CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED} error
 * result codes.
 */
@SuppressWarnings("serial")
public class CancelledException extends ErrorResultException
public class MultipleEntriesFoundException extends ErrorResultException
{
  CancelledException(Result result)
  MultipleEntriesFoundException(Result result)
  {
    super(result);
  }
sdk/src/org/opends/sdk/ResultCode.java
@@ -37,7 +37,6 @@
/**
 * An operation result code as defined in RFC 4511 section 4.1.9 is used
 * to indicate the final status of an operation. If a server detects
@@ -483,22 +482,23 @@
      93, INFO_RESULT_CLIENT_SIDE_CONTROL_NOT_FOUND.get());
  /**
   * The client-side result code that indicates that the server did not
   * return any results for a search operation that was expected to
   * match at least one entry. This is for client-side use only and
   * should never be transferred over protocol.
   * The client-side result code that indicates that the requested
   * single entry search operation or read operation failed because the
   * Directory Server did not return any matching entries. This is for
   * client-side use only and should never be transferred over protocol.
   */
  public static final ResultCode CLIENT_SIDE_NO_RESULTS_RETURNED = registerErrorResultCode(
      94, INFO_RESULT_CLIENT_SIDE_NO_RESULTS_RETURNED.get());
  /**
   * The client-side result code that indicates that the server has
   * returned more matching entries for a search operation than have
   * been processed so far. This is for client-side use only and should
   * never be transferred over protocol.
   * The client-side result code that the requested single entry search
   * operation or read operation failed because the Directory Server
   * returned multiple matching entries (or search references) when only
   * a single matching entry was expected. This is for client-side use
   * only and should never be transferred over protocol.
   */
  public static final ResultCode CLIENT_SIDE_MORE_RESULTS_TO_RETURN = registerErrorResultCode(
      95, INFO_RESULT_CLIENT_SIDE_MORE_RESULTS_TO_RETURN.get());
  public static final ResultCode CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED = registerErrorResultCode(
      95, INFO_RESULT_CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED.get());
  /**
   * The client-side result code that indicates that the client detected
@@ -523,7 +523,7 @@
   * The result code that indicates that a cancel request was
   * successful, or that the specified operation was canceled.
   */
  public static final ResultCode CANCELED = registerErrorResultCode(
  public static final ResultCode CANCELLED = registerErrorResultCode(
      118, INFO_RESULT_CANCELED.get());
  /**
@@ -637,8 +637,8 @@
    if (resultCode == null)
    {
      resultCode = new ResultCode(intValue, LocalizableMessage.raw("undefined("
          + intValue + ")"), true);
      resultCode = new ResultCode(intValue, LocalizableMessage
          .raw("undefined(" + intValue + ")"), true);
    }
    return resultCode;
@@ -670,7 +670,8 @@
  // Prevent direct instantiation.
  private ResultCode(int intValue, LocalizableMessage name, boolean exceptional)
  private ResultCode(int intValue, LocalizableMessage name,
      boolean exceptional)
  {
    this.intValue = intValue;
    this.name = name;
sdk/src/org/opends/sdk/ResultFuture.java
@@ -34,8 +34,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.opends.sdk.responses.Result;
/**
@@ -45,7 +43,7 @@
 * @param <S>
 *          The type of result returned by this future.
 */
public interface ResultFuture<S extends Result> extends Future<S>
public interface ResultFuture<S> extends Future<S>
{
  /**
   * Attempts to cancel the request. This attempt will fail if the
@@ -78,16 +76,17 @@
   * 
   * @return The result, but only if the result code indicates that the
   *         request succeeded.
   * @throws CancellationException
   *           If the request was cancelled using a call to
   *           {@link #cancel}.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws CancellationException
   *           If the request was cancelled using a call to
   *           {@link #cancel}.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   */
  S get() throws InterruptedException, ErrorResultException;
  S get() throws ErrorResultException, CancellationException,
      InterruptedException;
@@ -103,19 +102,19 @@
   *          The time unit of the timeout argument.
   * @return The result, but only if the result code indicates that the
   *         request succeeded.
   * @throws CancellationException
   *           If the request was cancelled using a call to
   *           {@link #cancel}.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws TimeoutException
   *           If the wait timed out.
   * @throws CancellationException
   *           If the request was cancelled using a call to
   *           {@link #cancel}.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   */
  S get(long timeout, TimeUnit unit) throws InterruptedException,
      TimeoutException, ErrorResultException;
  S get(long timeout, TimeUnit unit) throws ErrorResultException,
      TimeoutException, CancellationException, InterruptedException;
sdk/src/org/opends/sdk/ResultHandler.java
@@ -27,12 +27,6 @@
package org.opends.sdk;
import org.opends.sdk.responses.Result;
/**
 * A completion handler for consuming the result of an asynchronous
 * operation.
@@ -54,7 +48,7 @@
 *          methods. Use {@link java.lang.Void} for visitors that do not
 *          need an additional parameter.
 */
public interface ResultHandler<S extends Result, P>
public interface ResultHandler<S, P>
{
  /**
   * Invoked when the asynchronous operation has failed.
sdk/src/org/opends/sdk/RootDSE.java
@@ -32,432 +32,476 @@
import java.util.Collection;
import java.util.Collections;
import org.opends.sdk.requests.Requests;
import org.opends.sdk.requests.SearchRequest;
import org.opends.sdk.responses.SearchResultEntry;
import org.opends.sdk.schema.SchemaNotFoundException;
import org.opends.sdk.schema.CoreSchema;
import com.sun.opends.sdk.util.Functions;
import com.sun.opends.sdk.util.Iterables;
import com.sun.opends.sdk.util.Validator;
import com.sun.opends.sdk.util.*;
/**
 * Root DSE Entry.
 * The root DSE is a DSA-specific Entry (DSE) and not part of any naming
 * context (or any subtree), and which is uniquely identified by the
 * empty DN.
 * <p>
 * A Directory Server uses the root DSE to provide information about
 * itself using the following set of attributes:
 * <ul>
 * <li>{@code altServer}: alternative Directory Servers
 * <li>{@code namingContexts}: naming contexts
 * <li>{@code supportedControl}: recognized LDAP controls
 * <li>{@code supportedExtension}: recognized LDAP extended operations
 * <li>{@code supportedFeatures}: recognized LDAP features
 * <li>{@code supportedLDAPVersion}: LDAP versions supported
 * <li>{@code supportedSASLMechanisms}: recognized SASL authentication
 * mechanisms
 * <li>{@code supportedAuthPasswordSchemes}: recognized authentication
 * password schemes
 * <li>{@code subschemaSubentry}: the name of the subschema subentry
 * holding the schema controlling the Root DSE
 * <li>{@code vendorName}: the name of the Directory Server implementer
 * <li>{@code vendorVersion}: the version of the Directory Server
 * implementation.
 * </ul>
 * The values provided for these attributes may depend on session-
 * specific and other factors. For example, a server supporting the SASL
 * EXTERNAL mechanism might only list "EXTERNAL" when the client's
 * identity has been established by a lower level.
 * <p>
 * The root DSE may also include a {@code subschemaSubentry} attribute.
 * If it does, the attribute refers to the subschema (sub)entry holding
 * the schema controlling the root DSE. Clients SHOULD NOT assume that
 * this subschema (sub)entry controls other entries held by the server.
 *
 * @see <a href="http://tools.ietf.org/html/rfc4512">RFC 4512 -
 *      Lightweight Directory Access Protocol (LDAP): Directory
 *      Information Models </a>
 * @see <a href="http://tools.ietf.org/html/rfc3045">RFC 3045 - Storing
 *      Vendor Information in the LDAP Root DSE </a>
 * @see <a href="http://tools.ietf.org/html/rfc3112">RFC 3112 - LDAP
 *      Authentication Password Schema </a>
 */
public class RootDSE extends AbstractEntry
public final class RootDSE
{
  private static final AttributeDescription ATTR_ALT_SERVER = AttributeDescription
      .valueOf("altServer");
      .create(CoreSchema.getAltServerAttributeType());
  private static final AttributeDescription ATTR_NAMING_CONTEXTS = AttributeDescription
      .valueOf("namingContexts");
      .create(CoreSchema.getNamingContextsAttributeType());
  private static final AttributeDescription ATTR_SUPPORTED_CONTROL = AttributeDescription
      .valueOf("supportedControl");
      .create(CoreSchema.getSupportedControlAttributeType());
  private static final AttributeDescription ATTR_SUPPORTED_EXTENSION = AttributeDescription
      .valueOf("supportedExtension");
      .create(CoreSchema.getSupportedExtensionAttributeType());
  private static final AttributeDescription ATTR_SUPPORTED_FEATURE = AttributeDescription
      .valueOf("supportedFeatures");
      .create(CoreSchema.getSupportedFeaturesAttributeType());
  private static final AttributeDescription ATTR_SUPPORTED_LDAP_VERSION = AttributeDescription
      .valueOf("supportedLDAPVersion");
      .create(CoreSchema.getSupportedLDAPVersionAttributeType());
  private static final AttributeDescription ATTR_SUPPORTED_SASL_MECHANISMS = AttributeDescription
      .valueOf("supportedSASLMechanisms");
      .create(CoreSchema.getSupportedSASLMechanismsAttributeType());
  private static final AttributeDescription ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES = AttributeDescription
      .valueOf("supportedAuthPasswordSchemes");
      .create(CoreSchema.getSupportedAuthPasswordSchemesAttributeType());
  private static final AttributeDescription ATTR_SUBSCHEMA_SUBENTRY = AttributeDescription
      .create(CoreSchema.getSubschemaSubentryAttributeType());
  private static final AttributeDescription ATTR_VENDOR_NAME = AttributeDescription
      .valueOf("vendorName");
      .create(CoreSchema.getVendorNameAttributeType());
  private static final AttributeDescription ATTR_VENDOR_VERSION = AttributeDescription
      .valueOf("vendorVersion");
      .create(CoreSchema.getVendorNameAttributeType());
  private static String[] ROOTDSE_ATTRS = new String[] {
      ATTR_ALT_SERVER.toString(), ATTR_NAMING_CONTEXTS.toString(),
      ATTR_SUPPORTED_CONTROL.toString(),
      ATTR_SUPPORTED_EXTENSION.toString(),
  private static final SearchRequest SEARCH_REQUEST = Requests
      .newSearchRequest(DN.rootDN(), SearchScope.BASE_OBJECT, Filter
          .getObjectClassPresentFilter(), ATTR_ALT_SERVER.toString(),
          ATTR_NAMING_CONTEXTS.toString(), ATTR_SUPPORTED_CONTROL
              .toString(), ATTR_SUPPORTED_EXTENSION.toString(),
      ATTR_SUPPORTED_FEATURE.toString(),
      ATTR_SUPPORTED_LDAP_VERSION.toString(),
      ATTR_SUPPORTED_SASL_MECHANISMS.toString(),
      ATTR_VENDOR_NAME.toString(), ATTR_VENDOR_VERSION.toString(),
      ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES.toString(), "*" };
  private final Entry entry;
  private final Iterable<String> altServers;
  private final Iterable<DN> namingContexts;
  private final Iterable<String> supportedControls;
  private final Iterable<String> supportedExtensions;
  private final Iterable<String> supportedFeatures;
  private final Iterable<Integer> supportedLDAPVerions;
  private final Iterable<String> supportedSASLMechanisms;
  private final Iterable<String> supportedAuthPasswordSchemes;
  private final String vendorName;
  private final String vendorVersion;
          ATTR_SUPPORTED_SASL_MECHANISMS.toString(), ATTR_VENDOR_NAME
              .toString(), ATTR_VENDOR_VERSION.toString(),
          ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES.toString(),
          ATTR_SUBSCHEMA_SUBENTRY.toString(), "*");
  private RootDSE(Entry entry) throws IllegalArgumentException
  /**
   * Reads the Root DSE from the Directory Server using the provided
   * connection.
   * <p>
   * If the Root DSE is not returned by the Directory Server then the
   * request will fail with an {@link EntryNotFoundException}. More
   * specifically, the returned future will never return {@code null}.
   *
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param connection
   *          A connection to the Directory Server whose Root DSE is to
   *          be read.
   * @param handler
   *          A result handler which can be used to asynchronously
   *          process the operation result when it is received, may be
   *          {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If the connection does not support search operations.
   * @throws IllegalStateException
   *           If the connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code connection} was {@code null}.
   */
  public static <P> ResultFuture<RootDSE> readRootDSE(
      AsynchronousConnection connection,
      ResultHandler<RootDSE, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    this.entry = Types.unmodifiableEntry(entry);
    final ResultTransformer<SearchResultEntry, RootDSE, P> future =
      new ResultTransformer<SearchResultEntry, RootDSE, P>(handler)
    {
    Attribute attr = getAttribute(ATTR_ALT_SERVER);
    if (attr == null)
      protected RootDSE transformResult(SearchResultEntry result)
          throws ErrorResultException
    {
      altServers = Collections.emptyList();
    }
    else
    {
      altServers = Iterables.unmodifiable(Iterables.transform(attr,
          Functions.valueToString()));
    }
    attr = getAttribute(ATTR_NAMING_CONTEXTS);
    if (attr == null)
    {
      namingContexts = Collections.emptyList();
    }
    else
    {
      namingContexts = Iterables.unmodifiable(Iterables.transform(attr,
          Functions.valueToDN()));
    }
    attr = getAttribute(ATTR_SUPPORTED_CONTROL);
    if (attr == null)
    {
      supportedControls = Collections.emptyList();
    }
    else
    {
      supportedControls = Iterables.unmodifiable(Iterables.transform(
          attr, Functions.valueToString()));
    }
    attr = getAttribute(ATTR_SUPPORTED_EXTENSION);
    if (attr == null)
    {
      supportedExtensions = Collections.emptyList();
    }
    else
    {
      supportedExtensions = Iterables.unmodifiable(Iterables.transform(
          attr, Functions.valueToString()));
    }
    attr = getAttribute(ATTR_SUPPORTED_FEATURE);
    if (attr == null)
    {
      supportedFeatures = Collections.emptyList();
    }
    else
    {
      supportedFeatures = Iterables.unmodifiable(Iterables.transform(
          attr, Functions.valueToString()));
    }
    attr = getAttribute(ATTR_SUPPORTED_LDAP_VERSION);
    if (attr == null)
    {
      supportedLDAPVerions = Collections.emptyList();
    }
    else
    {
      supportedLDAPVerions = Iterables.unmodifiable(Iterables
          .transform(attr, Functions.valueToInteger()));
    }
    attr = getAttribute(ATTR_SUPPORTED_SASL_MECHANISMS);
    if (attr == null)
    {
      supportedSASLMechanisms = Collections.emptyList();
    }
    else
    {
      supportedSASLMechanisms = Iterables.unmodifiable(Iterables
          .transform(attr, Functions.valueToString()));
    }
    attr = getAttribute(ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES);
    if (attr == null)
    {
      supportedAuthPasswordSchemes = Collections.emptyList();
    }
    else
    {
      supportedAuthPasswordSchemes = Iterables.unmodifiable(Iterables
          .transform(attr, Functions.valueToString()));
    }
    attr = getAttribute(ATTR_VENDOR_NAME);
    vendorName = attr == null ? "" : attr.firstValueAsString();
    attr = getAttribute(ATTR_VENDOR_VERSION);
    vendorVersion = attr == null ? "" : attr.firstValueAsString();
  }
  public static RootDSE getRootDSE(Connection connection)
      throws ErrorResultException, InterruptedException,
      DecodeException, SchemaNotFoundException
  {
    SearchResultEntry result = connection.readEntry(DN.rootDN(),
        ROOTDSE_ATTRS);
    return new RootDSE(result);
  }
    };
  public Iterable<String> getAltServers()
  {
    return altServers;
  }
  public Iterable<DN> getNamingContexts()
  {
    return namingContexts;
  }
  public Iterable<String> getSupportedControls()
  {
    return supportedControls;
  }
  public boolean supportsControl(String oid)
  {
    Validator.ensureNotNull(oid);
    for (String supported : supportedControls)
    {
      if (supported.equals(oid))
      {
        return true;
      }
    }
    return false;
  }
  public Iterable<String> getSupportedExtendedOperations()
  {
    return supportedExtensions;
  }
  public boolean supportsExtendedOperation(String oid)
  {
    Validator.ensureNotNull(oid);
    for (String supported : supportedExtensions)
    {
      if (supported.equals(oid))
      {
        return true;
      }
    }
    return false;
  }
  public Iterable<String> getSupportedFeatures()
  {
    return supportedFeatures;
  }
  public boolean supportsFeature(String oid)
  {
    Validator.ensureNotNull(oid);
    for (String supported : supportedFeatures)
    {
      if (supported.equals(oid))
      {
        return true;
      }
    }
    return false;
  }
  public Iterable<Integer> getSupportedLDAPVersions()
  {
    return supportedLDAPVerions;
  }
  public boolean supportsLDAPVersion(int version)
  {
    for (int supported : supportedLDAPVerions)
    {
      if (supported == version)
      {
        return true;
      }
    }
    return false;
  }
  public Iterable<String> getSupportedSASLMechanismNames()
  {
    return supportedSASLMechanisms;
  }
  public boolean supportsSASLMechanism(String name)
  {
    Validator.ensureNotNull(name);
    for (String supported : supportedSASLMechanisms)
    {
      if (supported.equals(name))
      {
        return true;
      }
    }
    return false;
  }
  public Iterable<String> getSupportedAuthPasswordSchemes()
  {
    return supportedSASLMechanisms;
  }
  public boolean supportsAuthPasswordScheme(String name)
  {
    Validator.ensureNotNull(name);
    for (String supported : supportedAuthPasswordSchemes)
    {
      if (supported.equals(name))
      {
        return true;
      }
    }
    return false;
  }
  public String getVendorName()
  {
    return vendorName;
  }
  public String getVendorVersion()
  {
    return vendorVersion;
    ResultFuture<SearchResultEntry> innerFuture = connection
        .searchSingleEntry(SEARCH_REQUEST, future, p);
    future.setResultFuture(innerFuture);
    return future;
  }
  /**
   * {@inheritDoc}
   * Reads the Root DSE from the Directory Server using the provided
   * connection.
   * <p>
   * If the Root DSE is not returned by the Directory Server then the
   * request will fail with an {@link EntryNotFoundException}. More
   * specifically, this method will never return {@code null}.
   *
   * @param connection
   *          A connection to the Directory Server whose Root DSE is to
   *          be read.
   * @return The Directory Server's Root DSE.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If the connection does not support search operations.
   * @throws IllegalStateException
   *           If the connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code connection} was {@code null}.
   */
  public boolean addAttribute(Attribute attribute,
      Collection<ByteString> duplicateValues)
      throws UnsupportedOperationException, NullPointerException
  {
    throw new UnsupportedOperationException();
  }
  public Entry clearAttributes() throws UnsupportedOperationException
  {
    throw new UnsupportedOperationException();
  }
  public boolean containsAttribute(
      AttributeDescription attributeDescription)
      throws NullPointerException
  {
    Validator.ensureNotNull(attributeDescription);
    return entry.containsAttribute(attributeDescription);
  }
  public Attribute getAttribute(
      AttributeDescription attributeDescription)
      throws NullPointerException
  {
    Validator.ensureNotNull(attributeDescription);
    return entry.getAttribute(attributeDescription);
  }
  public int getAttributeCount()
  {
    return entry.getAttributeCount();
  }
  public Iterable<Attribute> getAttributes()
  {
    return entry.getAttributes();
  }
  public DN getName()
  {
    return DN.rootDN();
  }
  /**
   * {@inheritDoc}
   */
  public boolean removeAttribute(Attribute attribute,
      Collection<ByteString> missingValues)
      throws UnsupportedOperationException, NullPointerException
  {
    throw new UnsupportedOperationException();
  }
  public Entry setName(DN dn) throws UnsupportedOperationException,
  public static RootDSE readRootDSE(Connection connection)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    throw new UnsupportedOperationException();
    final Entry entry = connection.searchSingleEntry(SEARCH_REQUEST);
    return new RootDSE(entry);
  }
  private final Entry entry;
  /**
   * Creates a new Root DSE instance backed by the provided entry.
   * Modifications made to {@code entry} will be reflected in the
   * returned Root DSE. The returned Root DSE instance is unmodifiable
   * and attempts to use modify any of the returned collections will
   * result in a {@code UnsupportedOperationException}.
   *
   * @param entry
   *          The Root DSE entry.
   * @throws NullPointerException
   *           If {@code entry} was {@code null} .
   */
  public RootDSE(Entry entry) throws NullPointerException
  {
    Validator.ensureNotNull(entry);
    this.entry = entry;
  }
  /**
   * Returns an unmodifiable list of URIs referring to alternative
   * Directory Servers that may be contacted when the Directory Server
   * becomes unavailable.
   * <p>
   * URIs for Directory Servers implementing the LDAP protocol are
   * written according to RFC 4516. Other kinds of URIs may be provided.
   * <p>
   * If the Directory Server does not know of any other Directory
   * Servers that could be used, the returned list will be empty.
   *
   * @return An unmodifiable list of URIs referring to alternative
   *         Directory Servers, which may be empty.
   * @see <a href="http://tools.ietf.org/html/rfc4516">RFC 4516 -
   *      Lightweight Directory Access Protocol (LDAP): Uniform Resource
   *      Locator </a>
   */
  public Collection<String> getAlternativeServers()
  {
    return getMultiValuedAttribute(ATTR_ALT_SERVER, Functions
        .valueToString());
  }
  /**
   * Returns an unmodifiable list of DNs identifying the context
   * prefixes of the naming contexts that the Directory Server masters
   * or shadows (in part or in whole).
   * <p>
   * If the Directory Server does not master or shadow any naming
   * contexts, the returned list will be empty.
   *
   * @return An unmodifiable list of DNs identifying the context
   *         prefixes of the naming contexts, which may be empty.
   */
  public Collection<String> getNamingContexts()
  {
    return getMultiValuedAttribute(
        ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES, Functions.valueToString());
  }
  /**
   * Returns a string which represents the DN of the subschema subentry
   * holding the schema controlling the Root DSE.
   * <p>
   * Clients SHOULD NOT assume that this subschema (sub)entry controls
   * other entries held by the Directory Server.
   *
   * @return The DN of the subschema subentry holding the schema
   *         controlling the Root DSE, or {@code null} if the DN is not
   *         provided.
   */
  public String getSubschemaSubentry()
  {
    return getSingleValuedAttribute(ATTR_SUBSCHEMA_SUBENTRY);
  }
  /**
   * Returns an unmodifiable list of supported authentication password
   * schemes which the Directory Server supports.
   * <p>
   * If the Directory Server does not support any authentication
   * password schemes, the returned list will be empty.
   *
   * @return An unmodifiable list of supported authentication password
   *         schemes, which may be empty.
   * @see <a href="http://tools.ietf.org/html/rfc3112">RFC 3112 - LDAP
   *      Authentication Password Schema </a>
   */
  public Collection<String> getSupportedAuthenticationPasswordSchemes()
  {
    return getMultiValuedAttribute(
        ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES, Functions.valueToString());
  }
  /**
   * Returns an unmodifiable list of object identifiers identifying the
   * request controls that the Directory Server supports.
   * <p>
   * If the Directory Server does not support any request controls, the
   * returned list will be empty. Object identifiers identifying
   * response controls may not be listed.
   *
   * @return An unmodifiable list of object identifiers identifying the
   *         request controls, which may be empty.
   */
  public Collection<String> getSupportedControls()
  {
    return getMultiValuedAttribute(ATTR_SUPPORTED_CONTROL, Functions
        .valueToString());
  }
  /**
   * Returns an unmodifiable list of object identifiers identifying the
   * extended operations that the Directory Server supports.
   * <p>
   * If the Directory Server does not support any extended operations,
   * the returned list will be empty.
   * <p>
   * An extended operation generally consists of an extended request and
   * an extended response but may also include other protocol data units
   * (such as intermediate responses). The object identifier assigned to
   * the extended request is used to identify the extended operation.
   * Other object identifiers used in the extended operation may not be
   * listed as values of this attribute.
   *
   * @return An unmodifiable list of object identifiers identifying the
   *         extended operations, which may be empty.
   */
  public Collection<String> getSupportedExtendedOperations()
  {
    return getMultiValuedAttribute(ATTR_SUPPORTED_EXTENSION, Functions
        .valueToString());
  }
  /**
   * Returns an unmodifiable list of object identifiers identifying
   * elective features that the Directory Server supports.
   * <p>
   * If the server does not support any discoverable elective features,
   * the returned list will be empty.
   *
   * @return An unmodifiable list of object identifiers identifying the
   *         elective features, which may be empty.
   */
  public Collection<String> getSupportedFeatures()
  {
    return getMultiValuedAttribute(ATTR_SUPPORTED_FEATURE, Functions
        .valueToString());
  }
  /**
   * Returns an unmodifiable list of the versions of LDAP that the
   * Directory Server supports.
   *
   * @return An unmodifiable list of the versions.
   */
  public Collection<Integer> getSupportedLDAPVersions()
  {
    return getMultiValuedAttribute(ATTR_SUPPORTED_LDAP_VERSION,
        Functions.valueToInteger());
  }
  /**
   * Returns an unmodifiable list of the SASL mechanisms that the
   * Directory Server recognizes and/or supports.
   * <p>
   * The contents of the returned list may depend on the current session
   * state and may be empty if the Directory Server does not support any
   * SASL mechanisms.
   *
   * @return An unmodifiable list of the SASL mechanisms, which may be
   *         empty.
   * @see <a href="http://tools.ietf.org/html/rfc4513">RFC 4513 -
   *      Lightweight Directory Access Protocol (LDAP): Authentication
   *      Methods and Security Mechanisms </a>
   * @see <a href="http://tools.ietf.org/html/rfc4422">RFC 4422 - Simple
   *      Authentication and Security Layer (SASL) </a>
   */
  public Collection<String> getSupportedSASLMechanisms()
  {
    return getMultiValuedAttribute(ATTR_SUPPORTED_SASL_MECHANISMS,
        Functions.valueToString());
  }
  /**
   * Returns a string which represents the name of the Directory Server
   * implementer.
   *
   * @return The name of the Directory Server implementer, or {@code
   *         null} if the vendor name is not provided.
   * @see <a href="http://tools.ietf.org/html/rfc3045">RFC 3045 -
   *      Storing Vendor Information in the LDAP Root DSE </a>
   */
  public String getVendorName()
  {
    return getSingleValuedAttribute(ATTR_VENDOR_NAME);
  }
  /**
   * Returns a string which represents the version of the Directory
   * Server implementation.
   * <p>
   * Note that this value is typically a release value comprised of a
   * string and/or a string of numbers used by the developer of the LDAP
   * server product. The returned string will be unique between two
   * versions of the Directory Server, but there are no other syntactic
   * restrictions on the value or the way it is formatted.
   *
   * @return The version of the Directory Server implementation, or
   *         {@code null} if the vendor version is not provided.
   * @see <a href="http://tools.ietf.org/html/rfc3045">RFC 3045 -
   *      Storing Vendor Information in the LDAP Root DSE </a>
   */
  public String getVendorVersion()
  {
    return getSingleValuedAttribute(ATTR_VENDOR_VERSION);
  }
  private <N> Collection<N> getMultiValuedAttribute(
      AttributeDescription attributeDescription,
      Function<ByteString, N, Void> function)
  {
    // The returned collection is unmodifiable because we may need to
    // return an empty collection if the attribute does not exist in the
    // underlying entry. If a value is then added to the returned empty
    // collection it would require that an attribute is created in the
    // underlying entry in order to maintain consistency.
    final Attribute attr = entry.getAttribute(attributeDescription);
    if (attr != null)
    {
      return Collections.unmodifiableCollection(Collections2.transform(
          attr, function, Functions.objectToByteString()));
    }
    else
    {
      return Collections.emptySet();
    }
  }
  private String getSingleValuedAttribute(
      AttributeDescription attributeDescription)
  {
    final Attribute attr = entry.getAttribute(attributeDescription);
    if (attr == null || attr.isEmpty())
    {
      return null;
    }
    else
    {
      return attr.firstValueAsString();
    }
  }
}
sdk/src/org/opends/sdk/SynchronousConnection.java
@@ -33,6 +33,7 @@
import org.opends.sdk.responses.BindResult;
import org.opends.sdk.responses.CompareResult;
import org.opends.sdk.responses.Result;
import org.opends.sdk.schema.Schema;
import com.sun.opends.sdk.util.Validator;
@@ -270,4 +271,26 @@
    return connection.isClosed();
  }
  /**
   * {@inheritDoc}
   */
  public Schema readSchemaForEntry(DN name)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException
  {
    ResultFuture<Schema> future = connection.readSchemaForEntry(name,
        null, null);
    try
    {
      return future.get();
    }
    finally
    {
      // Cancel the request if it hasn't completed.
      future.cancel(false);
    }
  }
}
sdk/src/org/opends/sdk/TimeoutResultException.java
File was renamed from sdk/src/org/opends/sdk/OperationTimeoutException.java
@@ -39,9 +39,9 @@
 * out period.
 */
@SuppressWarnings("serial")
public class OperationTimeoutException extends ErrorResultException
public class TimeoutResultException extends ErrorResultException
{
  OperationTimeoutException(Result result)
  TimeoutResultException(Result result)
  {
    super(result);
  }
sdk/src/org/opends/sdk/controls/MatchedValuesControl.java
@@ -86,7 +86,7 @@
    @Override
    public LocalizedIllegalArgumentException visitExtensibleMatchFilter(
        Filter p, String matchingRule, String attributeDescription,
        ByteSequence assertionValue, boolean dnAttributes)
        ByteString assertionValue, boolean dnAttributes)
    {
      if (dnAttributes)
      {
@@ -123,7 +123,7 @@
    @Override
    public LocalizedIllegalArgumentException visitUnrecognizedFilter(
        Filter p, byte filterTag, ByteSequence filterBytes)
        Filter p, byte filterTag, ByteString filterBytes)
    {
      LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_UNRECOGNIZED.get(p
          .toString(), filterTag);
sdk/src/org/opends/sdk/ldap/LDAPUtils.java
@@ -37,6 +37,7 @@
import java.util.List;
import org.opends.sdk.ByteSequence;
import org.opends.sdk.ByteString;
import org.opends.sdk.Filter;
import org.opends.sdk.FilterVisitor;
import org.opends.sdk.asn1.ASN1Reader;
@@ -82,7 +83,7 @@
    public IOException visitApproxMatchFilter(ASN1Writer writer,
        String attributeDescription, ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      try
      {
@@ -101,7 +102,7 @@
    public IOException visitEqualityMatchFilter(ASN1Writer writer,
        String attributeDescription, ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      try
      {
@@ -121,7 +122,7 @@
    public IOException visitExtensibleMatchFilter(ASN1Writer writer,
        String matchingRule, String attributeDescription,
        ByteSequence assertionValue, boolean dnAttributes)
        ByteString assertionValue, boolean dnAttributes)
    {
      try
      {
@@ -158,7 +159,7 @@
    public IOException visitGreaterOrEqualFilter(ASN1Writer writer,
        String attributeDescription, ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      try
      {
@@ -177,7 +178,7 @@
    public IOException visitLessOrEqualFilter(ASN1Writer writer,
        String attributeDescription, ByteSequence assertionValue)
        String attributeDescription, ByteString assertionValue)
    {
      try
      {
@@ -260,8 +261,8 @@
    public IOException visitSubstringsFilter(ASN1Writer writer,
        String attributeDescription, ByteSequence initialSubstring,
        List<ByteSequence> anySubstrings, ByteSequence finalSubstring)
        String attributeDescription, ByteString initialSubstring,
        List<ByteString> anySubstrings, ByteString finalSubstring)
    {
      try
      {
@@ -297,7 +298,7 @@
    public IOException visitUnrecognizedFilter(ASN1Writer writer,
        byte filterTag, ByteSequence filterBytes)
        byte filterTag, ByteString filterBytes)
    {
      try
      {
@@ -481,7 +482,7 @@
      throws IOException
  {
    String attributeDescription;
    ByteSequence assertionValue;
    ByteString assertionValue;
    reader.readStartSequence(TYPE_FILTER_APPROXIMATE);
    try
@@ -505,7 +506,7 @@
      throws IOException
  {
    String attributeDescription;
    ByteSequence assertionValue;
    ByteString assertionValue;
    reader.readStartSequence(TYPE_FILTER_EQUALITY);
    try
@@ -531,7 +532,7 @@
    String matchingRule;
    String attributeDescription;
    boolean dnAttributes;
    ByteSequence assertionValue;
    ByteString assertionValue;
    reader.readStartSequence(TYPE_FILTER_EXTENSIBLE_MATCH);
    try
@@ -572,7 +573,7 @@
      ASN1Reader reader) throws IOException
  {
    String attributeDescription;
    ByteSequence assertionValue;
    ByteString assertionValue;
    reader.readStartSequence(TYPE_FILTER_GREATER_OR_EQUAL);
    try
@@ -595,7 +596,7 @@
      throws IOException
  {
    String attributeDescription;
    ByteSequence assertionValue;
    ByteString assertionValue;
    reader.readStartSequence(TYPE_FILTER_LESS_OR_EQUAL);
    try
@@ -673,9 +674,9 @@
  private static Filter decodeSubstringsFilter(ASN1Reader reader)
      throws IOException
  {
    ByteSequence initialSubstring = null;
    List<ByteSequence> anySubstrings = null;
    ByteSequence finalSubstring = null;
    ByteString initialSubstring = null;
    List<ByteString> anySubstrings = null;
    ByteString finalSubstring = null;
    String attributeDescription;
    reader.readStartSequence(TYPE_FILTER_SUBSTRING);
@@ -694,7 +695,7 @@
        if (reader.hasNextElement()
            && (reader.peekType() == TYPE_SUBANY))
        {
          anySubstrings = new LinkedList<ByteSequence>();
          anySubstrings = new LinkedList<ByteString>();
          do
          {
            anySubstrings.add(reader.readOctetString(TYPE_SUBANY));
sdk/src/org/opends/sdk/schema/AbstractMatchingRuleImpl.java
@@ -108,7 +108,7 @@
  public Assertion getAssertion(Schema schema, ByteSequence subInitial,
      List<ByteSequence> subAnyElements, ByteSequence subFinal)
      List<? extends ByteSequence> subAnyElements, ByteSequence subFinal)
      throws DecodeException
  {
    return UNDEFINED_ASSERTION;
sdk/src/org/opends/sdk/schema/AbstractSubstringMatchingRuleImpl.java
@@ -235,7 +235,7 @@
  @Override
  public Assertion getAssertion(Schema schema, ByteSequence subInitial,
      List<ByteSequence> subAnyElements, ByteSequence subFinal)
      List<? extends ByteSequence> subAnyElements, ByteSequence subFinal)
      throws DecodeException
  {
    final ByteString normInitial =
sdk/src/org/opends/sdk/schema/AttributeType.java
@@ -37,6 +37,7 @@
import java.util.List;
import java.util.Map;
import org.opends.sdk.AttributeDescription;
import org.opends.sdk.LocalizableMessage;
import com.sun.opends.sdk.util.StaticUtils;
@@ -127,6 +128,10 @@
  // The syntax for this attribute type.
  private Syntax syntax;
  // The attribute description representing this attribute type with no
  // options.
  private final AttributeDescription attributeDescription;
  AttributeType(String oid, List<String> names, String description,
@@ -169,6 +174,7 @@
    this.isObjectClassType = oid.equals("2.5.4.0");
    this.normalizedName = StaticUtils.toLowerCase(getNameOrOID());
    this.attributeDescription = AttributeDescription.create(this);
  }
@@ -200,6 +206,21 @@
    this.isObjectClassType = oid.equals("2.5.4.0");
    this.normalizedName = StaticUtils.toLowerCase(getNameOrOID());
    this.attributeDescription = AttributeDescription.create(this);
  }
  /**
   * Returns an attribute description comprising of this attribute type
   * and no options.
   *
   * @return An attribute description comprising of this attribute type
   *         and no options.
   */
  public AttributeDescription asAttributeDescription()
  {
    return attributeDescription;
  }
@@ -753,8 +774,8 @@
        // never fail since the core schema is non-strict and will
        // substitute the syntax if required.
        syntax = Schema.getCoreSchema().getSyntax(syntaxOID);
        final LocalizableMessage message = WARN_ATTR_TYPE_NOT_DEFINED.get(
            getNameOrOID(), syntaxOID, syntax.toString());
        final LocalizableMessage message = WARN_ATTR_TYPE_NOT_DEFINED
            .get(getNameOrOID(), syntaxOID, syntax.toString());
        warnings.add(message);
      }
      else
sdk/src/org/opends/sdk/schema/CoreSchema.java
@@ -2269,7 +2269,7 @@
   *
   * @return A reference to the {@code supportedSASLMechanisms} Attribute Type.
   */
  public static AttributeType getSupportedSaslMechanismsAttributeType()
  public static AttributeType getSupportedSASLMechanismsAttributeType()
  {
    return SUPPORTED_SASL_MECHANISMS_ATTRIBUTE_TYPE;
  }
sdk/src/org/opends/sdk/schema/CoreSchemaImpl.java
@@ -32,51 +32,53 @@
import java.util.*;
import org.opends.sdk.LocalizableMessage;
final class CoreSchemaImpl
{
  private static final Map<String, List<String>> X500_ORIGIN =
      Collections.singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
  private static final Map<String, List<String>> X500_ORIGIN = Collections
      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
          .singletonList("X.500"));
  private static final Map<String, List<String>> RFC2252_ORIGIN =
      Collections.singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
  private static final Map<String, List<String>> RFC2252_ORIGIN = Collections
      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
          .singletonList("RFC 2252"));
  private static final Map<String, List<String>> RFC3045_ORIGIN =
      Collections.singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
  private static final Map<String, List<String>> RFC3045_ORIGIN = Collections
      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
          .singletonList("RFC 3045"));
  private static final Map<String, List<String>> RFC3112_ORIGIN =
      Collections.singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
  private static final Map<String, List<String>> RFC3112_ORIGIN = Collections
      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
          .singletonList("RFC 3112"));
  private static final Map<String, List<String>> RFC4512_ORIGIN =
      Collections.singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
  private static final Map<String, List<String>> RFC4512_ORIGIN = Collections
      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
          .singletonList("RFC 4512"));
  private static final Map<String, List<String>> RFC4517_ORIGIN =
      Collections.singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
  private static final Map<String, List<String>> RFC4517_ORIGIN = Collections
      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
          .singletonList("RFC 4517"));
  private static final Map<String, List<String>> RFC4519_ORIGIN =
      Collections.singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
  private static final Map<String, List<String>> RFC4519_ORIGIN = Collections
      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
          .singletonList("RFC 4519"));
  private static final Map<String, List<String>> RFC4530_ORIGIN =
      Collections.singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
  private static final Map<String, List<String>> RFC4530_ORIGIN = Collections
      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
          .singletonList("RFC 4530"));
  static final Map<String, List<String>> OPENDS_ORIGIN =
      Collections.singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
  static final Map<String, List<String>> OPENDS_ORIGIN = Collections
      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
          .singletonList("OpenDS Directory Server"));
  private static final String EMPTY_STRING = "".intern();
  private static final Set<String> EMPTY_STRING_SET =
      Collections.emptySet();
  private static final Set<String> EMPTY_STRING_SET = Collections
      .emptySet();
  private static final Schema SINGLETON;
  // Package private so that we can check for warnings in the unit
  // tests.
  static final List<LocalizableMessage> CORE_SCHEMA_WARNINGS =
      new LinkedList<LocalizableMessage>();
  static
  {
    final SchemaBuilder builder = new SchemaBuilder();
@@ -91,7 +93,7 @@
    addRFC3112(builder);
    addSunProprietary(builder);
    SINGLETON = builder.toSchema(CORE_SCHEMA_WARNINGS).nonStrict();
    SINGLETON = builder.toSchema().nonStrict();
  }
sdk/src/org/opends/sdk/schema/GenerateCoreSchema.java
@@ -43,10 +43,12 @@
    return oid.startsWith(SchemaConstants.OID_OPENDS_SERVER_BASE + ".");
  }
  private static final Set<String> ABBREVIATIONS =
      new HashSet<String>(Arrays.asList("LDAP", "DN", "DIT", "RDN",
          "JPEG", "OID", "UUID", "IA5", "UID", "UTC", "X500", "X121",
          "C", "CN", "O", "OU", "L", "DC", "ISDN", "SN", "ST"));
  private static final Set<String> ABBREVIATIONS = new HashSet<String>(
      Arrays.asList("SASL", "LDAP", "DN", "DIT", "RDN", "JPEG", "OID",
          "UUID", "IA5", "UID", "UTC", "X500", "X121", "C", "CN", "O",
          "OU", "L", "DC", "ISDN", "SN", "ST"));
sdk/src/org/opends/sdk/schema/MatchingRule.java
@@ -151,7 +151,7 @@
   *           if the syntax of the value is not valid.
   */
  public Assertion getAssertion(ByteSequence subInitial,
      List<ByteSequence> subAnyElements, ByteSequence subFinal)
      List<? extends ByteSequence> subAnyElements, ByteSequence subFinal)
      throws DecodeException
  {
    return impl.getAssertion(schema, subInitial, subAnyElements,
sdk/src/org/opends/sdk/schema/MatchingRuleImpl.java
@@ -97,7 +97,7 @@
   *           if an syntax error occured while parsing the value.
   */
  public Assertion getAssertion(Schema schema, ByteSequence subInitial,
      List<ByteSequence> subAnyElements, ByteSequence subFinal)
      List<? extends ByteSequence> subAnyElements, ByteSequence subFinal)
      throws DecodeException;
sdk/src/org/opends/sdk/schema/Schema.java
@@ -36,10 +36,15 @@
import java.util.Map;
import org.opends.sdk.*;
import org.opends.sdk.requests.Requests;
import org.opends.sdk.requests.SearchRequest;
import org.opends.sdk.responses.Responses;
import org.opends.sdk.responses.Result;
import org.opends.sdk.responses.SearchResultEntry;
import com.sun.opends.sdk.util.ResultChain;
import com.sun.opends.sdk.util.ResultTransformer;
import com.sun.opends.sdk.util.StaticUtils;
import com.sun.opends.sdk.util.Validator;
@@ -291,6 +296,13 @@
    public Collection<LocalizableMessage> getWarnings()
    {
      return Collections.emptyList();
    }
    public boolean hasAttributeType(String name)
    {
      // In theory a non-strict schema always contains the requested
@@ -480,6 +492,10 @@
    Collection<LocalizableMessage> getWarnings();
    boolean hasAttributeType(String name);
@@ -752,6 +768,13 @@
    public Collection<LocalizableMessage> getWarnings()
    {
      return strictImpl.getWarnings();
    }
    public boolean hasAttributeType(String name)
    {
      // In theory a non-strict schema always contains the requested
@@ -858,6 +881,8 @@
    private final SchemaCompatOptions options;
    private final List<LocalizableMessage> warnings;
    private StrictImpl(Map<String, Syntax> numericOID2Syntaxes,
@@ -877,7 +902,7 @@
        Map<String, List<DITStructureRule>> name2StructureRules,
        Map<String, List<NameForm>> objectClass2NameForms,
        Map<String, List<DITStructureRule>> nameForm2StructureRules,
        SchemaCompatOptions options)
        SchemaCompatOptions options, List<LocalizableMessage> warnings)
    {
      this.numericOID2Syntaxes = Collections
          .unmodifiableMap(numericOID2Syntaxes);
@@ -913,6 +938,7 @@
      this.nameForm2StructureRules = Collections
          .unmodifiableMap(nameForm2StructureRules);
      this.options = options;
      this.warnings = Collections.unmodifiableList(warnings);
    }
@@ -1315,6 +1341,13 @@
    public Collection<LocalizableMessage> getWarnings()
    {
      return warnings;
    }
    public boolean hasAttributeType(String name)
    {
      if (numericOID2AttributeTypes.containsKey(name))
@@ -1458,6 +1491,294 @@
      ATTR_MATCHING_RULES.toString(), ATTR_NAME_FORMS.toString(),
      ATTR_OBJECT_CLASSES.toString() };
  private static final Filter SUBSCHEMA_FILTER = Filter
      .newEqualityMatchFilter(CoreSchema.getObjectClassAttributeType()
          .getNameOrOID(), CoreSchema.getSubschemaObjectClass()
          .getNameOrOID());
  private static final String[] SUBSCHEMA_SUBENTRY_ATTRS = new String[] { ATTR_SUBSCHEMA_SUBENTRY
      .toString() };
  /**
   * Reads the schema from the Directory Server contained in the named
   * subschema sub-entry using the provided connection.
   * <p>
   * If the requested schema is not returned by the Directory Server
   * then the request will fail with an {@link EntryNotFoundException}.
   * More specifically, this method will never return {@code null}.
   *
   * @param connection
   *          A connection to the Directory Server whose schema is to be
   *          read.
   * @param name
   *          The distinguished name of the subschema sub-entry.
   * @return The schema from the Directory Server.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If the connection does not support search operations.
   * @throws IllegalStateException
   *           If the connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code connection} or {@code name} was {@code
   *           null}.
   */
  public static Schema readSchema(Connection connection, DN name)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final SearchRequest request = getReadSchemaSearchRequest(name);
    final Entry entry = connection.searchSingleEntry(request);
    return valueOf(entry);
  }
  /**
   * Reads the schema from the Directory Server which applies to the
   * named entry using the provided connection.
   * <p>
   * If the requested entry or its associated schema are not returned by
   * the Directory Server then the request will fail with an
   * {@link EntryNotFoundException}. More specifically, this method will
   * never return {@code null}.
   * <p>
   * A typical implementation will first read the {@code
   * subschemaSubentry} attribute of the entry in order to locate the
   * schema. However, implementations may choose to perform other
   * optimizations, such as caching.
   *
   * @param connection
   *          A connection to the Directory Server whose schema is to be
   *          read.
   * @param name
   *          The distinguished name of the entry whose schema is to be
   *          located.
   * @return The schema from the Directory Server which applies to the
   *         named entry.
   * @throws ErrorResultException
   *           If the result code indicates that the request failed for
   *           some reason.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws UnsupportedOperationException
   *           If the connection does not support search operations.
   * @throws IllegalStateException
   *           If the connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code connection} or {@code name} was {@code
   *           null}.
   */
  public static Schema readSchemaForEntry(Connection connection, DN name)
      throws ErrorResultException, InterruptedException,
      UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final SearchRequest request = getReadSchemaForEntrySearchRequest(name);
    final Entry entry = connection.searchSingleEntry(request);
    final DN subschemaDN = getSubschemaSubentryDN(name, entry);
    return readSchema(connection, subschemaDN);
  }
  private static DN getSubschemaSubentryDN(DN name, final Entry entry)
      throws ErrorResultException
  {
    final Attribute subentryAttr = entry
        .getAttribute(ATTR_SUBSCHEMA_SUBENTRY);
    if (subentryAttr == null || subentryAttr.isEmpty())
    {
      // Did not get the subschema sub-entry attribute.
      Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
          .setDiagnosticMessage(
              ERR_NO_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString())
                  .toString());
      throw ErrorResultException.wrap(result);
    }
    String dnString = subentryAttr.iterator().next().toString();
    DN subschemaDN;
    try
    {
      subschemaDN = DN.valueOf(dnString);
    }
    catch (LocalizedIllegalArgumentException e)
    {
      Result result = Responses.newResult(
          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
          .setDiagnosticMessage(
              ERR_INVALID_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString(),
                  dnString, e.getMessageObject()).toString());
      throw ErrorResultException.wrap(result);
    }
    return subschemaDN;
  }
  /**
   * Reads the schema from the Directory Server contained in the named
   * subschema sub-entry.
   * <p>
   * If the requested schema is not returned by the Directory Server
   * then the request will fail with an {@link EntryNotFoundException}.
   * More specifically, the returned future will never return {@code
   * null}.
   * <p>
   * Implementations may choose to perform optimizations such as
   * caching.
   *
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param connection
   *          A connection to the Directory Server whose schema is to be
   *          read.
   * @param name
   *          The distinguished name of the subschema sub-entry.
   * @param handler
   *          A result handler which can be used to asynchronously
   *          process the operation result when it is received, may be
   *          {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code connection} or {@code name} was {@code
   *           null}.
   */
  public static <P> ResultFuture<Schema> readSchema(
      AsynchronousConnection connection, DN name,
      ResultHandler<? super Schema, P> handler, P p)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final SearchRequest request = getReadSchemaSearchRequest(name);
    final ResultTransformer<SearchResultEntry, Schema, P> future = new ResultTransformer<SearchResultEntry, Schema, P>(
        handler)
    {
      protected Schema transformResult(SearchResultEntry result)
          throws ErrorResultException
      {
        return valueOf(result);
      }
    };
    ResultFuture<SearchResultEntry> innerFuture = connection
        .searchSingleEntry(request, future, p);
    future.setResultFuture(innerFuture);
    return future;
  }
  /**
   * Reads the schema from the Directory Server which applies to the
   * named entry.
   * <p>
   * If the requested entry or its associated schema are not returned by
   * the Directory Server then the request will fail with an
   * {@link EntryNotFoundException}. More specifically, the returned
   * future will never return {@code null}.
   * <p>
   * A typical implementation will first read the {@code
   * subschemaSubentry} attribute of the entry in order to locate the
   * schema. However, implementations may choose to perform other
   * optimizations, such as caching.
   *
   * @param <P>
   *          The type of the additional parameter to the handler's
   *          methods.
   * @param connection
   *          A connection to the Directory Server whose schema is to be
   *          read.
   * @param name
   *          The distinguished name of the entry whose schema is to be
   *          located.
   * @param handler
   *          A result handler which can be used to asynchronously
   *          process the operation result when it is received, may be
   *          {@code null}.
   * @param p
   *          Optional additional handler parameter.
   * @return A future representing the result of the operation.
   * @throws UnsupportedOperationException
   *           If this connection does not support search operations.
   * @throws IllegalStateException
   *           If this connection has already been closed, i.e. if
   *           {@code isClosed() == true}.
   * @throws NullPointerException
   *           If the {@code connection} or {@code name} was {@code
   *           null}.
   */
  public static <P> ResultFuture<Schema> readSchemaForEntry(
      final AsynchronousConnection connection, final DN name,
      ResultHandler<Schema, P> handler, final P p)
      throws UnsupportedOperationException, IllegalStateException,
      NullPointerException
  {
    final ResultChain<SearchResultEntry, Schema, P> future = new ResultChain<SearchResultEntry, Schema, P>(
        handler)
    {
      protected ResultFuture<Schema> chainResult(
          SearchResultEntry innerResult,
          ResultHandler<? super Schema, P> handler)
          throws ErrorResultException
      {
        final DN subschemaDN = getSubschemaSubentryDN(name, innerResult);
        return readSchema(connection, subschemaDN, handler, p);
      }
    };
    final SearchRequest request = getReadSchemaForEntrySearchRequest(name);
    ResultFuture<SearchResultEntry> innerFuture = connection
        .searchSingleEntry(request, future, p);
    future.setInnerResultFuture(innerFuture);
    return future;
  }
  // Constructs a search request for retrieving the named subschema
  // sub-entry.
  private static SearchRequest getReadSchemaSearchRequest(DN dn)
  {
    return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT,
        SUBSCHEMA_FILTER, SUBSCHEMA_ATTRS);
  }
  // Constructs a search request for retrieving the subschemaSubentry
  // attribute from the named entry.
  private static SearchRequest getReadSchemaForEntrySearchRequest(DN dn)
  {
    return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT,
        SUBSCHEMA_FILTER, SUBSCHEMA_SUBENTRY_ATTRS);
  }
  /**
@@ -1520,62 +1841,19 @@
  /**
   * Reads the schema associated with the provided entry from an LDAP
   * Directory Server.
   * Parses the provided entry as a subschema subentry. Any problems
   * encountered while parsing the entry can be retrieved using the
   * returned schema's {@link #getWarnings()} method.
   *
   * @param connection
   *          The connection to the Directory Server.
   * @param dn
   *          The name of the entry whose schema is to be retrieved.
   * @param warnings
   *          A list to which any warning messages encountered while
   *          decoding the schema should be appended.
   * @return The schema.
   * @throws LocalizedIllegalArgumentException
   *           If {@code dn} could not be decoded using the default
   *           schema.
   * @throws ErrorResultException
   *           If the server returned an error result code.
   * @throws InterruptedException
   *           If the current thread was interrupted while waiting.
   * @throws SchemaNotFoundException
   *           If the requested schema was not found in the Directory
   *           Server.
   * @param entry
   *          The subschema subentry to be parsed.
   * @return The parsed schema.
   */
  public static Schema getSchema(Connection connection, String dn,
      List<LocalizableMessage> warnings) throws ErrorResultException,
      InterruptedException, LocalizedIllegalArgumentException,
      SchemaNotFoundException
  public static Schema valueOf(Entry entry)
  {
    Validator.ensureNotNull(connection, dn, warnings);
    SearchResultEntry result = connection.readEntry(dn,
        ATTR_SUBSCHEMA_SUBENTRY.toString());
    Attribute subentryAttr;
    if ((subentryAttr = result.getAttribute(ATTR_SUBSCHEMA_SUBENTRY)) == null
        || subentryAttr.isEmpty())
    {
      throw new SchemaNotFoundException(ERR_NO_SUBSCHEMA_SUBENTRY_ATTR
          .get(dn));
    }
    String subschemaDNString = subentryAttr.iterator().next()
        .toString();
    DN subschemaDN;
    try
    {
      subschemaDN = DN.valueOf(subschemaDNString);
    }
    catch (LocalizedIllegalArgumentException e)
    {
      throw new SchemaNotFoundException(
          ERR_INVALID_SUBSCHEMA_SUBENTRY_ATTR.get(dn,
              subschemaDNString, e.getMessageObject()));
    }
    result = connection.readEntry(subschemaDN, SUBSCHEMA_ATTRS);
    final SchemaBuilder builder = new SchemaBuilder();
    Attribute attr = result.getAttribute(ATTR_LDAP_SYNTAXES);
    Attribute attr = entry.getAttribute(ATTR_LDAP_SYNTAXES);
    if (attr != null)
    {
      for (final ByteString def : attr)
@@ -1586,12 +1864,12 @@
        }
        catch (final LocalizedIllegalArgumentException e)
        {
          warnings.add(e.getMessageObject());
          builder.addWarning(e.getMessageObject());
        }
      }
    }
    attr = result.getAttribute(ATTR_ATTRIBUTE_TYPES);
    attr = entry.getAttribute(ATTR_ATTRIBUTE_TYPES);
    if (attr != null)
    {
      for (final ByteString def : attr)
@@ -1602,12 +1880,12 @@
        }
        catch (final LocalizedIllegalArgumentException e)
        {
          warnings.add(e.getMessageObject());
          builder.addWarning(e.getMessageObject());
        }
      }
    }
    attr = result.getAttribute(ATTR_OBJECT_CLASSES);
    attr = entry.getAttribute(ATTR_OBJECT_CLASSES);
    if (attr != null)
    {
      for (final ByteString def : attr)
@@ -1618,12 +1896,12 @@
        }
        catch (final LocalizedIllegalArgumentException e)
        {
          warnings.add(e.getMessageObject());
          builder.addWarning(e.getMessageObject());
        }
      }
    }
    attr = result.getAttribute(ATTR_MATCHING_RULE_USE);
    attr = entry.getAttribute(ATTR_MATCHING_RULE_USE);
    if (attr != null)
    {
      for (final ByteString def : attr)
@@ -1634,12 +1912,12 @@
        }
        catch (final LocalizedIllegalArgumentException e)
        {
          warnings.add(e.getMessageObject());
          builder.addWarning(e.getMessageObject());
        }
      }
    }
    attr = result.getAttribute(ATTR_MATCHING_RULES);
    attr = entry.getAttribute(ATTR_MATCHING_RULES);
    if (attr != null)
    {
      for (final ByteString def : attr)
@@ -1650,12 +1928,12 @@
        }
        catch (final LocalizedIllegalArgumentException e)
        {
          warnings.add(e.getMessageObject());
          builder.addWarning(e.getMessageObject());
        }
      }
    }
    attr = result.getAttribute(ATTR_DIT_CONTENT_RULES);
    attr = entry.getAttribute(ATTR_DIT_CONTENT_RULES);
    if (attr != null)
    {
      for (final ByteString def : attr)
@@ -1666,12 +1944,12 @@
        }
        catch (final LocalizedIllegalArgumentException e)
        {
          warnings.add(e.getMessageObject());
          builder.addWarning(e.getMessageObject());
        }
      }
    }
    attr = result.getAttribute(ATTR_DIT_STRUCTURE_RULES);
    attr = entry.getAttribute(ATTR_DIT_STRUCTURE_RULES);
    if (attr != null)
    {
      for (final ByteString def : attr)
@@ -1682,12 +1960,12 @@
        }
        catch (final LocalizedIllegalArgumentException e)
        {
          warnings.add(e.getMessageObject());
          builder.addWarning(e.getMessageObject());
        }
      }
    }
    attr = result.getAttribute(ATTR_NAME_FORMS);
    attr = entry.getAttribute(ATTR_NAME_FORMS);
    if (attr != null)
    {
      for (final ByteString def : attr)
@@ -1698,12 +1976,12 @@
        }
        catch (final LocalizedIllegalArgumentException e)
        {
          warnings.add(e.getMessageObject());
          builder.addWarning(e.getMessageObject());
        }
      }
    }
    return builder.toSchema(warnings);
    return builder.toSchema();
  }
@@ -1758,7 +2036,7 @@
      Map<String, List<DITStructureRule>> name2StructureRules,
      Map<String, List<NameForm>> objectClass2NameForms,
      Map<String, List<DITStructureRule>> nameForm2StructureRules,
      SchemaCompatOptions options)
      SchemaCompatOptions options, List<LocalizableMessage> warnings)
  {
    impl = new StrictImpl(numericOID2Syntaxes,
        numericOID2MatchingRules, numericOID2MatchingRuleUses,
@@ -1767,7 +2045,7 @@
        id2StructureRules, name2MatchingRules, name2MatchingRuleUses,
        name2AttributeTypes, name2ObjectClasses, name2NameForms,
        name2ContentRules, name2StructureRules, objectClass2NameForms,
        nameForm2StructureRules, options);
        nameForm2StructureRules, options, warnings);
  }
@@ -2205,6 +2483,20 @@
  /**
   * Returns an unmodifiable collection containing all of the warnings
   * that were detected when this schema was constructed.
   *
   * @return An unmodifiable collection containing all of the warnings
   *         that were detected when this schema was constructed.
   */
  public Collection<LocalizableMessage> getWarnings()
  {
    return impl.getWarnings();
  }
  /**
   * Indicates whether or not this schema contains an attribute type
   * with the specified name or numeric OID.
   *
sdk/src/org/opends/sdk/schema/SchemaBuilder.java
@@ -51,23 +51,43 @@
{
  private Map<Integer, DITStructureRule> id2StructureRules;
  private Map<String, List<AttributeType>> name2AttributeTypes;
  private Map<String, List<DITContentRule>> name2ContentRules;
  private Map<String, List<MatchingRule>> name2MatchingRules;
  private Map<String, List<MatchingRuleUse>> name2MatchingRuleUses;
  private Map<String, List<NameForm>> name2NameForms;
  private Map<String, List<ObjectClass>> name2ObjectClasses;
  private Map<String, List<DITStructureRule>> name2StructureRules;
  private Map<String, List<DITStructureRule>> nameForm2StructureRules;
  private Map<String, AttributeType> numericOID2AttributeTypes;
  private Map<String, DITContentRule> numericOID2ContentRules;
  private Map<String, MatchingRule> numericOID2MatchingRules;
  private Map<String, MatchingRuleUse> numericOID2MatchingRuleUses;
  private Map<String, NameForm> numericOID2NameForms;
  private Map<String, ObjectClass> numericOID2ObjectClasses;
  private Map<String, Syntax> numericOID2Syntaxes;
  private Map<String, List<NameForm>> objectClass2NameForms;
  private SchemaCompatOptions options;
  private List<LocalizableMessage> warnings;
  private Schema schema;
@@ -137,8 +157,8 @@
      {
        // This means that the definition was empty or contained only
        // whitespace. That is illegal.
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_ATTRTYPE_EMPTY_VALUE.get();
        final LocalizableMessage message = ERR_ATTR_SYNTAX_ATTRTYPE_EMPTY_VALUE
            .get();
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -147,9 +167,8 @@
      final char c = reader.read();
      if (c != '(')
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_ATTRTYPE_EXPECTED_OPEN_PARENTHESIS.get(
                definition, (reader.pos() - 1), String.valueOf(c));
        final LocalizableMessage message = ERR_ATTR_SYNTAX_ATTRTYPE_EXPECTED_OPEN_PARENTHESIS
            .get(definition, (reader.pos() - 1), String.valueOf(c));
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -173,8 +192,8 @@
      boolean isCollective = false;
      boolean isNoUserModification = false;
      AttributeUsage attributeUsage = AttributeUsage.USER_APPLICATIONS;
      Map<String, List<String>> extraProperties =
          Collections.emptyMap();
      Map<String, List<String>> extraProperties = Collections
          .emptyMap();
      // At this point, we should have a pretty specific syntax that
      // describes what may come next, but some of the components are
@@ -312,9 +331,8 @@
          }
          else
          {
            final LocalizableMessage message =
                WARN_ATTR_SYNTAX_ATTRTYPE_INVALID_ATTRIBUTE_USAGE.get(
                    String.valueOf(oid), usageStr);
            final LocalizableMessage message = WARN_ATTR_SYNTAX_ATTRTYPE_INVALID_ATTRIBUTE_USAGE
                .get(String.valueOf(oid), usageStr);
            throw new LocalizedIllegalArgumentException(message);
          }
        }
@@ -334,25 +352,25 @@
        }
        else
        {
          final LocalizableMessage message =
              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
              .get(tokenName);
          throw new LocalizedIllegalArgumentException(message);
        }
      }
      final List<String> approxRules =
          extraProperties.get(SCHEMA_PROPERTY_APPROX_RULE);
      final List<String> approxRules = extraProperties
          .get(SCHEMA_PROPERTY_APPROX_RULE);
      if (approxRules != null && !approxRules.isEmpty())
      {
        approximateMatchingRule = approxRules.get(0);
      }
      final AttributeType attrType =
          new AttributeType(oid, names, description, isObsolete,
              superiorType, equalityMatchingRule, orderingMatchingRule,
              substringMatchingRule, approximateMatchingRule, syntax,
              isSingleValue, isCollective, isNoUserModification,
              attributeUsage, extraProperties, definition);
      final AttributeType attrType = new AttributeType(oid, names,
          description, isObsolete, superiorType, equalityMatchingRule,
          orderingMatchingRule, substringMatchingRule,
          approximateMatchingRule, syntax, isSingleValue, isCollective,
          isNoUserModification, attributeUsage, extraProperties,
          definition);
      addAttributeType(attrType, overwrite);
    }
@@ -433,12 +451,11 @@
      Map<String, List<String>> extraProperties, boolean overwrite)
      throws ConflictingSchemaElementException
  {
    final AttributeType attrType =
        new AttributeType(oid, names, description, obsolete,
            superiorType, equalityMatchingRule, orderingMatchingRule,
            substringMatchingRule, approximateMatchingRule, syntax,
            singleValue, collective, noUserModification,
            attributeUsage, extraProperties, null);
    final AttributeType attrType = new AttributeType(oid, names,
        description, obsolete, superiorType, equalityMatchingRule,
        orderingMatchingRule, substringMatchingRule,
        approximateMatchingRule, syntax, singleValue, collective,
        noUserModification, attributeUsage, extraProperties, null);
    addAttributeType(attrType, overwrite);
    return this;
  }
@@ -481,7 +498,8 @@
      {
        // This means that the value was empty or contained only
        // whitespace. That is illegal.
        final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_EMPTY_VALUE.get();
        final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_EMPTY_VALUE
            .get();
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -490,9 +508,8 @@
      final char c = reader.read();
      if (c != '(')
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_DCR_EXPECTED_OPEN_PARENTHESIS.get(
                definition, (reader.pos() - 1), String.valueOf(c));
        final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_EXPECTED_OPEN_PARENTHESIS
            .get(definition, (reader.pos() - 1), String.valueOf(c));
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -510,8 +527,8 @@
      Set<String> optionalAttributes = Collections.emptySet();
      Set<String> prohibitedAttributes = Collections.emptySet();
      Set<String> requiredAttributes = Collections.emptySet();
      Map<String, List<String>> extraProperties =
          Collections.emptyMap();
      Map<String, List<String>> extraProperties = Collections
          .emptyMap();
      // At this point, we should have a pretty specific syntax that
      // describes what may come next, but some of the components are
@@ -580,16 +597,15 @@
        }
        else
        {
          final LocalizableMessage message =
              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
              .get(tokenName);
          throw new LocalizedIllegalArgumentException(message);
        }
      }
      final DITContentRule rule =
          new DITContentRule(structuralClass, names, description,
              isObsolete, auxiliaryClasses, optionalAttributes,
              prohibitedAttributes, requiredAttributes,
      final DITContentRule rule = new DITContentRule(structuralClass,
          names, description, isObsolete, auxiliaryClasses,
          optionalAttributes, prohibitedAttributes, requiredAttributes,
              extraProperties, definition);
      addDITContentRule(rule, overwrite);
    }
@@ -648,11 +664,10 @@
      Map<String, List<String>> extraProperties, boolean overwrite)
      throws ConflictingSchemaElementException
  {
    final DITContentRule rule =
        new DITContentRule(structuralClass, names, description,
            obsolete, auxiliaryClasses, optionalAttributes,
            prohibitedAttributes, requiredAttributes, extraProperties,
            null);
    final DITContentRule rule = new DITContentRule(structuralClass,
        names, description, obsolete, auxiliaryClasses,
        optionalAttributes, prohibitedAttributes, requiredAttributes,
        extraProperties, null);
    addDITContentRule(rule, overwrite);
    return this;
  }
@@ -694,9 +709,9 @@
      Map<String, List<String>> extraProperties, boolean overwrite)
      throws ConflictingSchemaElementException
  {
    final DITStructureRule rule =
        new DITStructureRule(ruleID, names, description, obsolete,
            nameForm, superiorRules, extraProperties, null);
    final DITStructureRule rule = new DITStructureRule(ruleID, names,
        description, obsolete, nameForm, superiorRules,
        extraProperties, null);
    addDITStructureRule(rule, overwrite);
    return this;
  }
@@ -739,7 +754,8 @@
      {
        // This means that the value was empty or contained only
        // whitespace. That is illegal.
        final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_EMPTY_VALUE.get();
        final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_EMPTY_VALUE
            .get();
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -748,9 +764,8 @@
      final char c = reader.read();
      if (c != '(')
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_DSR_EXPECTED_OPEN_PARENTHESIS.get(
                definition, (reader.pos() - 1), String.valueOf(c));
        final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_EXPECTED_OPEN_PARENTHESIS
            .get(definition, (reader.pos() - 1), String.valueOf(c));
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -766,8 +781,8 @@
      boolean isObsolete = false;
      String nameForm = null;
      Set<Integer> superiorRules = Collections.emptySet();
      Map<String, List<String>> extraProperties =
          Collections.emptyMap();
      Map<String, List<String>> extraProperties = Collections
          .emptyMap();
      // At this point, we should have a pretty specific syntax that
      // describes what may come next, but some of the components are
@@ -828,22 +843,22 @@
        }
        else
        {
          final LocalizableMessage message =
              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
              .get(tokenName);
          throw new LocalizedIllegalArgumentException(message);
        }
      }
      if (nameForm == null)
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_DSR_NO_NAME_FORM.get(definition);
        final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_NO_NAME_FORM
            .get(definition);
        throw new LocalizedIllegalArgumentException(message);
      }
      final DITStructureRule rule =
          new DITStructureRule(ruleID, names, description, isObsolete,
              nameForm, superiorRules, extraProperties, definition);
      final DITStructureRule rule = new DITStructureRule(ruleID, names,
          description, isObsolete, nameForm, superiorRules,
          extraProperties, definition);
      addDITStructureRule(rule, overwrite);
    }
    catch (final DecodeException e)
@@ -881,15 +896,15 @@
  {
    Validator.ensureNotNull((Object) enumerations);
    final EnumSyntaxImpl enumImpl =
        new EnumSyntaxImpl(oid, Arrays.asList(enumerations));
    final Syntax enumSyntax =
        new Syntax(oid, description, Collections.singletonMap("X-ENUM",
            Arrays.asList(enumerations)), null, enumImpl);
    final MatchingRule enumOMR =
        new MatchingRule(enumImpl.getOrderingMatchingRule(),
            Collections.singletonList(OMR_GENERIC_ENUM_NAME + oid), "",
            false, oid, CoreSchemaImpl.OPENDS_ORIGIN, null,
    final EnumSyntaxImpl enumImpl = new EnumSyntaxImpl(oid, Arrays
        .asList(enumerations));
    final Syntax enumSyntax = new Syntax(oid, description, Collections
        .singletonMap("X-ENUM", Arrays.asList(enumerations)), null,
        enumImpl);
    final MatchingRule enumOMR = new MatchingRule(enumImpl
        .getOrderingMatchingRule(), Collections
        .singletonList(OMR_GENERIC_ENUM_NAME + oid), "", false, oid,
        CoreSchemaImpl.OPENDS_ORIGIN, null,
            new EnumOrderingMatchingRule(enumImpl));
    addSyntax(enumSyntax, overwrite);
@@ -941,7 +956,8 @@
      {
        // This means that the value was empty or contained only
        // whitespace. That is illegal.
        final LocalizableMessage message = ERR_ATTR_SYNTAX_MR_EMPTY_VALUE.get();
        final LocalizableMessage message = ERR_ATTR_SYNTAX_MR_EMPTY_VALUE
            .get();
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -950,9 +966,8 @@
      final char c = reader.read();
      if (c != '(')
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_MR_EXPECTED_OPEN_PARENTHESIS.get(
                definition, (reader.pos() - 1), String.valueOf(c));
        final LocalizableMessage message = ERR_ATTR_SYNTAX_MR_EXPECTED_OPEN_PARENTHESIS
            .get(definition, (reader.pos() - 1), String.valueOf(c));
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -967,8 +982,8 @@
      String description = "".intern();
      boolean isObsolete = false;
      String syntax = null;
      Map<String, List<String>> extraProperties =
          Collections.emptyMap();
      Map<String, List<String>> extraProperties = Collections
          .emptyMap();
      // At this point, we should have a pretty specific syntax that
      // describes what may come next, but some of the components are
@@ -1025,8 +1040,8 @@
        }
        else
        {
          final LocalizableMessage message =
              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
              .get(tokenName);
          throw new LocalizedIllegalArgumentException(message);
        }
      }
@@ -1034,8 +1049,8 @@
      // Make sure that a syntax was specified.
      if (syntax == null)
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_MR_NO_SYNTAX.get(definition);
        final LocalizableMessage message = ERR_ATTR_SYNTAX_MR_NO_SYNTAX
            .get(definition);
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -1087,9 +1102,9 @@
      throws ConflictingSchemaElementException
  {
    Validator.ensureNotNull(implementation);
    final MatchingRule matchingRule =
        new MatchingRule(oid, names, description, obsolete,
            assertionSyntax, extraProperties, null, implementation);
    final MatchingRule matchingRule = new MatchingRule(oid, names,
        description, obsolete, assertionSyntax, extraProperties, null,
        implementation);
    addMatchingRule(matchingRule, overwrite);
    return this;
  }
@@ -1132,7 +1147,8 @@
      {
        // This means that the value was empty or contained only
        // whitespace. That is illegal.
        final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_EMPTY_VALUE.get();
        final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_EMPTY_VALUE
            .get();
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -1141,9 +1157,8 @@
      final char c = reader.read();
      if (c != '(')
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_MRUSE_EXPECTED_OPEN_PARENTHESIS.get(
                definition, (reader.pos() - 1), String.valueOf(c));
        final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_EXPECTED_OPEN_PARENTHESIS
            .get(definition, (reader.pos() - 1), String.valueOf(c));
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -1158,8 +1173,8 @@
      String description = "".intern();
      boolean isObsolete = false;
      Set<String> attributes = null;
      Map<String, List<String>> extraProperties =
          Collections.emptyMap();
      Map<String, List<String>> extraProperties = Collections
          .emptyMap();
      // At this point, we should have a pretty specific syntax that
      // describes what may come next, but some of the components are
@@ -1216,8 +1231,8 @@
        }
        else
        {
          final LocalizableMessage message =
              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
              .get(tokenName);
          throw new LocalizedIllegalArgumentException(message);
        }
      }
@@ -1225,14 +1240,14 @@
      // Make sure that the set of attributes was defined.
      if (attributes == null || attributes.size() == 0)
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_MRUSE_NO_ATTR.get(definition);
        final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_NO_ATTR
            .get(definition);
        throw new LocalizedIllegalArgumentException(message);
      }
      final MatchingRuleUse use =
          new MatchingRuleUse(oid, names, description, isObsolete,
              attributes, extraProperties, definition);
      final MatchingRuleUse use = new MatchingRuleUse(oid, names,
          description, isObsolete, attributes, extraProperties,
          definition);
      addMatchingRuleUse(use, overwrite);
    }
    catch (final DecodeException e)
@@ -1278,9 +1293,8 @@
      Map<String, List<String>> extraProperties, boolean overwrite)
      throws ConflictingSchemaElementException
  {
    final MatchingRuleUse use =
        new MatchingRuleUse(oid, names, description, obsolete,
            attributeOIDs, extraProperties, null);
    final MatchingRuleUse use = new MatchingRuleUse(oid, names,
        description, obsolete, attributeOIDs, extraProperties, null);
    addMatchingRuleUse(use, overwrite);
    return this;
  }
@@ -1321,8 +1335,8 @@
      {
        // This means that the value was empty or contained only
        // whitespace. That is illegal.
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_NAME_FORM_EMPTY_VALUE.get();
        final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_EMPTY_VALUE
            .get();
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -1331,9 +1345,8 @@
      final char c = reader.read();
      if (c != '(')
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_NAME_FORM_EXPECTED_OPEN_PARENTHESIS.get(
                definition, (reader.pos() - 1), c);
        final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_EXPECTED_OPEN_PARENTHESIS
            .get(definition, (reader.pos() - 1), c);
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -1350,8 +1363,8 @@
      String structuralClass = null;
      Set<String> optionalAttributes = Collections.emptySet();
      Set<String> requiredAttributes = null;
      Map<String, List<String>> extraProperties =
          Collections.emptyMap();
      Map<String, List<String>> extraProperties = Collections
          .emptyMap();
      // At this point, we should have a pretty specific syntax that
      // describes what may come next, but some of the components are
@@ -1416,8 +1429,8 @@
        }
        else
        {
          final LocalizableMessage message =
              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
              .get(tokenName);
          throw new LocalizedIllegalArgumentException(message);
        }
      }
@@ -1426,23 +1439,21 @@
      // it cannot be valid.
      if (structuralClass == null)
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_NAME_FORM_NO_STRUCTURAL_CLASS
        final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_NO_STRUCTURAL_CLASS
                .get(definition);
        throw new LocalizedIllegalArgumentException(message);
      }
      if (requiredAttributes == null || requiredAttributes.size() == 0)
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_NAME_FORM_NO_REQUIRED_ATTR.get(definition);
        final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_NO_REQUIRED_ATTR
            .get(definition);
        throw new LocalizedIllegalArgumentException(message);
      }
      final NameForm nameForm =
          new NameForm(oid, names, description, isObsolete,
              structuralClass, requiredAttributes, optionalAttributes,
              extraProperties, definition);
      final NameForm nameForm = new NameForm(oid, names, description,
          isObsolete, structuralClass, requiredAttributes,
          optionalAttributes, extraProperties, definition);
      addNameForm(nameForm, overwrite);
    }
    catch (final DecodeException e)
@@ -1492,10 +1503,9 @@
      Map<String, List<String>> extraProperties, boolean overwrite)
      throws ConflictingSchemaElementException
  {
    final NameForm nameForm =
        new NameForm(oid, names, description, obsolete,
            structuralClass, requiredAttributes, optionalAttributes,
            extraProperties, null);
    final NameForm nameForm = new NameForm(oid, names, description,
        obsolete, structuralClass, requiredAttributes,
        optionalAttributes, extraProperties, null);
    addNameForm(nameForm, overwrite);
    return this;
  }
@@ -1537,8 +1547,8 @@
      {
        // This means that the value was empty or contained only
        // whitespace. That is illegal.
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_OBJECTCLASS_EMPTY_VALUE.get();
        final LocalizableMessage message = ERR_ATTR_SYNTAX_OBJECTCLASS_EMPTY_VALUE
            .get();
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -1547,9 +1557,8 @@
      final char c = reader.read();
      if (c != '(')
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_OBJECTCLASS_EXPECTED_OPEN_PARENTHESIS.get(
                definition, (reader.pos() - 1), String.valueOf(c));
        final LocalizableMessage message = ERR_ATTR_SYNTAX_OBJECTCLASS_EXPECTED_OPEN_PARENTHESIS
            .get(definition, (reader.pos() - 1), String.valueOf(c));
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -1567,8 +1576,8 @@
      Set<String> requiredAttributes = Collections.emptySet();
      Set<String> optionalAttributes = Collections.emptySet();
      ObjectClassType objectClassType = ObjectClassType.STRUCTURAL;
      Map<String, List<String>> extraProperties =
          Collections.emptyMap();
      Map<String, List<String>> extraProperties = Collections
          .emptyMap();
      // At this point, we should have a pretty specific syntax that
      // describes what may come next, but some of the components are
@@ -1653,8 +1662,8 @@
        }
        else
        {
          final LocalizableMessage message =
              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
              .get(tokenName);
          throw new LocalizedIllegalArgumentException(message);
        }
      }
@@ -1917,8 +1926,8 @@
      {
        // This means that the value was empty or contained only
        // whitespace. That is illegal.
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_ATTRSYNTAX_EMPTY_VALUE.get();
        final LocalizableMessage message = ERR_ATTR_SYNTAX_ATTRSYNTAX_EMPTY_VALUE
            .get();
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -1927,9 +1936,8 @@
      final char c = reader.read();
      if (c != '(')
      {
        final LocalizableMessage message =
            ERR_ATTR_SYNTAX_ATTRSYNTAX_EXPECTED_OPEN_PARENTHESIS.get(
                definition, (reader.pos() - 1), String.valueOf(c));
        final LocalizableMessage message = ERR_ATTR_SYNTAX_ATTRSYNTAX_EXPECTED_OPEN_PARENTHESIS
            .get(definition, (reader.pos() - 1), String.valueOf(c));
        throw new LocalizedIllegalArgumentException(message);
      }
@@ -1941,8 +1949,8 @@
      final String oid = SchemaUtils.readOID(reader);
      String description = "".intern();
      Map<String, List<String>> extraProperties =
          Collections.emptyMap();
      Map<String, List<String>> extraProperties = Collections
          .emptyMap();
      // At this point, we should have a pretty specific syntax that
      // describes what may come next, but some of the components are
@@ -1983,8 +1991,8 @@
        }
        else
        {
          final LocalizableMessage message =
              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
              .get(tokenName);
          throw new LocalizedIllegalArgumentException(message);
        }
      }
@@ -1995,16 +2003,14 @@
      {
        if (property.getKey().equalsIgnoreCase("x-enum"))
        {
          final EnumSyntaxImpl enumImpl =
              new EnumSyntaxImpl(oid, property.getValue());
          final Syntax enumSyntax =
              new Syntax(oid, description, extraProperties, definition,
                  enumImpl);
          final MatchingRule enumOMR =
              new MatchingRule(enumImpl.getOrderingMatchingRule(),
                  Collections
                      .singletonList(OMR_GENERIC_ENUM_NAME + oid), "",
                  false, oid, CoreSchemaImpl.OPENDS_ORIGIN, null,
          final EnumSyntaxImpl enumImpl = new EnumSyntaxImpl(oid,
              property.getValue());
          final Syntax enumSyntax = new Syntax(oid, description,
              extraProperties, definition, enumImpl);
          final MatchingRule enumOMR = new MatchingRule(enumImpl
              .getOrderingMatchingRule(), Collections
              .singletonList(OMR_GENERIC_ENUM_NAME + oid), "", false,
              oid, CoreSchemaImpl.OPENDS_ORIGIN, null,
                  new EnumOrderingMatchingRule(enumImpl));
          addSyntax(enumSyntax, overwrite);
@@ -2240,9 +2246,6 @@
   * contained in this schema builder as well as the same set of schema
   * compatibility options.
   * <p>
   * Any errors that were detected while validating the schema will be
   * ignored.
   * <p>
   * When this method returns this schema builder is empty and contains
   * a default set of compatibility options.
   *
@@ -2252,35 +2255,7 @@
   */
  public Schema toSchema()
  {
    return toSchema(null);
  }
  /**
   * Returns a {@code Schema} containing all of the schema elements
   * contained in this schema builder as well as the same set of schema
   * compatibility options.
   * <p>
   * When this method returns this schema builder is empty and contains
   * a default set of compatibility options.
   *
   * @param errorMessages
   *          A list into which any errors that were detected while
   *          validating the schema will be placed, may be {@code null}
   *          in which case any errors will be ignored.
   * @return A {@code Schema} containing all of the schema elements
   *         contained in this schema builder as well as the same set of
   *         schema compatibility options
   */
  public Schema toSchema(List<LocalizableMessage> errorMessages)
  {
    if (errorMessages == null)
    {
      errorMessages = new LinkedList<LocalizableMessage>();
    }
    validate(errorMessages);
    validate();
    final Schema builtSchema = schema;
    initBuilder();
    return builtSchema;
@@ -2288,19 +2263,25 @@
  void addWarning(LocalizableMessage warning)
  {
    warnings.add(warning);
  }
  private synchronized void addAttributeType(AttributeType attribute,
      boolean overwrite) throws ConflictingSchemaElementException
  {
    AttributeType conflictingAttribute;
    if (numericOID2AttributeTypes.containsKey(attribute.getOID()))
    {
      conflictingAttribute =
          numericOID2AttributeTypes.get(attribute.getOID());
      conflictingAttribute = numericOID2AttributeTypes.get(attribute
          .getOID());
      if (!overwrite)
      {
        final LocalizableMessage message =
            ERR_SCHEMA_CONFLICTING_ATTRIBUTE_OID.get(attribute
                .getNameOrOID(), attribute.getOID(),
        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_ATTRIBUTE_OID
            .get(attribute.getNameOrOID(), attribute.getOID(),
                conflictingAttribute.getNameOrOID());
        throw new ConflictingSchemaElementException(message);
      }
@@ -2339,13 +2320,12 @@
    if (numericOID2ContentRules.containsKey(rule
        .getStructuralClassOID()))
    {
      conflictingRule =
          numericOID2ContentRules.get(rule.getStructuralClassOID());
      conflictingRule = numericOID2ContentRules.get(rule
          .getStructuralClassOID());
      if (!overwrite)
      {
        final LocalizableMessage message =
            ERR_SCHEMA_CONFLICTING_DIT_CONTENT_RULE.get(rule
                .getNameOrOID(), rule.getStructuralClassOID(),
        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_DIT_CONTENT_RULE
            .get(rule.getNameOrOID(), rule.getStructuralClassOID(),
                conflictingRule.getNameOrOID());
        throw new ConflictingSchemaElementException(message);
      }
@@ -2386,10 +2366,9 @@
      conflictingRule = id2StructureRules.get(rule.getRuleID());
      if (!overwrite)
      {
        final LocalizableMessage message =
            ERR_SCHEMA_CONFLICTING_DIT_STRUCTURE_RULE_ID.get(rule
                .getNameOrRuleID(), rule.getRuleID(), conflictingRule
                .getNameOrRuleID());
        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_DIT_STRUCTURE_RULE_ID
            .get(rule.getNameOrRuleID(), rule.getRuleID(),
                conflictingRule.getNameOrRuleID());
        throw new ConflictingSchemaElementException(message);
      }
      removeDITStructureRule(conflictingRule);
@@ -2429,9 +2408,9 @@
      conflictingRule = numericOID2MatchingRules.get(rule.getOID());
      if (!overwrite)
      {
        final LocalizableMessage message =
            ERR_SCHEMA_CONFLICTING_MR_OID.get(rule.getNameOrOID(), rule
                .getOID(), conflictingRule.getNameOrOID());
        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_MR_OID
            .get(rule.getNameOrOID(), rule.getOID(), conflictingRule
                .getNameOrOID());
        throw new ConflictingSchemaElementException(message);
      }
      removeMatchingRule(conflictingRule);
@@ -2469,13 +2448,12 @@
    if (numericOID2MatchingRuleUses.containsKey(use
        .getMatchingRuleOID()))
    {
      conflictingUse =
          numericOID2MatchingRuleUses.get(use.getMatchingRuleOID());
      conflictingUse = numericOID2MatchingRuleUses.get(use
          .getMatchingRuleOID());
      if (!overwrite)
      {
        final LocalizableMessage message =
            ERR_SCHEMA_CONFLICTING_MATCHING_RULE_USE.get(use
                .getNameOrOID(), use.getMatchingRuleOID(),
        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_MATCHING_RULE_USE
            .get(use.getNameOrOID(), use.getMatchingRuleOID(),
                conflictingUse.getNameOrOID());
        throw new ConflictingSchemaElementException(message);
      }
@@ -2516,9 +2494,8 @@
      conflictingForm = numericOID2NameForms.get(form.getOID());
      if (!overwrite)
      {
        final LocalizableMessage message =
            ERR_SCHEMA_CONFLICTING_NAME_FORM_OID.get(form
                .getNameOrOID(), form.getOID(), conflictingForm
        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_NAME_FORM_OID
            .get(form.getNameOrOID(), form.getOID(), conflictingForm
                .getNameOrOID());
        throw new ConflictingSchemaElementException(message);
      }
@@ -2558,9 +2535,8 @@
      conflictingOC = numericOID2ObjectClasses.get(oc.getOID());
      if (!overwrite)
      {
        final LocalizableMessage message =
            ERR_SCHEMA_CONFLICTING_OBJECTCLASS_OID.get(oc
                .getNameOrOID(), oc.getOID(), conflictingOC
        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_OBJECTCLASS_OID
            .get(oc.getNameOrOID(), oc.getOID(), conflictingOC
                .getNameOrOID());
        throw new ConflictingSchemaElementException(message);
      }
@@ -2601,9 +2577,9 @@
      conflictingSyntax = numericOID2Syntaxes.get(syntax.getOID());
      if (!overwrite)
      {
        final LocalizableMessage message =
            ERR_SCHEMA_CONFLICTING_SYNTAX_OID.get(syntax.toString(),
                syntax.getOID(), conflictingSyntax.getOID());
        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_SYNTAX_OID
            .get(syntax.toString(), syntax.getOID(), conflictingSyntax
                .getOID());
        throw new ConflictingSchemaElementException(message);
      }
      removeSyntax(conflictingSyntax);
@@ -2617,8 +2593,7 @@
  {
    numericOID2Syntaxes = new HashMap<String, Syntax>();
    numericOID2MatchingRules = new HashMap<String, MatchingRule>();
    numericOID2MatchingRuleUses =
        new HashMap<String, MatchingRuleUse>();
    numericOID2MatchingRuleUses = new HashMap<String, MatchingRuleUse>();
    numericOID2AttributeTypes = new HashMap<String, AttributeType>();
    numericOID2ObjectClasses = new HashMap<String, ObjectClass>();
    numericOID2NameForms = new HashMap<String, NameForm>();
@@ -2626,8 +2601,7 @@
    id2StructureRules = new HashMap<Integer, DITStructureRule>();
    name2MatchingRules = new HashMap<String, List<MatchingRule>>();
    name2MatchingRuleUses =
        new HashMap<String, List<MatchingRuleUse>>();
    name2MatchingRuleUses = new HashMap<String, List<MatchingRuleUse>>();
    name2AttributeTypes = new HashMap<String, List<AttributeType>>();
    name2ObjectClasses = new HashMap<String, List<ObjectClass>>();
    name2NameForms = new HashMap<String, List<NameForm>>();
@@ -2635,18 +2609,18 @@
    name2StructureRules = new HashMap<String, List<DITStructureRule>>();
    objectClass2NameForms = new HashMap<String, List<NameForm>>();
    nameForm2StructureRules =
        new HashMap<String, List<DITStructureRule>>();
    nameForm2StructureRules = new HashMap<String, List<DITStructureRule>>();
    options = SchemaCompatOptions.defaultOptions();
    schema =
        new Schema(numericOID2Syntaxes, numericOID2MatchingRules,
    warnings = new LinkedList<LocalizableMessage>();
    schema = new Schema(numericOID2Syntaxes, numericOID2MatchingRules,
            numericOID2MatchingRuleUses, numericOID2AttributeTypes,
            numericOID2ObjectClasses, numericOID2NameForms,
            numericOID2ContentRules, id2StructureRules,
            name2MatchingRules, name2MatchingRuleUses,
            name2AttributeTypes, name2ObjectClasses, name2NameForms,
            name2ContentRules, name2StructureRules,
            objectClass2NameForms, nameForm2StructureRules, options);
        numericOID2ContentRules, id2StructureRules, name2MatchingRules,
        name2MatchingRuleUses, name2AttributeTypes, name2ObjectClasses,
        name2NameForms, name2ContentRules, name2StructureRules,
        objectClass2NameForms, nameForm2StructureRules, options,
        warnings);
  }
@@ -2658,8 +2632,8 @@
    for (final String name : attributeType.getNames())
    {
      final String lowerName = StaticUtils.toLowerCase(name);
      final List<AttributeType> attributes =
          name2AttributeTypes.get(lowerName);
      final List<AttributeType> attributes = name2AttributeTypes
          .get(lowerName);
      if (attributes != null && attributes.contains(attributeType))
      {
        if (attributes.size() <= 1)
@@ -2682,8 +2656,8 @@
    for (final String name : rule.getNames())
    {
      final String lowerName = StaticUtils.toLowerCase(name);
      final List<DITContentRule> rules =
          name2ContentRules.get(lowerName);
      final List<DITContentRule> rules = name2ContentRules
          .get(lowerName);
      if (rules != null && rules.contains(rule))
      {
        if (rules.size() <= 1)
@@ -2706,8 +2680,8 @@
    for (final String name : rule.getNames())
    {
      final String lowerName = StaticUtils.toLowerCase(name);
      final List<DITStructureRule> rules =
          name2StructureRules.get(lowerName);
      final List<DITStructureRule> rules = name2StructureRules
          .get(lowerName);
      if (rules != null && rules.contains(rule))
      {
        if (rules.size() <= 1)
@@ -2730,8 +2704,8 @@
    for (final String name : rule.getNames())
    {
      final String lowerName = StaticUtils.toLowerCase(name);
      final List<MatchingRule> rules =
          name2MatchingRules.get(lowerName);
      final List<MatchingRule> rules = name2MatchingRules
          .get(lowerName);
      if (rules != null && rules.contains(rule))
      {
        if (rules.size() <= 1)
@@ -2754,8 +2728,8 @@
    for (final String name : use.getNames())
    {
      final String lowerName = StaticUtils.toLowerCase(name);
      final List<MatchingRuleUse> uses =
          name2MatchingRuleUses.get(lowerName);
      final List<MatchingRuleUse> uses = name2MatchingRuleUses
          .get(lowerName);
      if (uses != null && uses.contains(use))
      {
        if (uses.size() <= 1)
@@ -2803,8 +2777,8 @@
    for (final String name : oc.getNames())
    {
      final String lowerName = StaticUtils.toLowerCase(name);
      final List<ObjectClass> classes =
          name2ObjectClasses.get(lowerName);
      final List<ObjectClass> classes = name2ObjectClasses
          .get(lowerName);
      if (classes != null && classes.contains(oc))
      {
        if (classes.size() <= 1)
@@ -2828,7 +2802,7 @@
  private synchronized void validate(List<LocalizableMessage> warnings)
  private synchronized void validate()
  {
    // Verify all references in all elements
    for (final Syntax syntax : numericOID2Syntaxes.values().toArray(
sdk/src/org/opends/sdk/schema/SchemaNotFoundException.java
File was deleted
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTest.java
File was renamed from sdk/tests/unit-tests-testng/src/org/opends/sdk/util/StaticUtilsTest.java
@@ -25,7 +25,7 @@
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.sdk.util;
package com.sun.opends.sdk.util;
sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTest.java
@@ -32,11 +32,12 @@
import java.util.Iterator;
import org.opends.sdk.schema.Schema;
import org.opends.sdk.util.LocalizedIllegalArgumentException;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.sdk.LocalizedIllegalArgumentException;
/**
sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTest.java
@@ -30,9 +30,10 @@
import org.opends.sdk.schema.Schema;
import org.opends.sdk.util.ByteString;
import org.testng.annotations.Test;
import org.opends.sdk.ByteString;
/**
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/ApproximateMatchingRuleTest.java
@@ -32,10 +32,11 @@
import static org.testng.Assert.assertEquals;
import org.opends.sdk.ConditionResult;
import org.opends.sdk.util.ByteString;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.sdk.ByteString;
/**
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/EnumSyntaxTestCase.java
@@ -32,11 +32,12 @@
import org.opends.sdk.ConditionResult;
import org.opends.sdk.DecodeException;
import org.opends.sdk.util.ByteString;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.sdk.ByteString;
/**
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleTest.java
@@ -33,10 +33,11 @@
import org.opends.sdk.Assertion;
import org.opends.sdk.ConditionResult;
import org.opends.sdk.DecodeException;
import org.opends.sdk.util.ByteString;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.sdk.ByteString;
/**
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OrderingMatchingRuleTest.java
@@ -31,11 +31,12 @@
import org.opends.sdk.Assertion;
import org.opends.sdk.ConditionResult;
import org.opends.sdk.DecodeException;
import org.opends.sdk.util.ByteString;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.sdk.ByteString;
/**
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstringMatchingRuleTest.java
@@ -35,11 +35,12 @@
import org.opends.sdk.ConditionResult;
import org.opends.sdk.DecodeException;
import org.opends.sdk.util.ByteSequence;
import org.opends.sdk.util.ByteString;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.sdk.ByteSequence;
import org.opends.sdk.ByteString;
/**
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SyntaxTestCase.java
@@ -32,10 +32,11 @@
import org.opends.messages.MessageBuilder;
import org.opends.sdk.DecodeException;
import org.opends.sdk.util.ByteString;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.sdk.ByteString;
/**