/*
* 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 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 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 2008-2009 Sun Microsystems, Inc.
* Portions Copyright 2014-2015 ForgeRock AS
*/
package org.forgerock.opendj.config.client.spi;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.config.AbstractManagedObjectDefinition;
import org.forgerock.opendj.config.Configuration;
import org.forgerock.opendj.config.ConfigurationClient;
import org.forgerock.opendj.config.Constraint;
import org.forgerock.opendj.config.PropertyException;
import org.forgerock.opendj.config.DefaultManagedObject;
import org.forgerock.opendj.config.DefinitionDecodingException;
import org.forgerock.opendj.config.InstantiableRelationDefinition;
import org.forgerock.opendj.config.ManagedObjectAlreadyExistsException;
import org.forgerock.opendj.config.ManagedObjectDefinition;
import org.forgerock.opendj.config.ManagedObjectNotFoundException;
import org.forgerock.opendj.config.ManagedObjectPath;
import org.forgerock.opendj.config.OptionalRelationDefinition;
import org.forgerock.opendj.config.PropertyDefinition;
import org.forgerock.opendj.config.PropertyOption;
import org.forgerock.opendj.config.RelationDefinition;
import org.forgerock.opendj.config.RelationDefinitionVisitor;
import org.forgerock.opendj.config.SetRelationDefinition;
import org.forgerock.opendj.config.SingletonRelationDefinition;
import org.forgerock.opendj.config.DefinitionDecodingException.Reason;
import org.forgerock.opendj.config.client.ClientConstraintHandler;
import org.forgerock.opendj.config.client.ConcurrentModificationException;
import org.forgerock.opendj.config.client.IllegalManagedObjectNameException;
import org.forgerock.opendj.config.client.ManagedObject;
import org.forgerock.opendj.config.client.ManagedObjectDecodingException;
import org.forgerock.opendj.config.client.ManagementContext;
import org.forgerock.opendj.config.client.MissingMandatoryPropertiesException;
import org.forgerock.opendj.config.client.OperationRejectedException;
import org.forgerock.opendj.config.client.OperationRejectedException.OperationType;
import org.forgerock.opendj.ldap.LdapException;
/**
* An abstract managed object implementation.
*
* @param <T>
* The type of client configuration represented by the client managed
* object.
*/
public abstract class AbstractManagedObject<T extends ConfigurationClient> implements ManagedObject<T> {
/**
* Creates any default managed objects associated with a relation
* definition.
*/
private final class DefaultManagedObjectFactory implements RelationDefinitionVisitor<Void, Void> {
/** Possible exceptions. */
private ManagedObjectAlreadyExistsException moaee;
private MissingMandatoryPropertiesException mmpe;
private ConcurrentModificationException cme;
private OperationRejectedException ore;
private LdapException ere;
/** {@inheritDoc} */
@Override
public <C extends ConfigurationClient, S extends Configuration> Void visitInstantiable(
InstantiableRelationDefinition<C, S> rd, Void p) {
for (String name : rd.getDefaultManagedObjectNames()) {
DefaultManagedObject<? extends C, ? extends S> dmo = rd.getDefaultManagedObject(name);
ManagedObjectDefinition<? extends C, ? extends S> d = dmo.getManagedObjectDefinition();
ManagedObject<? extends C> child;
try {
child = createChild(rd, d, name, null);
} catch (IllegalManagedObjectNameException e) {
// This should not happen.
throw new RuntimeException(e);
}
createDefaultManagedObject(d, child, dmo);
}
return null;
}
/** {@inheritDoc} */
@Override
public <C extends ConfigurationClient, S extends Configuration> Void visitOptional(
OptionalRelationDefinition<C, S> rd, Void p) {
if (rd.getDefaultManagedObject() != null) {
DefaultManagedObject<? extends C, ? extends S> dmo = rd.getDefaultManagedObject();
ManagedObjectDefinition<? extends C, ? extends S> d = dmo.getManagedObjectDefinition();
ManagedObject<? extends C> child = createChild(rd, d, null);
createDefaultManagedObject(d, child, dmo);
}
return null;
}
/** {@inheritDoc} */
@Override
public <C extends ConfigurationClient, S extends Configuration> Void visitSingleton(
SingletonRelationDefinition<C, S> rd, Void p) {
// Do nothing - not possible to create singletons
// dynamically.
return null;
}
/** {@inheritDoc} */
@Override
public <C extends ConfigurationClient, S extends Configuration> Void visitSet(SetRelationDefinition<C, S> rd,
Void p) {
for (String name : rd.getDefaultManagedObjectNames()) {
DefaultManagedObject<? extends C, ? extends S> dmo = rd.getDefaultManagedObject(name);
ManagedObjectDefinition<? extends C, ? extends S> d = dmo.getManagedObjectDefinition();
ManagedObject<? extends C> child = createChild(rd, d, null);
createDefaultManagedObject(d, child, dmo);
}
return null;
}
/** Create the child managed object. */
private void createDefaultManagedObject(ManagedObjectDefinition<?, ?> d, ManagedObject<?> child,
DefaultManagedObject<?, ?> dmo) {
for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
setPropertyValues(child, pd, dmo);
}
try {
child.commit();
} catch (ManagedObjectAlreadyExistsException e) {
moaee = e;
} catch (MissingMandatoryPropertiesException e) {
mmpe = e;
} catch (ConcurrentModificationException e) {
cme = e;
} catch (OperationRejectedException e) {
ore = e;
} catch (LdapException e) {
ere = e;
}
}
/**
* Creates the default managed objects associated with the provided
* relation definition.
*
* @param rd
* The relation definition.
*/
private void createDefaultManagedObjects(RelationDefinition<?, ?> rd) throws LdapException,
ConcurrentModificationException, MissingMandatoryPropertiesException,
ManagedObjectAlreadyExistsException, OperationRejectedException {
rd.accept(this, null);
if (ere != null) {
throw ere;
} else if (cme != null) {
throw cme;
} else if (mmpe != null) {
throw mmpe;
} else if (moaee != null) {
throw moaee;
} else if (ore != null) {
throw ore;
}
}
/** Set property values. */
private <P> void setPropertyValues(ManagedObject<?> mo, PropertyDefinition<P> pd,
DefaultManagedObject<?, ?> dmo) {
mo.setPropertyValues(pd, dmo.getPropertyValues(pd));
}
}
/**
* The managed object definition associated with this managed
* object.
*/
private final ManagedObjectDefinition<T, ? extends Configuration> definition;
/**
* 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;
/** Optional naming property definition. */
private final PropertyDefinition<?> namingPropertyDefinition;
/** The path associated with this managed object. */
private ManagedObjectPath<T, ? extends Configuration> path;
/** The managed object's properties. */
private final PropertySet properties;
/**
* Creates a new abstract managed object.
*
* @param d
* The managed object's definition.
* @param path
* The managed object's path.
* @param properties
* The managed object's properties.
* @param existsOnServer
* Indicates whether or not the managed object exists on the
* server (false means the managed object is new and has not been
* committed).
* @param namingPropertyDefinition
* Optional naming property definition.
*/
protected AbstractManagedObject(ManagedObjectDefinition<T, ? extends Configuration> d,
ManagedObjectPath<T, ? extends Configuration> path, PropertySet properties, boolean existsOnServer,
PropertyDefinition<?> namingPropertyDefinition) {
this.definition = d;
this.path = path;
this.properties = properties;
this.existsOnServer = existsOnServer;
this.namingPropertyDefinition = namingPropertyDefinition;
}
/** {@inheritDoc} */
@Override
public final void commit() throws ManagedObjectAlreadyExistsException, MissingMandatoryPropertiesException,
ConcurrentModificationException, OperationRejectedException, LdapException {
// First make sure all mandatory properties are defined.
List<PropertyException> exceptions = new LinkedList<>();
for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
Property<?> p = getProperty(pd);
if (pd.hasOption(PropertyOption.MANDATORY) && p.getEffectiveValues().isEmpty()) {
exceptions.add(PropertyException.propertyIsMandatoryException(pd));
}
}
if (!exceptions.isEmpty()) {
throw new MissingMandatoryPropertiesException(definition.getUserFriendlyName(), exceptions,
!existsOnServer);
}
// Now enforce any constraints.
List<LocalizableMessage> messages = new LinkedList<>();
boolean isAcceptable = true;
ManagementContext context = getDriver().getManagementContext();
for (Constraint constraint : definition.getAllConstraints()) {
for (ClientConstraintHandler handler : constraint.getClientConstraintHandlers()) {
if (existsOnServer) {
if (!handler.isModifyAcceptable(context, this, messages)) {
isAcceptable = false;
}
} else {
if (!handler.isAddAcceptable(context, this, messages)) {
isAcceptable = false;
}
}
}
if (!isAcceptable) {
break;
}
}
if (!isAcceptable) {
if (existsOnServer) {
throw new OperationRejectedException(OperationType.MODIFY, definition.getUserFriendlyName(), messages);
} else {
throw new OperationRejectedException(OperationType.CREATE, definition.getUserFriendlyName(), messages);
}
}
// Commit the managed object.
if (existsOnServer) {
modifyExistingManagedObject();
} else {
addNewManagedObject();
}
// Make all pending property values active.
properties.commit();
// If the managed object was created make sure that any default
// subordinate managed objects are also created.
if (!existsOnServer) {
DefaultManagedObjectFactory factory = new DefaultManagedObjectFactory();
for (RelationDefinition<?, ?> rd : definition.getAllRelationDefinitions()) {
factory.createDefaultManagedObjects(rd);
}
existsOnServer = true;
}
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration, C1 extends C> ManagedObject<C1> createChild(
InstantiableRelationDefinition<C, S> r, ManagedObjectDefinition<C1, ? extends S> d, String name,
Collection<PropertyException> exceptions) throws IllegalManagedObjectNameException {
validateRelationDefinition(r);
// Empty names are not allowed.
if (name.trim().length() == 0) {
throw new IllegalManagedObjectNameException(name);
}
// If the relation uses a naming property definition then it must
// be a valid value.
PropertyDefinition<?> pd = r.getNamingPropertyDefinition();
if (pd != null) {
try {
pd.decodeValue(name);
} catch (PropertyException e) {
throw new IllegalManagedObjectNameException(name, pd);
}
}
ManagedObjectPath<C1, ? extends S> childPath = path.child(r, d, name);
return createNewManagedObject(d, childPath, pd, name, exceptions);
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration, C1 extends C> ManagedObject<C1> createChild(
OptionalRelationDefinition<C, S> r, ManagedObjectDefinition<C1, ? extends S> d,
Collection<PropertyException> exceptions) {
validateRelationDefinition(r);
ManagedObjectPath<C1, ? extends S> childPath = path.child(r, d);
return createNewManagedObject(d, childPath, null, null, exceptions);
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration, C1 extends C> ManagedObject<C1> createChild(
SetRelationDefinition<C, S> r, ManagedObjectDefinition<C1, ? extends S> d,
Collection<PropertyException> exceptions) {
validateRelationDefinition(r);
ManagedObjectPath<C1, ? extends S> childPath = path.child(r, d);
return createNewManagedObject(d, childPath, null, null, exceptions);
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getChild(
InstantiableRelationDefinition<C, S> r, String name) throws DefinitionDecodingException,
ManagedObjectDecodingException, ManagedObjectNotFoundException, ConcurrentModificationException,
LdapException {
validateRelationDefinition(r);
ensureThisManagedObjectExists();
Driver ctx = getDriver();
return ctx.getManagedObject(path.child(r, name));
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getChild(
OptionalRelationDefinition<C, S> r) throws DefinitionDecodingException, ManagedObjectDecodingException,
ManagedObjectNotFoundException, ConcurrentModificationException, LdapException {
validateRelationDefinition(r);
ensureThisManagedObjectExists();
Driver ctx = getDriver();
return ctx.getManagedObject(path.child(r));
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getChild(
SingletonRelationDefinition<C, S> r) throws DefinitionDecodingException, ManagedObjectDecodingException,
ManagedObjectNotFoundException, ConcurrentModificationException, LdapException {
validateRelationDefinition(r);
ensureThisManagedObjectExists();
Driver ctx = getDriver();
return ctx.getManagedObject(path.child(r));
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getChild(
SetRelationDefinition<C, S> r, String name) throws DefinitionDecodingException,
ManagedObjectDecodingException, ManagedObjectNotFoundException, ConcurrentModificationException,
LdapException {
validateRelationDefinition(r);
ensureThisManagedObjectExists();
Driver ctx = getDriver();
AbstractManagedObjectDefinition<C, S> d = r.getChildDefinition();
AbstractManagedObjectDefinition<? extends C, ? extends S> cd;
try {
cd = d.getChild(name);
} catch (IllegalArgumentException e) {
// Unrecognized definition name - report this as a decoding
// exception.
throw new DefinitionDecodingException(d, Reason.WRONG_TYPE_INFORMATION);
}
return ctx.getManagedObject(path.child(r, cd));
}
/** {@inheritDoc} */
@Override
public final T getConfiguration() {
return definition.createClientConfiguration(this);
}
/** {@inheritDoc} */
@Override
public final ManagedObjectDefinition<T, ? extends Configuration> getManagedObjectDefinition() {
return definition;
}
/** {@inheritDoc} */
@Override
public final ManagedObjectPath<T, ? extends Configuration> getManagedObjectPath() {
return path;
}
/** {@inheritDoc} */
@Override
public final <P> SortedSet<P> getPropertyDefaultValues(PropertyDefinition<P> pd) {
return new TreeSet<>(getProperty(pd).getDefaultValues());
}
/** {@inheritDoc} */
@Override
public final <P> P getPropertyValue(PropertyDefinition<P> pd) {
Set<P> values = getProperty(pd).getEffectiveValues();
if (!values.isEmpty()) {
return values.iterator().next();
}
return null;
}
/** {@inheritDoc} */
@Override
public final <P> SortedSet<P> getPropertyValues(PropertyDefinition<P> pd) {
return new TreeSet<>(getProperty(pd).getEffectiveValues());
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> boolean hasChild(
OptionalRelationDefinition<C, S> r) throws ConcurrentModificationException, LdapException {
validateRelationDefinition(r);
Driver ctx = getDriver();
try {
return ctx.managedObjectExists(path.child(r));
} catch (ManagedObjectNotFoundException e) {
throw new ConcurrentModificationException();
}
}
/** {@inheritDoc} */
@Override
public final boolean isPropertyPresent(PropertyDefinition<?> pd) {
return !getProperty(pd).isEmpty();
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> String[] listChildren(
InstantiableRelationDefinition<C, S> r) throws ConcurrentModificationException, LdapException {
return listChildren(r, r.getChildDefinition());
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> String[] listChildren(
InstantiableRelationDefinition<C, S> r, AbstractManagedObjectDefinition<? extends C, ? extends S> d)
throws ConcurrentModificationException, LdapException {
validateRelationDefinition(r);
Driver ctx = getDriver();
try {
return ctx.listManagedObjects(path, r, d);
} catch (ManagedObjectNotFoundException e) {
throw new ConcurrentModificationException();
}
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> String[] listChildren(
SetRelationDefinition<C, S> r) throws ConcurrentModificationException, LdapException {
return listChildren(r, r.getChildDefinition());
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> String[] listChildren(
SetRelationDefinition<C, S> r, AbstractManagedObjectDefinition<? extends C, ? extends S> d)
throws ConcurrentModificationException, LdapException {
validateRelationDefinition(r);
Driver ctx = getDriver();
try {
return ctx.listManagedObjects(path, r, d);
} catch (ManagedObjectNotFoundException e) {
throw new ConcurrentModificationException();
}
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> void removeChild(
InstantiableRelationDefinition<C, S> r, String name) throws ManagedObjectNotFoundException,
OperationRejectedException, ConcurrentModificationException, LdapException {
validateRelationDefinition(r);
Driver ctx = getDriver();
boolean found;
try {
found = ctx.deleteManagedObject(path, r, name);
} catch (ManagedObjectNotFoundException e) {
throw new ConcurrentModificationException();
}
if (!found) {
throw new ManagedObjectNotFoundException();
}
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> void removeChild(
OptionalRelationDefinition<C, S> r) throws ManagedObjectNotFoundException, OperationRejectedException,
ConcurrentModificationException, LdapException {
validateRelationDefinition(r);
Driver ctx = getDriver();
boolean found;
try {
found = ctx.deleteManagedObject(path, r);
} catch (ManagedObjectNotFoundException e) {
throw new ConcurrentModificationException();
}
if (!found) {
throw new ManagedObjectNotFoundException();
}
}
/** {@inheritDoc} */
@Override
public final <C extends ConfigurationClient, S extends Configuration> void removeChild(
SetRelationDefinition<C, S> r, String name) throws ManagedObjectNotFoundException,
OperationRejectedException, ConcurrentModificationException, LdapException {
validateRelationDefinition(r);
Driver ctx = getDriver();
boolean found;
try {
found = ctx.deleteManagedObject(path, r, name);
} catch (ManagedObjectNotFoundException e) {
throw new ConcurrentModificationException();
}
if (!found) {
throw new ManagedObjectNotFoundException();
}
}
/** {@inheritDoc} */
@Override
public final <P> void setPropertyValue(PropertyDefinition<P> pd, P value) {
if (value != null) {
setPropertyValues(pd, Collections.singleton(value));
} else {
setPropertyValues(pd, Collections.<P> emptySet());
}
}
/** {@inheritDoc} */
@Override
public final <P> void setPropertyValues(PropertyDefinition<P> pd, Collection<P> values) {
if (pd.hasOption(PropertyOption.MONITORING)) {
throw PropertyException.propertyIsReadOnlyException(pd);
}
if (existsOnServer && pd.hasOption(PropertyOption.READ_ONLY)) {
throw PropertyException.propertyIsReadOnlyException(pd);
}
properties.setPropertyValues(pd, values);
// If this is a naming property then update the name.
if (pd.equals(namingPropertyDefinition)) {
// The property must be single-valued and mandatory.
String newName = pd.encodeValue(values.iterator().next());
path = path.rename(newName);
}
}
/** {@inheritDoc} */
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("{ TYPE=");
builder.append(definition.getName());
builder.append(", PATH=\"");
builder.append(path);
builder.append('\"');
for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
builder.append(", ");
builder.append(pd.getName());
builder.append('=');
builder.append(getPropertyValues(pd));
}
builder.append(" }");
return builder.toString();
}
/**
* Adds this new managed object.
*
* @throws ManagedObjectAlreadyExistsException
* If the managed object cannot be added to the server because
* it already exists.
* @throws ConcurrentModificationException
* If the managed object's parent has been removed by another
* client.
* @throws OperationRejectedException
* If the managed object cannot be added due to some client-side
* or server-side constraint which cannot be satisfied.
* @throws LdapException
* If any other error occurs.
*/
protected abstract void addNewManagedObject() throws LdapException, OperationRejectedException,
ConcurrentModificationException, ManagedObjectAlreadyExistsException;
/**
* Gets the management context driver associated with this managed object.
*
* @return Returns the management context driver associated with this
* managed object.
*/
protected abstract Driver getDriver();
/**
* Gets the naming property definition associated with this managed object.
*
* @return Returns the naming property definition associated with this
* managed object, or <code>null</code> if this managed object does
* not have a naming property.
*/
protected final PropertyDefinition<?> getNamingPropertyDefinition() {
return namingPropertyDefinition;
}
/**
* Gets the property associated with the specified property definition.
*
* @param <P>
* The underlying type of the property.
* @param pd
* The Property definition.
* @return Returns the property associated with the specified property
* definition.
* @throws IllegalArgumentException
* If this property provider does not recognize the requested
* property definition.
*/
protected final <P> Property<P> getProperty(PropertyDefinition<P> pd) {
return properties.getProperty(pd);
}
/**
* Applies changes made to this managed object.
*
* @throws ConcurrentModificationException
* If this managed object has been removed from the server by
* another client.
* @throws OperationRejectedException
* If the managed object cannot be added due to some client-side
* or server-side constraint which cannot be satisfied.
* @throws LdapException
* If any other error occurs.
*/
protected abstract void modifyExistingManagedObject() throws ConcurrentModificationException,
OperationRejectedException, LdapException;
/**
* Creates a new managed object.
*
* @param <M>
* The type of client configuration represented by the client
* managed object.
* @param d
* The managed object's definition.
* @param path
* The managed object's path.
* @param properties
* The managed object's properties.
* @param existsOnServer
* Indicates whether or not the managed object exists on the
* server (false means the managed object is new and has not been
* committed).
* @param namingPropertyDefinition
* Optional naming property definition.
* @return Returns the new managed object.
*/
protected abstract <M extends ConfigurationClient> ManagedObject<M> newInstance(ManagedObjectDefinition<M, ?> d,
ManagedObjectPath<M, ?> path, PropertySet properties, boolean existsOnServer,
PropertyDefinition<?> namingPropertyDefinition);
/**
* Creates a new managed object with no active values, just default
* values.
*/
private <M extends ConfigurationClient, P> ManagedObject<M> createNewManagedObject(
ManagedObjectDefinition<M, ?> d, ManagedObjectPath<M, ?> p, PropertyDefinition<P> namingPropertyDefinition,
String name, Collection<PropertyException> exceptions) {
PropertySet childProperties = new PropertySet();
for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
try {
createProperty(childProperties, p, pd);
} catch (PropertyException e) {
// Add the exception if requested.
if (exceptions != null) {
exceptions.add(e);
}
}
}
// Set the naming property if there is one.
if (namingPropertyDefinition != null) {
P value = namingPropertyDefinition.decodeValue(name);
childProperties.setPropertyValues(namingPropertyDefinition, Collections.singleton(value));
}
return newInstance(d, p, childProperties, false, namingPropertyDefinition);
}
/** Create an empty property. */
private <P> void createProperty(PropertySet properties, ManagedObjectPath<?, ?> p, PropertyDefinition<P> pd) {
try {
Driver context = getDriver();
Collection<P> defaultValues = context.findDefaultValues(p, pd, true);
properties.addProperty(pd, defaultValues, Collections.<P> emptySet());
} catch (PropertyException e) {
// Make sure that we have still created the property.
properties.addProperty(pd, Collections.<P> emptySet(), Collections.<P> emptySet());
throw e;
}
}
/** Makes sure that this managed object exists. */
private void ensureThisManagedObjectExists() throws ConcurrentModificationException, LdapException {
if (!path.isEmpty()) {
Driver ctx = getDriver();
try {
if (!ctx.managedObjectExists(path)) {
throw new ConcurrentModificationException();
}
} catch (ManagedObjectNotFoundException e) {
throw new ConcurrentModificationException();
}
}
}
/**
* Validate that a relation definition belongs to this managed
* object.
*/
private void validateRelationDefinition(RelationDefinition<?, ?> rd) {
ManagedObjectDefinition<T, ?> d = getManagedObjectDefinition();
RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
if (tmp != rd) {
throw new IllegalArgumentException("The relation " + rd.getName() + " is not associated with a "
+ d.getName());
}
}
}