| | |
| | | * The type of the property. |
| | | */ |
| | | private static class DefaultValueFinder<T> implements |
| | | DefaultBehaviorProviderVisitor<T, Collection<T>, ManagedObjectPath> { |
| | | DefaultBehaviorProviderVisitor<T, Collection<T>, Void> { |
| | | |
| | | /** |
| | | * Get the default values for the specified property. |
| | |
| | | * The managed object path of the current managed object. |
| | | * @param pd |
| | | * The property definition. |
| | | * @param isCreate |
| | | * Indicates whether the managed object has been created |
| | | * yet. |
| | | * @return Returns the default values for the specified property. |
| | | * @throws DefaultBehaviorException |
| | | * If the default values could not be retrieved or |
| | |
| | | */ |
| | | 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; |
| | | PropertyDefinition<T> pd, boolean isCreate) |
| | | throws DefaultBehaviorException { |
| | | DefaultValueFinder<T> v = new DefaultValueFinder<T>(context, p, isCreate); |
| | | return v.find(p, pd); |
| | | } |
| | | |
| | | // The LDAP management context. |
| | |
| | | // values. |
| | | private DefaultBehaviorException exception = null; |
| | | |
| | | // The property definition whose default values are required. |
| | | private final PropertyDefinition<T> pd; |
| | | // Indicates whether the managed object has been created yet. |
| | | private final boolean isCreate; |
| | | |
| | | // The path of the managed object containing the first property. |
| | | private final ManagedObjectPath firstPath; |
| | | |
| | | // The path of the managed object containing the next property. |
| | | private ManagedObjectPath nextPath = null; |
| | | |
| | | // The next property whose default values were required. |
| | | private PropertyDefinition<T> nextProperty = null; |
| | | |
| | | |
| | | |
| | | // Private constructor. |
| | | private DefaultValueFinder(LDAPManagementContext context, |
| | | PropertyDefinition<T> pd) { |
| | | ManagedObjectPath p, boolean isCreate) { |
| | | this.context = context; |
| | | this.pd = pd; |
| | | this.firstPath = p; |
| | | this.isCreate = isCreate; |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<T> visitAbsoluteInherited( |
| | | AbsoluteInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) { |
| | | AbsoluteInheritedDefaultBehaviorProvider<T> d, Void p) { |
| | | try { |
| | | return getInheritedProperty(d.getManagedObjectPath(), d |
| | | .getManagedObjectDefinition(), d.getPropertyName()); |
| | | } catch (DefaultBehaviorException e) { |
| | | exception = new DefaultBehaviorException(pd, e); |
| | | exception = e; |
| | | return Collections.emptySet(); |
| | | } |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d, |
| | | ManagedObjectPath p) { |
| | | Void p) { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d, |
| | | ManagedObjectPath p) { |
| | | Void p) { |
| | | Collection<String> stringValues = d.getDefaultValues(); |
| | | List<T> values = new ArrayList<T>(stringValues.size()); |
| | | |
| | | for (String stringValue : stringValues) { |
| | | try { |
| | | values.add(pd.decodeValue(stringValue)); |
| | | values.add(nextProperty.decodeValue(stringValue)); |
| | | } catch (IllegalPropertyValueStringException e) { |
| | | exception = new DefaultBehaviorException(pd, e); |
| | | exception = new DefaultBehaviorException(nextProperty, e); |
| | | break; |
| | | } |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<T> visitRelativeInherited( |
| | | RelativeInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) { |
| | | RelativeInheritedDefaultBehaviorProvider<T> d, Void p) { |
| | | try { |
| | | return getInheritedProperty(d.getManagedObjectPath(p), d |
| | | return getInheritedProperty(d.getManagedObjectPath(nextPath), d |
| | | .getManagedObjectDefinition(), d.getPropertyName()); |
| | | } catch (DefaultBehaviorException e) { |
| | | exception = new DefaultBehaviorException(pd, e); |
| | | exception = e; |
| | | return Collections.emptySet(); |
| | | } |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d, |
| | | ManagedObjectPath p) { |
| | | Void p) { |
| | | return Collections.emptySet(); |
| | | } |
| | | |
| | | |
| | | |
| | | // Find the default values for the next path/property. |
| | | private Collection<T> find(ManagedObjectPath p, PropertyDefinition<T> pd) |
| | | throws DefaultBehaviorException { |
| | | this.nextPath = p; |
| | | this.nextProperty = pd; |
| | | |
| | | Collection<T> values = nextProperty.getDefaultBehaviorProvider().accept( |
| | | this, null); |
| | | |
| | | if (exception != null) { |
| | | throw exception; |
| | | } |
| | | |
| | | if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) { |
| | | throw new DefaultBehaviorException(pd, |
| | | new PropertyIsSingleValuedException(pd)); |
| | | } |
| | | |
| | | return values; |
| | | } |
| | | |
| | | |
| | | |
| | | // Get an inherited property value. |
| | | @SuppressWarnings("unchecked") |
| | | private Collection<T> getInheritedProperty(ManagedObjectPath target, |
| | | AbstractManagedObjectDefinition<?, ?> d, String propertyName) |
| | | throws DefaultBehaviorException { |
| | | // First check that the requested type of managed object |
| | | // corresponds to the path. |
| | | AbstractManagedObjectDefinition<?, ?> supr = target |
| | | .getManagedObjectDefinition(); |
| | | if (!supr.isParentOf(d)) { |
| | | throw new DefaultBehaviorException(nextProperty, |
| | | new DefinitionDecodingException(Reason.WRONG_TYPE_INFORMATION)); |
| | | } |
| | | |
| | | // Save the current property in case of recursion. |
| | | PropertyDefinition<T> pd1 = nextProperty; |
| | | |
| | | 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); |
| | | } |
| | | // If the path relates to the current managed object and the |
| | | // managed object is in the process of being created it won't |
| | | // exist, so we should just use the default values of the |
| | | // referenced property. |
| | | if (isCreate && firstPath.equals(target)) { |
| | | PropertyDefinition<T> pd2; |
| | | try { |
| | | // FIXME: we use the definition taken from the default |
| | | // behavior here when we should really use the exact |
| | | // definition of the component being created. |
| | | PropertyDefinition<?> pdTmp = d.getPropertyDefinition(propertyName); |
| | | pd2 = pd1.getClass().cast(pdTmp); |
| | | } catch (IllegalArgumentException e) { |
| | | throw new PropertyNotFoundException(propertyName); |
| | | } catch (ClassCastException e) { |
| | | // FIXME: would be nice to throw a better exception here. |
| | | throw new PropertyNotFoundException(propertyName); |
| | | } |
| | | |
| | | // 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> tmp = find(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); |
| | | for (T value : tmp) { |
| | | pd1.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())); |
| | | } |
| | | // Get the actual managed object definition. |
| | | LdapName dn = LDAPNameBuilder |
| | | .create(target, context.getLDAPProfile()); |
| | | ManagedObjectDefinition<?, ?> mod = |
| | | getEntryDefinition(context, d, dn); |
| | | |
| | | PropertyDefinition<T> pd2; |
| | | try { |
| | | PropertyDefinition<?> pdTmp = mod |
| | | .getPropertyDefinition(propertyName); |
| | | pd2 = pd1.getClass().cast(pdTmp); |
| | | } catch (IllegalArgumentException e) { |
| | | throw new PropertyNotFoundException(propertyName); |
| | | } catch (ClassCastException e) { |
| | | // FIXME: would be nice to throw a better exception here. |
| | | throw new PropertyNotFoundException(propertyName); |
| | | } |
| | | return values; |
| | | |
| | | 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<T> tmp = find(target, pd2); |
| | | Collection<T> values = new ArrayList<T>(tmp.size()); |
| | | for (T value : tmp) { |
| | | pd1.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(pd1.decodeValue(value.toString())); |
| | | } |
| | | } |
| | | return values; |
| | | } |
| | | } |
| | | } catch (DefaultBehaviorException e) { |
| | | // Wrap any errors due to recursion. |
| | | throw new DefaultBehaviorException(pd1, e); |
| | | } catch (DefinitionDecodingException e) { |
| | | throw new DefaultBehaviorException(pd, e); |
| | | throw new DefaultBehaviorException(pd1, e); |
| | | } catch (PropertyNotFoundException e) { |
| | | throw new DefaultBehaviorException(pd, e); |
| | | throw new DefaultBehaviorException(pd1, e); |
| | | } catch (IllegalPropertyValueException e) { |
| | | throw new DefaultBehaviorException(pd, e); |
| | | throw new DefaultBehaviorException(pd1, e); |
| | | } catch (IllegalPropertyValueStringException e) { |
| | | throw new DefaultBehaviorException(pd, e); |
| | | throw new DefaultBehaviorException(pd1, e); |
| | | } catch (NameNotFoundException e) { |
| | | throw new DefaultBehaviorException(pd, |
| | | throw new DefaultBehaviorException(pd1, |
| | | new ManagedObjectNotFoundException()); |
| | | } catch (NoPermissionException e) { |
| | | throw new DefaultBehaviorException(pd, new AuthorizationException(e)); |
| | | throw new DefaultBehaviorException(pd1, new AuthorizationException(e)); |
| | | } catch (NamingException e) { |
| | | throw new DefaultBehaviorException(pd, new CommunicationException(e)); |
| | | throw new DefaultBehaviorException(pd1, new CommunicationException(e)); |
| | | } |
| | | } |
| | | }; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public <M extends ConfigurationClient, N extends M> |
| | | ManagedObject<N> createChild( |
| | | OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d, |
| | |
| | | PropertyDefinition<T> pd) throws DefaultBehaviorException { |
| | | try { |
| | | Collection<T> defaultValues = DefaultValueFinder.getDefaultValues( |
| | | context, p, pd); |
| | | context, p, pd, true); |
| | | properties.addProperty(pd, defaultValues, Collections.<T> emptySet()); |
| | | } catch (DefaultBehaviorException e) { |
| | | // Make sure that we have still created the property. |
| | |
| | | // Get the property's default values. |
| | | Collection<T> defaultValues; |
| | | try { |
| | | defaultValues = DefaultValueFinder.getDefaultValues(context, p, pd); |
| | | defaultValues = DefaultValueFinder.getDefaultValues(context, p, pd, |
| | | false); |
| | | } catch (DefaultBehaviorException e) { |
| | | defaultValues = Collections.emptySet(); |
| | | exception = e; |