From 2bc8d15a28fafab97cefafede06d6b7e738ae0fe Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 11 Dec 2009 18:45:45 +0000
Subject: [PATCH] Various incremental improvements.
---
sdk/src/org/opends/sdk/schema/Schema.java | 434 +++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 363 insertions(+), 71 deletions(-)
diff --git a/sdk/src/org/opends/sdk/schema/Schema.java b/sdk/src/org/opends/sdk/schema/Schema.java
index d045f88..1dcc5b7 100644
--- a/sdk/src/org/opends/sdk/schema/Schema.java
+++ b/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.
*
--
Gitblit v1.10.0