2333N/A/*
2333N/A * CDDL HEADER START
2333N/A *
2333N/A * The contents of this file are subject to the terms of the
2333N/A * Common Development and Distribution License, Version 1.0 only
2333N/A * (the "License"). You may not use this file except in compliance
2333N/A * with the License.
2333N/A *
2333N/A * You can obtain a copy of the license at
2333N/A * trunk/opends/resource/legal-notices/OpenDS.LICENSE
2333N/A * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
2333N/A * See the License for the specific language governing permissions
2333N/A * and limitations under the License.
2333N/A *
2333N/A * When distributing Covered Code, include this CDDL HEADER in each
2333N/A * file and include the License file at
2333N/A * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
2333N/A * add the following below this CDDL HEADER, with the fields enclosed
2333N/A * by brackets "[]" replaced with your own identifying information:
2333N/A * Portions Copyright [yyyy] [name of copyright owner]
2333N/A *
2333N/A * CDDL HEADER END
2333N/A *
2333N/A *
4129N/A * Copyright 2008-2009 Sun Microsystems, Inc.
6092N/A * Portions Copyright 2013 ForgeRock, AS.
2333N/A */
2333N/Apackage org.opends.server.admin.client.ldap;
2333N/A
2333N/A
2333N/A
2333N/Aimport java.util.ArrayList;
2333N/Aimport java.util.Collection;
2333N/Aimport java.util.Collections;
2333N/Aimport java.util.HashSet;
2333N/Aimport java.util.LinkedList;
2333N/Aimport java.util.List;
2333N/Aimport java.util.Set;
2333N/Aimport java.util.SortedSet;
2333N/Aimport java.util.TreeSet;
2333N/A
2333N/Aimport javax.naming.NameNotFoundException;
2333N/Aimport javax.naming.NamingEnumeration;
2333N/Aimport javax.naming.NamingException;
2333N/Aimport javax.naming.NoPermissionException;
2333N/Aimport javax.naming.OperationNotSupportedException;
2333N/Aimport javax.naming.directory.Attribute;
2333N/Aimport javax.naming.directory.Attributes;
2333N/Aimport javax.naming.ldap.LdapName;
2333N/A
2358N/Aimport org.opends.messages.Message;
2333N/Aimport org.opends.server.admin.AbstractManagedObjectDefinition;
2407N/Aimport org.opends.server.admin.AggregationPropertyDefinition;
2333N/Aimport org.opends.server.admin.Configuration;
2333N/Aimport org.opends.server.admin.ConfigurationClient;
2333N/Aimport org.opends.server.admin.DefaultBehaviorException;
2333N/Aimport org.opends.server.admin.DefinitionDecodingException;
2333N/Aimport org.opends.server.admin.DefinitionResolver;
2333N/Aimport org.opends.server.admin.IllegalPropertyValueStringException;
2333N/Aimport org.opends.server.admin.InstantiableRelationDefinition;
2333N/Aimport org.opends.server.admin.LDAPProfile;
2333N/Aimport org.opends.server.admin.ManagedObjectDefinition;
2333N/Aimport org.opends.server.admin.ManagedObjectNotFoundException;
2333N/Aimport org.opends.server.admin.ManagedObjectPath;
2333N/Aimport org.opends.server.admin.PropertyDefinition;
2407N/Aimport org.opends.server.admin.PropertyDefinitionVisitor;
2333N/Aimport org.opends.server.admin.PropertyException;
2333N/Aimport org.opends.server.admin.PropertyIsMandatoryException;
2333N/Aimport org.opends.server.admin.PropertyIsSingleValuedException;
2333N/Aimport org.opends.server.admin.PropertyOption;
2407N/Aimport org.opends.server.admin.Reference;
2333N/Aimport org.opends.server.admin.RelationDefinition;
4129N/Aimport org.opends.server.admin.SetRelationDefinition;
2407N/Aimport org.opends.server.admin.UnknownPropertyDefinitionException;
2333N/Aimport org.opends.server.admin.DefinitionDecodingException.Reason;
2333N/Aimport org.opends.server.admin.client.AuthorizationException;
2333N/Aimport org.opends.server.admin.client.CommunicationException;
2333N/Aimport org.opends.server.admin.client.ManagedObject;
2333N/Aimport org.opends.server.admin.client.ManagedObjectDecodingException;
2333N/Aimport org.opends.server.admin.client.OperationRejectedException;
2543N/Aimport org.opends.server.admin.client.OperationRejectedException.OperationType;
2333N/Aimport org.opends.server.admin.client.spi.Driver;
2333N/Aimport org.opends.server.admin.client.spi.PropertySet;
2358N/Aimport org.opends.server.admin.std.client.RootCfgClient;
2358N/Aimport org.opends.server.admin.std.meta.RootCfgDefn;
2333N/A
2333N/A
2333N/A
2333N/A/**
2333N/A * The LDAP management context driver implementation.
2333N/A */
2333N/Afinal class LDAPDriver extends Driver {
2333N/A
2407N/A /**
2407N/A * A visitor which is used to decode property LDAP values.
2407N/A */
2407N/A private static final class ValueDecoder extends
2407N/A PropertyDefinitionVisitor<Object, String> {
2407N/A
2407N/A /**
2407N/A * Decodes the provided property LDAP value.
2407N/A *
2407N/A * @param
2407N/A * The type of the property.
2407N/A * @param pd
2407N/A * The property definition.
2407N/A * @param value
2407N/A * The LDAP string representation.
2407N/A * @return Returns the decoded LDAP value.
2407N/A * @throws IllegalPropertyValueStringException
2407N/A * If the property value could not be decoded because it
2407N/A * was invalid.
2407N/A */
2407N/A public static <PD> PD decode(PropertyDefinition<PD> pd, Object value)
2407N/A throws IllegalPropertyValueStringException {
2407N/A String s = String.valueOf(value);
2407N/A return pd.castValue(pd.accept(new ValueDecoder(), s));
2407N/A }
2407N/A
2407N/A
2407N/A
2407N/A // Prevent instantiation.
2407N/A private ValueDecoder() {
2407N/A // No implementation required.
2407N/A }
2407N/A
2407N/A
2407N/A
2407N/A /**
2407N/A * {@inheritDoc}
2407N/A */
2407N/A @Override
2407N/A public <C extends ConfigurationClient, S extends Configuration>
2407N/A Object visitAggregation(AggregationPropertyDefinition<C, S> d, String p) {
2407N/A // Aggregations values are stored as full DNs in LDAP, but
2407N/A // just their common name is exposed in the admin framework.
2407N/A try {
2407N/A Reference<C, S> reference = Reference.parseDN(d.getParentPath(), d
2407N/A .getRelationDefinition(), p);
2407N/A return reference.getName();
2407N/A } catch (IllegalArgumentException e) {
2407N/A throw new IllegalPropertyValueStringException(d, p);
2407N/A }
2407N/A }
2407N/A
2407N/A
2407N/A
2407N/A /**
2407N/A * {@inheritDoc}
2407N/A */
2407N/A @Override
2407N/A public <T> Object visitUnknown(PropertyDefinition<T> d, String p)
2407N/A throws UnknownPropertyDefinitionException {
2407N/A // By default the property definition's decoder will do.
2407N/A return d.decodeValue(p);
2407N/A }
2407N/A }
2407N/A
2407N/A
2407N/A
2333N/A // The LDAP connection.
2333N/A private final LDAPConnection connection;
2333N/A
2358N/A // The LDAP management context.
2358N/A private final LDAPManagementContext context;
2358N/A
2333N/A // The LDAP profile which should be used to construct LDAP
2333N/A // requests and decode LDAP responses.
2333N/A private final LDAPProfile profile;
2333N/A
2333N/A
2333N/A
2333N/A /**
2333N/A * Creates a new LDAP driver using the specified LDAP connection and
2333N/A * profile.
2333N/A *
2358N/A * @param context
2358N/A * The LDAP management context.
2333N/A * @param connection
2333N/A * The LDAP connection.
2333N/A * @param profile
2333N/A * The LDAP profile.
2333N/A */
2358N/A public LDAPDriver(LDAPManagementContext context, LDAPConnection connection,
2358N/A LDAPProfile profile) {
2358N/A this.context = context;
2333N/A this.connection = connection;
2333N/A this.profile = profile;
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A /**
2333N/A * {@inheritDoc}
2333N/A */
2333N/A @Override
2989N/A public void close() {
2989N/A connection.unbind();
2989N/A }
2989N/A
2989N/A
2989N/A
2989N/A /**
2989N/A * {@inheritDoc}
2989N/A */
2989N/A @Override
2333N/A public <C extends ConfigurationClient, S extends Configuration>
2333N/A ManagedObject<? extends C> getManagedObject(
2333N/A ManagedObjectPath<C, S> path) throws DefinitionDecodingException,
2333N/A ManagedObjectDecodingException, ManagedObjectNotFoundException,
2333N/A AuthorizationException, CommunicationException {
2349N/A if (!managedObjectExists(path)) {
2333N/A throw new ManagedObjectNotFoundException();
2333N/A }
2333N/A
2333N/A try {
2333N/A // Read the entry associated with the managed object.
2333N/A LdapName dn = LDAPNameBuilder.create(path, profile);
2333N/A AbstractManagedObjectDefinition<C, S> d = path
2333N/A .getManagedObjectDefinition();
2333N/A ManagedObjectDefinition<? extends C, ? extends S> mod =
2333N/A getEntryDefinition(d, dn);
2333N/A
2333N/A ArrayList<String> attrIds = new ArrayList<String>();
2333N/A for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
2333N/A String attrId = profile.getAttributeName(mod, pd);
2333N/A attrIds.add(attrId);
2333N/A }
2333N/A
2333N/A Attributes attributes = connection.readEntry(dn, attrIds);
2333N/A
2333N/A // Build the managed object's properties.
2333N/A List<PropertyException> exceptions = new LinkedList<PropertyException>();
2333N/A PropertySet newProperties = new PropertySet();
2333N/A for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
2333N/A String attrID = profile.getAttributeName(mod, pd);
2333N/A Attribute attribute = attributes.get(attrID);
2333N/A try {
2407N/A decodeProperty(newProperties, path, pd, attribute);
2333N/A } catch (PropertyException e) {
2333N/A exceptions.add(e);
2333N/A }
2333N/A }
2333N/A
2333N/A // If there were no decoding problems then return the object,
2333N/A // otherwise throw an operations exception.
2333N/A ManagedObject<? extends C> mo = createExistingManagedObject(mod, path,
2333N/A newProperties);
2333N/A if (exceptions.isEmpty()) {
2333N/A return mo;
2333N/A } else {
2333N/A throw new ManagedObjectDecodingException(mo, exceptions);
2333N/A }
2333N/A } catch (NameNotFoundException e) {
2333N/A throw new ManagedObjectNotFoundException();
2333N/A } catch (NoPermissionException e) {
2333N/A throw new AuthorizationException(e);
2333N/A } catch (NamingException e) {
2333N/A throw new CommunicationException(e);
2333N/A }
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A /**
2333N/A * {@inheritDoc}
2333N/A */
2407N/A @SuppressWarnings("unchecked")
2333N/A @Override
2407N/A public <C extends ConfigurationClient, S extends Configuration, PD>
2407N/A SortedSet<PD> getPropertyValues(ManagedObjectPath<C, S> path,
2333N/A PropertyDefinition<PD> pd) throws IllegalArgumentException,
2333N/A DefinitionDecodingException, AuthorizationException,
2333N/A ManagedObjectNotFoundException, CommunicationException,
2333N/A PropertyException {
2407N/A // Check that the requested property is from the definition
2407N/A // associated with the path.
2407N/A AbstractManagedObjectDefinition<C, S> d = path.getManagedObjectDefinition();
2407N/A PropertyDefinition<?> tmp = d.getPropertyDefinition(pd.getName());
2407N/A if (tmp != pd) {
2407N/A throw new IllegalArgumentException("The property " + pd.getName()
2407N/A + " is not associated with a " + d.getName());
2407N/A }
2407N/A
2349N/A if (!managedObjectExists(path)) {
2333N/A throw new ManagedObjectNotFoundException();
2333N/A }
2333N/A
2333N/A try {
2333N/A // Read the entry associated with the managed object.
2333N/A LdapName dn = LDAPNameBuilder.create(path, profile);
2407N/A ManagedObjectDefinition<? extends C, ? extends S> mod;
2407N/A mod = getEntryDefinition(d, dn);
2407N/A
2407N/A // Make sure we use the correct property definition, the
2407N/A // provided one might have been overridden in the resolved
2407N/A // definition.
2407N/A pd = (PropertyDefinition<PD>) mod.getPropertyDefinition(pd.getName());
2333N/A
2333N/A String attrID = profile.getAttributeName(mod, pd);
2333N/A Attributes attributes = connection.readEntry(dn, Collections
2333N/A .singleton(attrID));
2333N/A Attribute attribute = attributes.get(attrID);
2333N/A
2407N/A // Decode the values.
2333N/A SortedSet<PD> values = new TreeSet<PD>(pd);
2407N/A if (attribute != null) {
2333N/A NamingEnumeration<?> ldapValues = attribute.getAll();
2333N/A while (ldapValues.hasMore()) {
2333N/A Object obj = ldapValues.next();
2333N/A if (obj != null) {
2407N/A PD value = ValueDecoder.decode(pd, obj);
2333N/A values.add(value);
2333N/A }
2333N/A }
2333N/A }
2333N/A
2333N/A // Sanity check the returned values.
2333N/A if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
2333N/A throw new PropertyIsSingleValuedException(pd);
2333N/A }
2333N/A
2333N/A if (values.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) {
2333N/A throw new PropertyIsMandatoryException(pd);
2333N/A }
2333N/A
2407N/A if (values.isEmpty()) {
2407N/A // Use the property's default values.
2407N/A values.addAll(findDefaultValues(path.asSubType(mod), pd, false));
2407N/A }
2407N/A
2333N/A return values;
2333N/A } catch (NameNotFoundException e) {
2333N/A throw new ManagedObjectNotFoundException();
2333N/A } catch (NoPermissionException e) {
2333N/A throw new AuthorizationException(e);
2333N/A } catch (NamingException e) {
2333N/A throw new CommunicationException(e);
2333N/A }
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A /**
2333N/A * {@inheritDoc}
2333N/A */
2333N/A @Override
2358N/A public ManagedObject<RootCfgClient> getRootConfigurationManagedObject() {
2358N/A return new LDAPManagedObject<RootCfgClient>(this,
2358N/A RootCfgDefn.getInstance(), ManagedObjectPath.emptyPath(),
2358N/A new PropertySet(), true, null);
2358N/A }
2358N/A
2358N/A
2358N/A
2358N/A /**
2358N/A * {@inheritDoc}
2358N/A */
2358N/A @Override
2333N/A public <C extends ConfigurationClient, S extends Configuration>
2333N/A String[] listManagedObjects(
2333N/A ManagedObjectPath<?, ?> parent, InstantiableRelationDefinition<C, S> rd,
2333N/A AbstractManagedObjectDefinition<? extends C, ? extends S> d)
2333N/A throws IllegalArgumentException, ManagedObjectNotFoundException,
2333N/A AuthorizationException, CommunicationException {
2333N/A validateRelationDefinition(parent, rd);
2333N/A
2349N/A if (!managedObjectExists(parent)) {
2333N/A throw new ManagedObjectNotFoundException();
2333N/A }
2333N/A
2333N/A // Get the search base DN.
2333N/A LdapName dn = LDAPNameBuilder.create(parent, rd, profile);
2333N/A
2333N/A // Retrieve only those entries which are sub-types of the
2333N/A // specified definition.
2333N/A StringBuilder builder = new StringBuilder();
2333N/A builder.append("(objectclass=");
2333N/A builder.append(profile.getObjectClass(d));
2333N/A builder.append(')');
2333N/A String filter = builder.toString();
2333N/A
2333N/A List<String> children = new ArrayList<String>();
2333N/A try {
2333N/A for (LdapName child : connection.listEntries(dn, filter)) {
2333N/A children.add(child.getRdn(child.size() - 1).getValue().toString());
2333N/A }
2333N/A } catch (NameNotFoundException e) {
2333N/A // Ignore this - it means that the base entry does not exist
2333N/A // (which it might not if this managed object has just been
2333N/A // created.
2333N/A } catch (NamingException e) {
2333N/A adaptNamingException(e);
2333N/A }
2333N/A
2333N/A return children.toArray(new String[children.size()]);
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A /**
2349N/A * {@inheritDoc}
2349N/A */
2349N/A @Override
4129N/A public <C extends ConfigurationClient, S extends Configuration>
4129N/A String[] listManagedObjects(
4129N/A ManagedObjectPath<?, ?> parent, SetRelationDefinition<C, S> rd,
4129N/A AbstractManagedObjectDefinition<? extends C, ? extends S> d)
4129N/A throws IllegalArgumentException, ManagedObjectNotFoundException,
4129N/A AuthorizationException, CommunicationException {
4129N/A validateRelationDefinition(parent, rd);
4129N/A
4129N/A if (!managedObjectExists(parent)) {
4129N/A throw new ManagedObjectNotFoundException();
4129N/A }
4129N/A
4129N/A // Get the search base DN.
4129N/A LdapName dn = LDAPNameBuilder.create(parent, rd, profile);
4129N/A
4129N/A // Retrieve only those entries which are sub-types of the
4129N/A // specified definition.
4129N/A StringBuilder builder = new StringBuilder();
4129N/A builder.append("(objectclass=");
4129N/A builder.append(profile.getObjectClass(d));
4129N/A builder.append(')');
4129N/A String filter = builder.toString();
4129N/A
4129N/A List<String> children = new ArrayList<String>();
4129N/A try {
4129N/A for (LdapName child : connection.listEntries(dn, filter)) {
4129N/A children.add(child.getRdn(child.size() - 1).getValue().toString());
4129N/A }
4129N/A } catch (NameNotFoundException e) {
4129N/A // Ignore this - it means that the base entry does not exist
4129N/A // (which it might not if this managed object has just been
4129N/A // created.
4129N/A } catch (NamingException e) {
4129N/A adaptNamingException(e);
4129N/A }
4129N/A
4129N/A return children.toArray(new String[children.size()]);
4129N/A }
4129N/A
4129N/A
4129N/A
4129N/A /**
4129N/A * {@inheritDoc}
4129N/A */
4129N/A @Override
2349N/A public boolean managedObjectExists(ManagedObjectPath<?, ?> path)
2349N/A throws ManagedObjectNotFoundException, AuthorizationException,
2349N/A CommunicationException {
2349N/A if (path.isEmpty()) {
2349N/A return true;
2349N/A }
2349N/A
2358N/A ManagedObjectPath<?, ?> parent = path.parent();
2349N/A LdapName dn = LDAPNameBuilder.create(parent, profile);
2349N/A if (!entryExists(dn)) {
2349N/A throw new ManagedObjectNotFoundException();
2349N/A }
2349N/A
2349N/A dn = LDAPNameBuilder.create(path, profile);
2349N/A return entryExists(dn);
2349N/A }
2349N/A
2349N/A
2349N/A
2349N/A /**
2358N/A * {@inheritDoc}
2358N/A */
2358N/A @Override
2358N/A protected <C extends ConfigurationClient, S extends Configuration>
2358N/A void deleteManagedObject(
2358N/A ManagedObjectPath<C, S> path) throws OperationRejectedException,
2358N/A AuthorizationException, CommunicationException {
2358N/A // Delete the entry and any subordinate entries.
2358N/A LdapName dn = LDAPNameBuilder.create(path, profile);
2358N/A try {
2358N/A connection.deleteSubtree(dn);
2358N/A } catch (OperationNotSupportedException e) {
2358N/A // Unwilling to perform.
2543N/A AbstractManagedObjectDefinition<?, ?> d =
2543N/A path.getManagedObjectDefinition();
2370N/A if (e.getMessage() == null) {
2543N/A throw new OperationRejectedException(OperationType.DELETE, d
2543N/A .getUserFriendlyName());
2358N/A } else {
2358N/A Message m = Message.raw("%s", e.getMessage());
2543N/A throw new OperationRejectedException(OperationType.DELETE, d
2543N/A .getUserFriendlyName(), m);
2358N/A }
2358N/A } catch (NamingException e) {
2358N/A adaptNamingException(e);
2358N/A }
2358N/A }
2358N/A
2358N/A
2358N/A
2358N/A /**
2358N/A * {@inheritDoc}
2358N/A */
2358N/A @Override
2358N/A protected LDAPManagementContext getManagementContext() {
2358N/A return context;
2358N/A }
2358N/A
2358N/A
2358N/A
2358N/A /**
2333N/A * Adapts a naming exception to an appropriate admin client
2333N/A * exception.
2333N/A *
2333N/A * @param ne
2333N/A * The naming exception.
2333N/A * @throws CommunicationException
2333N/A * If the naming exception mapped to a communication
2333N/A * exception.
2333N/A * @throws AuthorizationException
2333N/A * If the naming exception mapped to an authorization
2333N/A * exception.
2333N/A */
2333N/A void adaptNamingException(NamingException ne) throws CommunicationException,
2333N/A AuthorizationException {
2333N/A try {
2333N/A throw ne;
2333N/A } catch (javax.naming.CommunicationException e) {
2333N/A throw new CommunicationException(e);
2333N/A } catch (javax.naming.ServiceUnavailableException e) {
2333N/A throw new CommunicationException(e);
2333N/A } catch (javax.naming.NoPermissionException e) {
2333N/A throw new AuthorizationException(e);
2333N/A } catch (NamingException e) {
2333N/A // Just treat it as a communication problem.
2333N/A throw new CommunicationException(e);
2333N/A }
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A /**
2333N/A * Determines whether the named LDAP entry exists.
2333N/A *
2333N/A * @param dn
2333N/A * The LDAP entry name.
2333N/A * @return Returns <code>true</code> if the named LDAP entry
2333N/A * exists.
2333N/A * @throws AuthorizationException
2333N/A * If the server refuses to make the determination because
2333N/A * the client does not have the correct privileges.
2333N/A * @throws CommunicationException
2333N/A * If the client cannot contact the server due to an
2333N/A * underlying communication problem.
2333N/A */
2333N/A boolean entryExists(LdapName dn) throws CommunicationException,
2333N/A AuthorizationException {
2333N/A try {
2333N/A return connection.entryExists(dn);
2333N/A } catch (NamingException e) {
2333N/A adaptNamingException(e);
2333N/A }
2333N/A return false;
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A /**
2333N/A * Gets the LDAP connection used for interacting with the server.
2333N/A *
2333N/A * @return Returns the LDAP connection used for interacting with the
2333N/A * server.
2333N/A */
2333N/A LDAPConnection getLDAPConnection() {
2333N/A return connection;
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A /**
2333N/A * Gets the LDAP profile which should be used to construct LDAP
2333N/A * requests and decode LDAP responses.
2333N/A *
2333N/A * @return Returns the LDAP profile which should be used to
2333N/A * construct LDAP requests and decode LDAP responses.
2333N/A */
2333N/A LDAPProfile getLDAPProfile() {
2333N/A return profile;
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A // Create a managed object which already exists on the server.
2333N/A private <M extends ConfigurationClient, N extends Configuration>
2333N/A ManagedObject<M> createExistingManagedObject(
2333N/A ManagedObjectDefinition<M, N> d,
2333N/A ManagedObjectPath<? super M, ? super N> p, PropertySet properties) {
2333N/A RelationDefinition<?, ?> rd = p.getRelationDefinition();
2333N/A PropertyDefinition<?> pd = null;
2333N/A if (rd instanceof InstantiableRelationDefinition) {
2333N/A InstantiableRelationDefinition<?, ?> ird =
2333N/A (InstantiableRelationDefinition<?, ?>) rd;
2333N/A pd = ird.getNamingPropertyDefinition();
2333N/A }
2333N/A return new LDAPManagedObject<M>(this, d, p.asSubType(d), properties, true,
2333N/A pd);
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A // Create a property using the provided string values.
2333N/A private <PD> void decodeProperty(PropertySet newProperties,
2407N/A ManagedObjectPath<?, ?> p, PropertyDefinition<PD> pd,
2407N/A Attribute attribute) throws PropertyException,
2407N/A NamingException {
2333N/A PropertyException exception = null;
2333N/A
2333N/A // Get the property's active values.
2407N/A SortedSet<PD> activeValues = new TreeSet<PD>(pd);
2407N/A if (attribute != null) {
2407N/A NamingEnumeration<?> ldapValues = attribute.getAll();
2407N/A while (ldapValues.hasMore()) {
2407N/A Object obj = ldapValues.next();
2407N/A if (obj != null) {
2407N/A PD value = ValueDecoder.decode(pd, obj);
2407N/A activeValues.add(value);
2407N/A }
2333N/A }
2333N/A }
2333N/A
2333N/A if (activeValues.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
2333N/A // This exception takes precedence over previous exceptions.
2333N/A exception = new PropertyIsSingleValuedException(pd);
2407N/A PD value = activeValues.first();
2333N/A activeValues.clear();
2333N/A activeValues.add(value);
2333N/A }
2333N/A
2333N/A // Get the property's default values.
2333N/A Collection<PD> defaultValues;
2333N/A try {
2333N/A defaultValues = findDefaultValues(p, pd, false);
2333N/A } catch (DefaultBehaviorException e) {
2333N/A defaultValues = Collections.emptySet();
2333N/A exception = e;
2333N/A }
2333N/A
2333N/A newProperties.addProperty(pd, defaultValues, activeValues);
6092N/A
6092N/A if (activeValues.isEmpty() && defaultValues.isEmpty()
6092N/A && pd.hasOption(PropertyOption.MANDATORY)) {
6092N/A // The active values maybe empty because of a previous
6092N/A // exception.
6092N/A if (exception == null) {
6092N/A exception = new PropertyIsMandatoryException(pd);
6092N/A }
6092N/A }
6092N/A
2333N/A if (exception != null) {
2333N/A throw exception;
2333N/A }
2333N/A }
2333N/A
2333N/A
2333N/A
2333N/A // Determine the type of managed object associated with the named
2333N/A // entry.
2333N/A private <C extends ConfigurationClient, S extends Configuration>
2333N/A ManagedObjectDefinition<? extends C, ? extends S> getEntryDefinition(
2333N/A AbstractManagedObjectDefinition<C, S> d, LdapName dn)
2333N/A throws NamingException, DefinitionDecodingException {
2333N/A Attributes attributes = connection.readEntry(dn, Collections
2333N/A .singleton("objectclass"));
2333N/A Attribute oc = attributes.get("objectclass");
2333N/A
2333N/A if (oc == null) {
2333N/A // No object classes.
2367N/A throw new DefinitionDecodingException(d, Reason.NO_TYPE_INFORMATION);
2333N/A }
2333N/A
2333N/A final Set<String> objectClasses = new HashSet<String>();
2333N/A NamingEnumeration<?> values = oc.getAll();
2333N/A while (values.hasMore()) {
2333N/A Object value = values.next();
2333N/A if (value != null) {
2333N/A objectClasses.add(value.toString().toLowerCase().trim());
2333N/A }
2333N/A }
2333N/A
2333N/A if (objectClasses.isEmpty()) {
2333N/A // No object classes.
2367N/A throw new DefinitionDecodingException(d, Reason.NO_TYPE_INFORMATION);
2333N/A }
2333N/A
2333N/A // Resolve the appropriate sub-type based on the object classes.
2333N/A DefinitionResolver resolver = new DefinitionResolver() {
2333N/A
2333N/A public boolean matches(AbstractManagedObjectDefinition<?, ?> d) {
2333N/A String objectClass = profile.getObjectClass(d);
2333N/A return objectClasses.contains(objectClass);
2333N/A }
2333N/A
2333N/A };
2333N/A
2333N/A return d.resolveManagedObjectDefinition(resolver);
2333N/A }
2333N/A}