/* * 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/opendj3/legal-notices/CDDLv1_0.txt * or http://forgerock.org/license/CDDLv1.0.html. * 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/opendj3/legal-notices/CDDLv1_0.txt. 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-2010 Sun Microsystems, Inc. * Portions copyright 2011 ForgeRock AS */ package org.forgerock.opendj.ldap.schema; import static org.forgerock.opendj.ldap.CoreMessages.*; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.opendj.ldap.*; import com.forgerock.opendj.util.FutureResultTransformer; import com.forgerock.opendj.util.StaticUtils; import com.forgerock.opendj.util.Validator; /** * This class defines a data structure that holds information about the * components of the LDAP schema. It includes the following kinds of elements: *
* 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}.
*
* @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}.
* @return A future representing the retrieved schema.
* @throws UnsupportedOperationException
* If the connection does not support search operations.
* @throws IllegalStateException
* If the connection has already been closed, i.e. if
* {@code connection.isClosed() == true}.
* @throws NullPointerException
* If the {@code connection} or {@code name} was {@code null}.
*/
public static FutureResult
* 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
* connection.isClosed() == true}.
* @throws NullPointerException
* If the {@code connection} or {@code name} was {@code null}.
*/
public static Schema readSchema(final Connection connection, final DN name)
throws ErrorResultException, InterruptedException,
UnsupportedOperationException, IllegalStateException,
NullPointerException
{
return new SchemaBuilder().addSchema(connection, name, true).toSchema();
}
/**
* Reads the schema contained in the subschema sub-entry which applies to the
* named entry.
*
* 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}.
*
* This implementation first reads the {@code subschemaSubentry} attribute of
* the entry in order to identify the schema and then invokes
* {@link #readSchema(AsynchronousConnection, DN, ResultHandler)} to read the
* schema.
*
* @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}.
* @return A future representing the retrieved schema.
* @throws UnsupportedOperationException
* If the connection does not support search operations.
* @throws IllegalStateException
* If the connection has already been closed, i.e. if
* {@code connection.isClosed() == true}.
* @throws NullPointerException
* If the {@code connection} or {@code name} was {@code null}.
*/
public static FutureResult
* 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}.
*
* This implementation first reads the {@code subschemaSubentry} attribute of
* the entry in order to identify the schema and then invokes
* {@link #readSchema(Connection, DN)} to read the schema.
*
* @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
* connection.isClosed() == true}.
* @throws NullPointerException
* If the {@code connection} or {@code name} was {@code null}.
*/
public static Schema readSchemaForEntry(final Connection connection,
final DN name) throws ErrorResultException, InterruptedException,
UnsupportedOperationException, IllegalStateException,
NullPointerException
{
return new SchemaBuilder().addSchemaForEntry(connection, name, true)
.toSchema();
}
/**
* Sets the default schema which should be used by this application. The
* default schema is initially set to the core schema.
*
* @param schema
* The default schema which should be used by this application.
*/
public static void setDefaultSchema(final Schema schema)
{
Validator.ensureNotNull(schema);
DefaultSchema.schema = schema;
}
/**
* 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 entry
* The subschema subentry to be parsed.
* @return The parsed schema.
*/
public static Schema valueOf(final Entry entry)
{
return new SchemaBuilder(entry).toSchema();
}
static MatchingRule getDefaultMatchingRule()
{
return CoreSchema.getOctetStringMatchingRule();
}
static Syntax getDefaultSyntax()
{
return CoreSchema.getOctetStringSyntax();
}
private final Impl impl;
Schema(final String schemaName,
final Map
* By default this compatibility option is set to {@code true}.
*
* @return {@code true} if the Telephone Number syntax defined for this schema
* allows values which do not conform to the E.123 international
* telephone number format.
*/
public boolean allowNonStandardTelephoneNumbers()
{
return impl.getSchemaCompatOptions()
.allowNonStandardTelephoneNumbers();
}
/**
* Returns {@code true} if zero-length values will be allowed by the Directory
* String syntax defined for this schema. This is technically forbidden by the
* LDAP specification, but it was allowed in earlier versions of the server,
* and the discussion of the directory string syntax in RFC 2252 does not
* explicitly state that they are not allowed.
*
* By default this compatibility option is set to {@code false}.
*
* @return {@code true} if zero-length values will be allowed by the Directory
* String syntax defined for this schema, or {@code false} if not.
*/
public boolean allowZeroLengthDirectoryStrings()
{
return impl.getSchemaCompatOptions()
.allowZeroLengthDirectoryStrings();
}
/**
* Returns the attribute type with the specified name or numeric OID.
*
* @param name
* The name or OID of the attribute type to retrieve.
* @return The requested attribute type.
* @throws UnknownSchemaElementException
* If this is a strict schema and the requested attribute type was
* not found or if the provided name is ambiguous.
*/
public AttributeType getAttributeType(final String name)
throws UnknownSchemaElementException
{
return impl.getAttributeType(name);
}
/**
* Returns an unmodifiable collection containing all of the attribute types
* contained in this schema.
*
* @return An unmodifiable collection containing all of the attribute types
* contained in this schema.
*/
public Collection
* Attribute type queries against non-strict schema always succeed: if the
* requested attribute type is not found then a temporary attribute type is
* created automatically having the Octet String syntax and associated
* matching rules.
*
* Strict schema, on the other hand, throw an
* {@link UnknownSchemaElementException} whenever an attempt is made to
* retrieve a non-existent attribute type.
*
* @return {@code true} if this schema is strict.
*/
public boolean isStrict()
{
return impl.isStrict();
}
/**
* Returns a non-strict view of this schema.
*
* See the description of {@link #isStrict()} for more details.
*
* @return A non-strict view of this schema.
* @see Schema#isStrict()
*/
public Schema asNonStrictSchema()
{
if (impl.isStrict())
{
return new Schema(new NonStrictImpl(impl));
}
else
{
return this;
}
}
/**
* Returns a strict view of this schema.
*
* See the description of {@link #isStrict()} for more details.
*
* @return A strict view of this schema.
* @see Schema#isStrict()
*/
public Schema asStrictSchema()
{
if (impl.isStrict())
{
return this;
}
else
{
return new Schema(((NonStrictImpl) impl).strictImpl);
}
}
/**
* Adds the definitions of all the schema elements contained in this schema to
* the provided subschema subentry. Any existing attributes (including schema
* definitions) contained in the provided entry will be preserved.
*
* @param entry
* The subschema subentry to which all schema definitions should be
* added.
* @return The updated subschema subentry.
* @throws NullPointerException
* If {@code entry} was {@code null}.
*/
public Entry toEntry(Entry entry) throws NullPointerException
{
Attribute attr = new LinkedAttribute(Schema.ATTR_LDAP_SYNTAXES);
for (Syntax syntax : getSyntaxes())
{
attr.add(syntax.toString());
}
if (!attr.isEmpty())
{
entry.addAttribute(attr);
}
attr = new LinkedAttribute(Schema.ATTR_ATTRIBUTE_TYPES);
for (AttributeType attributeType : getAttributeTypes())
{
attr.add(attributeType.toString());
}
if (!attr.isEmpty())
{
entry.addAttribute(attr);
}
attr = new LinkedAttribute(Schema.ATTR_OBJECT_CLASSES);
for (ObjectClass objectClass : getObjectClasses())
{
attr.add(objectClass.toString());
}
if (!attr.isEmpty())
{
entry.addAttribute(attr);
}
attr = new LinkedAttribute(Schema.ATTR_MATCHING_RULE_USE);
for (MatchingRuleUse matchingRuleUse : getMatchingRuleUses())
{
attr.add(matchingRuleUse.toString());
}
if (!attr.isEmpty())
{
entry.addAttribute(attr);
}
attr = new LinkedAttribute(Schema.ATTR_MATCHING_RULES);
for (MatchingRule matchingRule : getMatchingRules())
{
attr.add(matchingRule.toString());
}
if (!attr.isEmpty())
{
entry.addAttribute(attr);
}
attr = new LinkedAttribute(Schema.ATTR_DIT_CONTENT_RULES);
for (DITContentRule ditContentRule : getDITContentRules())
{
attr.add(ditContentRule.toString());
}
if (!attr.isEmpty())
{
entry.addAttribute(attr);
}
attr = new LinkedAttribute(Schema.ATTR_DIT_STRUCTURE_RULES);
for (DITStructureRule ditStructureRule : getDITStuctureRules())
{
attr.add(ditStructureRule.toString());
}
if (!attr.isEmpty())
{
entry.addAttribute(attr);
}
attr = new LinkedAttribute(Schema.ATTR_NAME_FORMS);
for (NameForm nameForm : getNameForms())
{
attr.add(nameForm.toString());
}
if (!attr.isEmpty())
{
entry.addAttribute(attr);
}
return entry;
}
SchemaCompatOptions getSchemaCompatOptions()
{
return impl.getSchemaCompatOptions();
}
}
* USCORE = %x5F ; underscore ("_")
* DOT = %x2E ; period (".")
*
*
* By default this compatibility option is set to {@code true} because these
* characters are often used for naming purposes (such as collation rules).
*
* @return {@code true} if this schema allows certain illegal characters
* in OIDs and attribute options.
* @see RFC 4512 - Lightweight
* Directory Access Protocol (LDAP): Directory Information Models
*/
public boolean allowMalformedNamesAndOptions()
{
return impl.getSchemaCompatOptions().allowMalformedNamesAndOptions();
}
/**
* Returns {@code true} if the Telephone Number syntax defined for this schema
* allows values which do not conform to the E.123 international telephone
* number format.
*