| | |
| | | import javax.naming.ldap.LdapName; |
| | | import javax.naming.ldap.Rdn; |
| | | |
| | | import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider; |
| | | import org.opends.server.admin.AbstractManagedObjectDefinition; |
| | | import org.opends.server.admin.AliasDefaultBehaviorProvider; |
| | | import org.opends.server.admin.ConfigurationClient; |
| | | import org.opends.server.admin.DefaultBehaviorException; |
| | | import org.opends.server.admin.DefaultBehaviorProviderVisitor; |
| | | import org.opends.server.admin.DefinedDefaultBehaviorProvider; |
| | | import org.opends.server.admin.DefinitionDecodingException; |
| | | import org.opends.server.admin.DefinitionResolver; |
| | | import org.opends.server.admin.IllegalPropertyValueException; |
| | | import org.opends.server.admin.InheritedDefaultValueProvider; |
| | | import org.opends.server.admin.IllegalPropertyValueStringException; |
| | | import org.opends.server.admin.InstantiableRelationDefinition; |
| | | import org.opends.server.admin.ManagedObjectAlreadyExistsException; |
| | | import org.opends.server.admin.ManagedObjectDefinition; |
| | | import org.opends.server.admin.ManagedObjectNotFoundException; |
| | | import org.opends.server.admin.ManagedObjectPath; |
| | | import org.opends.server.admin.OperationsException; |
| | | import org.opends.server.admin.OptionalRelationDefinition; |
| | | import org.opends.server.admin.PropertyDefinition; |
| | | import org.opends.server.admin.PropertyException; |
| | |
| | | import org.opends.server.admin.PropertyIsReadOnlyException; |
| | | import org.opends.server.admin.PropertyIsSingleValuedException; |
| | | import org.opends.server.admin.PropertyNotFoundException; |
| | | import org.opends.server.admin.PropertyProvider; |
| | | import org.opends.server.admin.PropertyOption; |
| | | import org.opends.server.admin.RelationDefinition; |
| | | import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider; |
| | | import org.opends.server.admin.SingletonRelationDefinition; |
| | | import org.opends.server.admin.StringPropertyProvider; |
| | | import org.opends.server.admin.UndefinedDefaultBehaviorProvider; |
| | | import org.opends.server.admin.DefinitionDecodingException.Reason; |
| | | import org.opends.server.admin.client.AuthorizationException; |
| | | import org.opends.server.admin.client.CommunicationException; |
| | | import org.opends.server.admin.client.ConcurrentModificationException; |
| | | import org.opends.server.admin.client.ManagedObject; |
| | | import org.opends.server.admin.client.ManagedObjectDecodingException; |
| | | import org.opends.server.admin.client.MissingMandatoryPropertiesException; |
| | | import org.opends.server.admin.client.OperationRejectedException; |
| | | import org.opends.server.admin.client.Property; |
| | | import org.opends.server.admin.client.PropertySet; |
| | |
| | | ManagedObject<C> { |
| | | |
| | | /** |
| | | * Internal inherited default value provider implementation. |
| | | * A default behavior visitor used for retrieving the default values |
| | | * of a property. |
| | | * |
| | | * @param <T> |
| | | * The type of the property. |
| | | */ |
| | | private static class MyInheritedDefaultValueProvider implements |
| | | InheritedDefaultValueProvider { |
| | | private static class DefaultValueFinder<T> implements |
| | | DefaultBehaviorProviderVisitor<T, Collection<T>, ManagedObjectPath> { |
| | | |
| | | /** |
| | | * Get the default values for the specified property. |
| | | * |
| | | * @param <T> |
| | | * The type of the property. |
| | | * @param context |
| | | * The LDAP management context. |
| | | * @param p |
| | | * The managed object path of the current managed object. |
| | | * @param pd |
| | | * The property definition. |
| | | * @return Returns the default values for the specified property. |
| | | * @throws DefaultBehaviorException |
| | | * If the default values could not be retrieved or |
| | | * decoded properly. |
| | | */ |
| | | public static <T> Collection<T> getDefaultValues( |
| | | LDAPManagementContext context, ManagedObjectPath p, |
| | | PropertyDefinition<T> pd) throws DefaultBehaviorException { |
| | | DefaultValueFinder<T> v = new DefaultValueFinder<T>(context, pd); |
| | | Collection<T> values = pd.getDefaultBehaviorProvider().accept(v, p); |
| | | |
| | | if (v.exception != null) { |
| | | throw v.exception; |
| | | } |
| | | |
| | | if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) { |
| | | throw new DefaultBehaviorException(pd, |
| | | new PropertyIsSingleValuedException(pd)); |
| | | } |
| | | |
| | | return values; |
| | | } |
| | | |
| | | // The LDAP management context. |
| | | private final LDAPManagementContext context; |
| | | |
| | | // The base path. |
| | | private final ManagedObjectPath path; |
| | | // Any exception that occurred whilst retrieving inherited default |
| | | // values. |
| | | private DefaultBehaviorException exception = null; |
| | | |
| | | // The property definition whose default values are required. |
| | | private final PropertyDefinition<T> pd; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Create a new inherited default value provider. |
| | | * |
| | | * @param context |
| | | * The LDAP management context. |
| | | * @param path |
| | | * The base path. |
| | | */ |
| | | public MyInheritedDefaultValueProvider(LDAPManagementContext context, |
| | | ManagedObjectPath path) { |
| | | // Private constructor. |
| | | private DefaultValueFinder(LDAPManagementContext context, |
| | | PropertyDefinition<T> pd) { |
| | | this.context = context; |
| | | this.path = path; |
| | | this.pd = pd; |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<?> getDefaultPropertyValues(ManagedObjectPath path, |
| | | String propertyName) throws OperationsException, |
| | | PropertyNotFoundException { |
| | | ManagedObjectPath<?, ?> tmp = path; |
| | | ManagedObject<?> mo; |
| | | public Collection<T> visitAbsoluteInherited( |
| | | AbsoluteInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) { |
| | | try { |
| | | mo = readEntry(context, tmp, tmp.getManagedObjectDefinition()); |
| | | } catch (AuthorizationException e) { |
| | | throw new OperationsException(e); |
| | | } catch (CommunicationException e) { |
| | | throw new OperationsException(e); |
| | | return getInheritedProperty(d.getManagedObjectPath(), d |
| | | .getManagedObjectDefinition(), d.getPropertyName()); |
| | | } catch (DefaultBehaviorException e) { |
| | | exception = new DefaultBehaviorException(pd, e); |
| | | } |
| | | ManagedObjectDefinition<?, ?> mod = mo.getManagedObjectDefinition(); |
| | | |
| | | try { |
| | | PropertyDefinition<?> dpd = mod.getPropertyDefinition(propertyName); |
| | | return mo.getPropertyValues(dpd); |
| | | } catch (IllegalArgumentException e) { |
| | | throw new PropertyNotFoundException(propertyName); |
| | | } |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ManagedObjectPath getManagedObjectPath() { |
| | | return path; |
| | | public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d, |
| | | ManagedObjectPath p) { |
| | | return Collections.emptySet(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d, |
| | | ManagedObjectPath p) { |
| | | Collection<String> stringValues = d.getDefaultValues(); |
| | | List<T> values = new ArrayList<T>(stringValues.size()); |
| | | |
| | | for (String stringValue : stringValues) { |
| | | try { |
| | | values.add(pd.decodeValue(stringValue)); |
| | | } catch (IllegalPropertyValueStringException e) { |
| | | exception = new DefaultBehaviorException(pd, e); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return values; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<T> visitRelativeInherited( |
| | | RelativeInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) { |
| | | try { |
| | | return getInheritedProperty(d.getManagedObjectPath(p), d |
| | | .getManagedObjectDefinition(), d.getPropertyName()); |
| | | } catch (DefaultBehaviorException e) { |
| | | exception = new DefaultBehaviorException(pd, e); |
| | | } |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d, |
| | | ManagedObjectPath p) { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | |
| | | |
| | | // Get an inherited property value. |
| | | private Collection<T> getInheritedProperty(ManagedObjectPath target, |
| | | AbstractManagedObjectDefinition<?, ?> d, String propertyName) |
| | | throws DefaultBehaviorException { |
| | | try { |
| | | // First check that the requested type of managed object |
| | | // corresponds to the path. |
| | | AbstractManagedObjectDefinition<?, ?> supr = target |
| | | .getManagedObjectDefinition(); |
| | | if (!supr.isParentOf(d)) { |
| | | throw new DefinitionDecodingException(Reason.WRONG_TYPE_INFORMATION); |
| | | } |
| | | |
| | | // Get the actual managed object definition. |
| | | LdapName dn = LDAPNameBuilder.create(target, context.getLDAPProfile()); |
| | | ManagedObjectDefinition<?, ?> mod = getEntryDefinition(context, d, dn); |
| | | |
| | | PropertyDefinition<?> pd2; |
| | | try { |
| | | pd2 = mod.getPropertyDefinition(propertyName); |
| | | } catch (IllegalArgumentException e) { |
| | | throw new PropertyNotFoundException(propertyName); |
| | | } |
| | | |
| | | String attrID = context.getLDAPProfile().getAttributeName(mod, pd2); |
| | | Attributes attributes = context.getLDAPConnection().readEntry(dn, |
| | | Collections.singleton(attrID)); |
| | | Attribute attr = attributes.get(attrID); |
| | | if (attr == null || attr.size() == 0) { |
| | | // Recursively retrieve this property's default values. |
| | | Collection<?> tmp = getDefaultValues(context, target, pd2); |
| | | Collection<T> values = new ArrayList<T>(tmp.size()); |
| | | for (Object o : tmp) { |
| | | T value; |
| | | try { |
| | | value = pd.castValue(o); |
| | | } catch (ClassCastException e) { |
| | | throw new IllegalPropertyValueException(pd, o); |
| | | } |
| | | pd.validateValue(value); |
| | | values.add(value); |
| | | } |
| | | return values; |
| | | } else { |
| | | Collection<T> values = new LinkedList<T>(); |
| | | NamingEnumeration<?> ne = attr.getAll(); |
| | | while (ne.hasMore()) { |
| | | Object value = ne.next(); |
| | | if (value != null) { |
| | | values.add(pd.decodeValue(value.toString())); |
| | | } |
| | | } |
| | | return values; |
| | | } |
| | | } catch (DefinitionDecodingException e) { |
| | | throw new DefaultBehaviorException(pd, e); |
| | | } catch (PropertyNotFoundException e) { |
| | | throw new DefaultBehaviorException(pd, e); |
| | | } catch (IllegalPropertyValueException e) { |
| | | throw new DefaultBehaviorException(pd, e); |
| | | } catch (IllegalPropertyValueStringException e) { |
| | | throw new DefaultBehaviorException(pd, e); |
| | | } catch (NameNotFoundException e) { |
| | | throw new DefaultBehaviorException(pd, |
| | | new ManagedObjectNotFoundException()); |
| | | } catch (NoPermissionException e) { |
| | | throw new DefaultBehaviorException(pd, new AuthorizationException(e)); |
| | | } catch (NamingException e) { |
| | | throw new DefaultBehaviorException(pd, new CommunicationException(e)); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | |
| | | |
| | |
| | | */ |
| | | static ManagedObject<RootCfgClient> getRootManagedObject( |
| | | LDAPManagementContext context) { |
| | | List<PropertyException> exceptions = new LinkedList<PropertyException>(); |
| | | InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider( |
| | | context, ManagedObjectPath.emptyPath()); |
| | | PropertySet properties = PropertySet.create(RootCfgDefn.getInstance(), |
| | | PropertyProvider.DEFAULT_PROVIDER, i, exceptions); |
| | | |
| | | // Should never get any exceptions. |
| | | if (!exceptions.isEmpty()) { |
| | | throw new RuntimeException( |
| | | "Got exceptions when creating root managed object"); |
| | | } |
| | | |
| | | return new LDAPManagedObject<RootCfgClient>(context, RootCfgDefn |
| | | .getInstance(), ManagedObjectPath.emptyPath(), properties); |
| | | } |
| | | |
| | | |
| | | |
| | | // Create a new child LDAP managed object. |
| | | private static <M extends ConfigurationClient> |
| | | ManagedObject<M> createLDAPManagedObject( |
| | | LDAPManagementContext context, ManagedObjectDefinition<M, ?> d, |
| | | ManagedObjectPath p, PropertySet properties) { |
| | | return new LDAPManagedObject<M>(context, d, p, properties); |
| | | .getInstance(), ManagedObjectPath.emptyPath(), new PropertySet(), true); |
| | | } |
| | | |
| | | |
| | |
| | | return d.resolveManagedObjectDefinition(resolver); |
| | | } |
| | | |
| | | |
| | | |
| | | // Read the entry identified by the path and which is a sub-type of |
| | | // the specified definition. |
| | | private static <M extends ConfigurationClient> |
| | | ManagedObject<? extends M> readEntry( |
| | | final LDAPManagementContext context, ManagedObjectPath p, |
| | | AbstractManagedObjectDefinition<M, ?> d) |
| | | throws DefinitionDecodingException, ManagedObjectDecodingException, |
| | | ManagedObjectNotFoundException, AuthorizationException, |
| | | CommunicationException { |
| | | LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile()); |
| | | |
| | | final ManagedObjectDefinition<? extends M, ?> mod; |
| | | final Attributes attributes; |
| | | try { |
| | | mod = getEntryDefinition(context, d, dn); |
| | | ArrayList<String> attrIds = new ArrayList<String>(); |
| | | for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) { |
| | | String attrId = context.getLDAPProfile().getAttributeName(mod, pd); |
| | | attrIds.add(attrId); |
| | | } |
| | | attributes = context.getLDAPConnection().readEntry(dn, attrIds); |
| | | } catch (NameNotFoundException e) { |
| | | throw new ManagedObjectNotFoundException(); |
| | | } catch (NoPermissionException e) { |
| | | throw new AuthorizationException(e); |
| | | } catch (NamingException e) { |
| | | throw new CommunicationException(e); |
| | | } |
| | | |
| | | // Create a provider which uses LDAP string representations. |
| | | |
| | | // TODO: the exception handling is a bit of a hack here. |
| | | final List<NamingException> nelist = new LinkedList<NamingException>(); |
| | | StringPropertyProvider provider = new StringPropertyProvider() { |
| | | |
| | | public Collection<String> getPropertyValues(PropertyDefinition<?> d) |
| | | throws IllegalArgumentException { |
| | | String attrID = context.getLDAPProfile().getAttributeName(mod, d); |
| | | Attribute attribute = attributes.get(attrID); |
| | | List<String> values = new LinkedList<String>(); |
| | | |
| | | if (attribute != null && attribute.size() != 0) { |
| | | try { |
| | | NamingEnumeration<?> ldapValues = attribute.getAll(); |
| | | while (ldapValues.hasMore()) { |
| | | Object obj = ldapValues.next(); |
| | | if (obj != null) { |
| | | values.add(obj.toString()); |
| | | } |
| | | } |
| | | } catch (NamingException e) { |
| | | nelist.add(e); |
| | | } |
| | | } |
| | | |
| | | return values; |
| | | } |
| | | |
| | | }; |
| | | |
| | | // There can only be at most one exception. |
| | | if (!nelist.isEmpty()) { |
| | | try { |
| | | throw nelist.get(0); |
| | | } catch (NameNotFoundException e) { |
| | | throw new ManagedObjectNotFoundException(); |
| | | } catch (NoPermissionException e) { |
| | | throw new AuthorizationException(e); |
| | | } catch (NamingException e) { |
| | | throw new CommunicationException(e); |
| | | } |
| | | } |
| | | |
| | | // Now decode the properties using the provider. |
| | | List<PropertyException> exceptions = new LinkedList<PropertyException>(); |
| | | InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider( |
| | | context, p); |
| | | PropertySet properties = PropertySet.create(mod, provider, i, exceptions); |
| | | ManagedObject<? extends M> mo = createLDAPManagedObject(context, mod, p, |
| | | properties); |
| | | |
| | | // If there were no decoding problems then return the object, |
| | | // otherwise throw an operations exception. |
| | | if (exceptions.isEmpty()) { |
| | | return mo; |
| | | } else { |
| | | throw new ManagedObjectDecodingException(mo, exceptions); |
| | | } |
| | | } |
| | | // The LDAP management context used for the ldap connection. |
| | | private final LDAPManagementContext context; |
| | | |
| | | // The managed object definition associated with this managed |
| | | // object. |
| | | private final ManagedObjectDefinition<C, ?> definition; |
| | | |
| | | // The LDAP management context used for the ldap connection. |
| | | private final LDAPManagementContext context; |
| | | // Indicates whether or not this managed object exists on the server |
| | | // (false means the managed object is new and has not been |
| | | // committed). |
| | | private boolean existsOnServer; |
| | | |
| | | // The path associated with this managed object. |
| | | private final ManagedObjectPath<?, ?> path; |
| | |
| | | // Create an new LDAP managed object with the provided JNDI context. |
| | | private LDAPManagedObject(LDAPManagementContext context, |
| | | ManagedObjectDefinition<C, ?> d, ManagedObjectPath path, |
| | | PropertySet properties) { |
| | | PropertySet properties, boolean existsOnServer) { |
| | | this.definition = d; |
| | | this.context = context; |
| | | this.path = path; |
| | | this.properties = properties; |
| | | this.existsOnServer = existsOnServer; |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void commit() throws ConcurrentModificationException, |
| | | OperationRejectedException, AuthorizationException, |
| | | CommunicationException { |
| | | // Build the list of modified attributes. |
| | | ManagedObjectDefinition<C, ?> d = getManagedObjectDefinition(); |
| | | Attributes mods = new BasicAttributes(); |
| | | for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { |
| | | public void commit() throws MissingMandatoryPropertiesException, |
| | | ConcurrentModificationException, OperationRejectedException, |
| | | AuthorizationException, CommunicationException, |
| | | ManagedObjectAlreadyExistsException { |
| | | // First make sure all mandatory properties are defined. |
| | | List<PropertyIsMandatoryException> exceptions = |
| | | new LinkedList<PropertyIsMandatoryException>(); |
| | | |
| | | for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) { |
| | | Property<?> p = properties.getProperty(pd); |
| | | if (p.isModified()) { |
| | | String attrID = context.getLDAPProfile().getAttributeName(d, pd); |
| | | Attribute attribute = new BasicAttribute(attrID); |
| | | encodeProperty(attribute, pd, properties); |
| | | mods.put(attribute); |
| | | if (pd.hasOption(PropertyOption.MANDATORY) && p.isEmpty()) { |
| | | exceptions.add(new PropertyIsMandatoryException(pd)); |
| | | } |
| | | } |
| | | |
| | | // Perform the LDAP modification if something has changed. |
| | | if (mods.size() > 0) { |
| | | try { |
| | | LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile()); |
| | | context.getLDAPConnection().modifyEntry(dn, mods); |
| | | } catch (NoPermissionException e) { |
| | | throw new AuthorizationException(e); |
| | | } catch (OperationNotSupportedException e) { |
| | | // Unwilling to perform. |
| | | throw new OperationRejectedException(e); |
| | | } catch (NamingException e) { |
| | | // Just treat it as a communication problem. |
| | | throw new CommunicationException(e); |
| | | } |
| | | if (!exceptions.isEmpty()) { |
| | | throw new MissingMandatoryPropertiesException(exceptions); |
| | | } |
| | | |
| | | // Commit the managed object. |
| | | if (existsOnServer) { |
| | | commitExistingManagedObject(); |
| | | } else { |
| | | commitNewManagedObject(); |
| | | } |
| | | } |
| | | |
| | |
| | | public <M extends ConfigurationClient, N extends M> |
| | | ManagedObject<N> createChild( |
| | | InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d, |
| | | String name, PropertyProvider p) throws IllegalArgumentException, |
| | | ManagedObjectDecodingException, ManagedObjectAlreadyExistsException, |
| | | ConcurrentModificationException, OperationRejectedException, |
| | | AuthorizationException, CommunicationException { |
| | | String name, Collection<DefaultBehaviorException> exceptions) |
| | | throws IllegalArgumentException { |
| | | validateRelationDefinition(r); |
| | | |
| | | ManagedObjectPath childPath = path.child(r, name); |
| | | |
| | | // First make sure all the properties are valid. |
| | | List<PropertyException> exceptions = new LinkedList<PropertyException>(); |
| | | InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider( |
| | | context, childPath); |
| | | PropertySet properties = PropertySet.create(d, p, i, exceptions); |
| | | if (!exceptions.isEmpty()) { |
| | | ManagedObject<N> mo = new LDAPManagedObject<N>(context, d, childPath, |
| | | properties); |
| | | throw new ManagedObjectDecodingException(mo, exceptions); |
| | | } |
| | | |
| | | ensureThisManagedObjectExists(); |
| | | |
| | | // TODO: this implementation does not handle relations which |
| | | // comprise of more than one RDN arc (this will probably never |
| | | // be required anyway). |
| | | LdapName dn = LDAPNameBuilder.create(path, r, context.getLDAPProfile()); |
| | | if (!entryExists(dn)) { |
| | | // Need to create the child managed object's parent entry i.e. |
| | | // the entry representing the relation itself. |
| | | Attributes attributes = new BasicAttributes(); |
| | | |
| | | // Create the branch's object class attribute. |
| | | Attribute oc = new BasicAttribute("objectClass"); |
| | | for (String objectClass : context.getLDAPProfile() |
| | | .getInstantiableRelationObjectClasses(r)) { |
| | | oc.add(objectClass); |
| | | } |
| | | attributes.put(oc); |
| | | |
| | | // Create the branch's naming attribute. |
| | | Rdn rdn = dn.getRdn(dn.size() - 1); |
| | | attributes.put(rdn.getType(), rdn.getValue().toString()); |
| | | |
| | | // Create the entry. |
| | | try { |
| | | context.getLDAPConnection().createEntry(dn, attributes); |
| | | } catch (OperationNotSupportedException e) { |
| | | // Unwilling to perform. |
| | | throw new OperationRejectedException(e); |
| | | } catch (NamingException e) { |
| | | adaptNamingException(e); |
| | | } |
| | | } |
| | | |
| | | return createManagedObject(childPath, d, properties); |
| | | return createNewManagedObject(d, childPath, exceptions); |
| | | } |
| | | |
| | | |
| | |
| | | public <M extends ConfigurationClient, N extends M> |
| | | ManagedObject<N> createChild( |
| | | OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d, |
| | | PropertyProvider p) throws IllegalArgumentException, |
| | | ManagedObjectDecodingException, ManagedObjectAlreadyExistsException, |
| | | ConcurrentModificationException, OperationRejectedException, |
| | | AuthorizationException, CommunicationException { |
| | | Collection<DefaultBehaviorException> exceptions) |
| | | throws IllegalArgumentException { |
| | | validateRelationDefinition(r); |
| | | |
| | | ManagedObjectPath childPath = path.child(r); |
| | | |
| | | // First make sure all the properties are valid. |
| | | List<PropertyException> exceptions = new LinkedList<PropertyException>(); |
| | | InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider( |
| | | context, childPath); |
| | | PropertySet properties = PropertySet.create(d, p, i, exceptions); |
| | | if (!exceptions.isEmpty()) { |
| | | ManagedObject<N> mo = new LDAPManagedObject<N>(context, d, childPath, |
| | | properties); |
| | | throw new ManagedObjectDecodingException(mo, exceptions); |
| | | } |
| | | |
| | | ensureThisManagedObjectExists(); |
| | | |
| | | return createManagedObject(childPath, d, properties); |
| | | return createNewManagedObject(d, childPath, exceptions); |
| | | } |
| | | |
| | | |
| | |
| | | CommunicationException { |
| | | validateRelationDefinition(d); |
| | | ensureThisManagedObjectExists(); |
| | | return readEntry(context, path.child(d, name), d.getChildDefinition()); |
| | | return readManagedObject(d.getChildDefinition(), path.child(d, name)); |
| | | } |
| | | |
| | | |
| | |
| | | AuthorizationException, CommunicationException { |
| | | validateRelationDefinition(d); |
| | | ensureThisManagedObjectExists(); |
| | | return readEntry(context, path.child(d), d.getChildDefinition()); |
| | | return readManagedObject(d.getChildDefinition(), path.child(d)); |
| | | } |
| | | |
| | | |
| | |
| | | AuthorizationException, CommunicationException { |
| | | validateRelationDefinition(d); |
| | | ensureThisManagedObjectExists(); |
| | | return readEntry(context, path.child(d), d.getChildDefinition()); |
| | | return readManagedObject(d.getChildDefinition(), path.child(d)); |
| | | } |
| | | |
| | | |
| | |
| | | public <T> void setPropertyValue(PropertyDefinition<T> d, T value) |
| | | throws IllegalPropertyValueException, PropertyIsReadOnlyException, |
| | | PropertyIsMandatoryException, IllegalArgumentException { |
| | | if (d.hasOption(PropertyOption.MONITORING)) { |
| | | throw new PropertyIsReadOnlyException(d); |
| | | } |
| | | |
| | | if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) { |
| | | throw new PropertyIsReadOnlyException(d); |
| | | } |
| | | |
| | | properties.setPropertyValue(d, value); |
| | | } |
| | | |
| | |
| | | Collection<T> values) throws IllegalPropertyValueException, |
| | | PropertyIsSingleValuedException, PropertyIsReadOnlyException, |
| | | PropertyIsMandatoryException, IllegalArgumentException { |
| | | if (d.hasOption(PropertyOption.MONITORING)) { |
| | | throw new PropertyIsReadOnlyException(d); |
| | | } |
| | | |
| | | if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) { |
| | | throw new PropertyIsReadOnlyException(d); |
| | | } |
| | | |
| | | properties.setPropertyValues(d, values); |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | // Creates a new managed object. The parent LDAP entry is assumed to |
| | | // already exist. |
| | | private <N extends ConfigurationClient> ManagedObject<N> createManagedObject( |
| | | ManagedObjectPath path, ManagedObjectDefinition<N, ?> d, |
| | | PropertySet properties) throws ManagedObjectAlreadyExistsException, |
| | | OperationRejectedException, AuthorizationException, |
| | | CommunicationException { |
| | | // Commit modifications made to this managed object. |
| | | private void commitExistingManagedObject() |
| | | throws ConcurrentModificationException, OperationRejectedException, |
| | | AuthorizationException, CommunicationException { |
| | | // Build the list of modified attributes. |
| | | Attributes mods = new BasicAttributes(); |
| | | for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) { |
| | | Property<?> p = properties.getProperty(pd); |
| | | if (p.isModified()) { |
| | | String attrID = context.getLDAPProfile().getAttributeName(definition, |
| | | pd); |
| | | Attribute attribute = new BasicAttribute(attrID); |
| | | encodeProperty(attribute, pd, properties); |
| | | mods.put(attribute); |
| | | } |
| | | } |
| | | |
| | | // Perform the LDAP modification if something has changed. |
| | | if (mods.size() > 0) { |
| | | try { |
| | | LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile()); |
| | | context.getLDAPConnection().modifyEntry(dn, mods); |
| | | } catch (NoPermissionException e) { |
| | | throw new AuthorizationException(e); |
| | | } catch (OperationNotSupportedException e) { |
| | | // Unwilling to perform. |
| | | throw new OperationRejectedException(e); |
| | | } catch (NamingException e) { |
| | | // Just treat it as a communication problem. |
| | | throw new CommunicationException(e); |
| | | } |
| | | } |
| | | |
| | | // The changes were committed successfully so update this managed |
| | | // object's state. |
| | | properties.commit(); |
| | | } |
| | | |
| | | |
| | | |
| | | // Commit this new managed object. |
| | | private void commitNewManagedObject() throws AuthorizationException, |
| | | CommunicationException, OperationRejectedException, |
| | | ConcurrentModificationException, ManagedObjectAlreadyExistsException { |
| | | // First make sure that the parent managed object still exists. |
| | | ManagedObjectPath<?, ?> parent = path.parent(); |
| | | if (!parent.isEmpty()) { |
| | | LdapName dn = LDAPNameBuilder.create(parent, context.getLDAPProfile()); |
| | | if (!entryExists(dn)) { |
| | | throw new ConcurrentModificationException(); |
| | | } |
| | | } |
| | | |
| | | // We may need to create the parent "relation" entry if this is a |
| | | // child of an instantiable relation. |
| | | RelationDefinition<?, ?> r = path.getRelationDefinition(); |
| | | if (r instanceof InstantiableRelationDefinition) { |
| | | InstantiableRelationDefinition<?, ?> ir = |
| | | (InstantiableRelationDefinition<?, ?>) r; |
| | | |
| | | // TODO: this implementation does not handle relations which |
| | | // comprise of more than one RDN arc (this will probably never |
| | | // be required anyway). |
| | | LdapName dn = LDAPNameBuilder |
| | | .create(parent, ir, context.getLDAPProfile()); |
| | | if (!entryExists(dn)) { |
| | | // We need to create the entry. |
| | | Attributes attributes = new BasicAttributes(); |
| | | |
| | | // Create the branch's object class attribute. |
| | | Attribute oc = new BasicAttribute("objectClass"); |
| | | for (String objectClass : context.getLDAPProfile() |
| | | .getInstantiableRelationObjectClasses(ir)) { |
| | | oc.add(objectClass); |
| | | } |
| | | attributes.put(oc); |
| | | |
| | | // Create the branch's naming attribute. |
| | | Rdn rdn = dn.getRdn(dn.size() - 1); |
| | | attributes.put(rdn.getType(), rdn.getValue().toString()); |
| | | |
| | | // Create the entry. |
| | | try { |
| | | context.getLDAPConnection().createEntry(dn, attributes); |
| | | } catch (OperationNotSupportedException e) { |
| | | // Unwilling to perform. |
| | | throw new OperationRejectedException(e); |
| | | } catch (NamingException e) { |
| | | adaptNamingException(e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Now add the entry representing this new managed object. |
| | | LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile()); |
| | | Attributes attributes = new BasicAttributes(true); |
| | | |
| | | // Create the child's object class attribute. |
| | | // Create the object class attribute. |
| | | Attribute oc = new BasicAttribute("objectclass"); |
| | | for (String objectClass : context.getLDAPProfile().getObjectClasses(d)) { |
| | | for (String objectClass : context.getLDAPProfile().getObjectClasses( |
| | | definition)) { |
| | | oc.add(objectClass); |
| | | } |
| | | attributes.put(oc); |
| | | |
| | | // Create the child's naming attribute. |
| | | // Create the naming attribute. |
| | | Rdn rdn = dn.getRdn(dn.size() - 1); |
| | | attributes.put(rdn.getType(), rdn.getValue().toString()); |
| | | |
| | | // Create the remaining attributes. |
| | | for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { |
| | | String attrID = context.getLDAPProfile().getAttributeName(d, pd); |
| | | for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) { |
| | | String attrID = context.getLDAPProfile().getAttributeName(definition, pd); |
| | | Attribute attribute = new BasicAttribute(attrID); |
| | | encodeProperty(attribute, pd, properties); |
| | | if (attribute.size() != 0) { |
| | |
| | | adaptNamingException(e); |
| | | } |
| | | |
| | | return new LDAPManagedObject<N>(context, d, path, properties); |
| | | // The entry was created successfully so update this managed |
| | | // object's state. |
| | | properties.commit(); |
| | | existsOnServer = true; |
| | | } |
| | | |
| | | |
| | | |
| | | // Create a managed object which already exists on the server. |
| | | private <M extends ConfigurationClient> |
| | | ManagedObject<M> createExistingManagedObject( |
| | | ManagedObjectDefinition<M, ?> d, ManagedObjectPath p, |
| | | PropertySet properties) { |
| | | return new LDAPManagedObject<M>(context, d, p, properties, true); |
| | | } |
| | | |
| | | |
| | | |
| | | // Creates a new managed object with no active values, just default |
| | | // values. |
| | | private <M extends ConfigurationClient> |
| | | ManagedObject<M> createNewManagedObject( |
| | | ManagedObjectDefinition<M, ?> d, ManagedObjectPath p, |
| | | Collection<DefaultBehaviorException> exceptions) { |
| | | PropertySet childProperties = new PropertySet(); |
| | | for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) { |
| | | try { |
| | | createProperty(childProperties, p, pd); |
| | | } catch (DefaultBehaviorException e) { |
| | | // Add the exception if requested. |
| | | if (exceptions != null) { |
| | | exceptions.add(e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return new LDAPManagedObject<M>(context, d, p, childProperties, false); |
| | | } |
| | | |
| | | |
| | | |
| | | // Create an empty property. |
| | | private <T> void createProperty(PropertySet properties, ManagedObjectPath p, |
| | | PropertyDefinition<T> pd) throws DefaultBehaviorException { |
| | | try { |
| | | Collection<T> defaultValues = DefaultValueFinder.getDefaultValues( |
| | | context, p, pd); |
| | | properties.addProperty(pd, defaultValues, Collections.<T> emptySet()); |
| | | } catch (DefaultBehaviorException e) { |
| | | // Make sure that we have still created the property. |
| | | properties.addProperty(pd, Collections.<T> emptySet(), Collections |
| | | .<T> emptySet()); |
| | | throw e; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | // Create a property using the provided string values. |
| | | private <T> void decodeProperty(PropertySet newProperties, |
| | | ManagedObjectPath p, PropertyDefinition<T> pd, List<String> values) |
| | | throws PropertyException { |
| | | PropertyException exception = null; |
| | | |
| | | // Get the property's active values. |
| | | Collection<T> activeValues = new ArrayList<T>(values.size()); |
| | | for (String value : values) { |
| | | try { |
| | | activeValues.add(pd.decodeValue(value)); |
| | | } catch (IllegalPropertyValueStringException e) { |
| | | exception = e; |
| | | } |
| | | } |
| | | |
| | | if (activeValues.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) { |
| | | // This exception takes precedence over previous exceptions. |
| | | exception = new PropertyIsSingleValuedException(pd); |
| | | T value = activeValues.iterator().next(); |
| | | activeValues.clear(); |
| | | activeValues.add(value); |
| | | } |
| | | |
| | | if (activeValues.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) { |
| | | // The active values maybe empty because of a previous exception. |
| | | if (exception == null) { |
| | | exception = new PropertyIsMandatoryException(pd); |
| | | } |
| | | } |
| | | |
| | | // Get the property's default values. |
| | | Collection<T> defaultValues; |
| | | try { |
| | | defaultValues = DefaultValueFinder.getDefaultValues(context, p, pd); |
| | | } catch (DefaultBehaviorException e) { |
| | | defaultValues = Collections.emptySet(); |
| | | exception = e; |
| | | } |
| | | |
| | | newProperties.addProperty(pd, defaultValues, activeValues); |
| | | if (exception != null) { |
| | | throw exception; |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | private void ensureThisManagedObjectExists() |
| | | throws ConcurrentModificationException, CommunicationException, |
| | | AuthorizationException { |
| | | LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile()); |
| | | if (!entryExists(dn)) { |
| | | throw new ConcurrentModificationException(); |
| | | if (!path.isEmpty()) { |
| | | LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile()); |
| | | if (!entryExists(dn)) { |
| | | throw new ConcurrentModificationException(); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | // Read the entry identified by the path and which is a sub-type of |
| | | // the specified definition. |
| | | private <M extends ConfigurationClient> |
| | | ManagedObject<? extends M> readManagedObject( |
| | | AbstractManagedObjectDefinition<M, ?> d, ManagedObjectPath p) |
| | | throws DefinitionDecodingException, ManagedObjectDecodingException, |
| | | ManagedObjectNotFoundException, AuthorizationException, |
| | | CommunicationException { |
| | | try { |
| | | // Read the entry associated with the managed object. |
| | | LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile()); |
| | | ManagedObjectDefinition<? extends M, ?> mod = getEntryDefinition(context, |
| | | d, dn); |
| | | |
| | | ArrayList<String> attrIds = new ArrayList<String>(); |
| | | for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) { |
| | | String attrId = context.getLDAPProfile().getAttributeName(mod, pd); |
| | | attrIds.add(attrId); |
| | | } |
| | | |
| | | Attributes attributes = context.getLDAPConnection() |
| | | .readEntry(dn, attrIds); |
| | | |
| | | // Build the managed object's properties. |
| | | List<PropertyException> exceptions = new LinkedList<PropertyException>(); |
| | | PropertySet newProperties = new PropertySet(); |
| | | for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) { |
| | | String attrID = context.getLDAPProfile().getAttributeName(mod, pd); |
| | | Attribute attribute = attributes.get(attrID); |
| | | List<String> values = new LinkedList<String>(); |
| | | |
| | | if (attribute != null && attribute.size() != 0) { |
| | | NamingEnumeration<?> ldapValues = attribute.getAll(); |
| | | while (ldapValues.hasMore()) { |
| | | Object obj = ldapValues.next(); |
| | | if (obj != null) { |
| | | values.add(obj.toString()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | try { |
| | | decodeProperty(newProperties, p, pd, values); |
| | | } catch (PropertyException e) { |
| | | exceptions.add(e); |
| | | } |
| | | } |
| | | |
| | | // If there were no decoding problems then return the object, |
| | | // otherwise throw an operations exception. |
| | | ManagedObject<? extends M> mo = createExistingManagedObject(mod, p, |
| | | newProperties); |
| | | |
| | | if (exceptions.isEmpty()) { |
| | | return mo; |
| | | } else { |
| | | throw new ManagedObjectDecodingException(mo, exceptions); |
| | | } |
| | | } catch (NameNotFoundException e) { |
| | | throw new ManagedObjectNotFoundException(); |
| | | } catch (NoPermissionException e) { |
| | | throw new AuthorizationException(e); |
| | | } catch (NamingException e) { |
| | | throw new CommunicationException(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | // Remove the named managed object. |
| | | private void removeManagedObject(ManagedObjectPath p) |
| | | throws CommunicationException, AuthorizationException, |