001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.types;
028    
029    
030    
031    import java.util.Iterator;
032    import java.util.Set;
033    
034    import org.opends.server.admin.std.meta.VirtualAttributeCfgDefn;
035    import org.opends.server.admin.std.server.VirtualAttributeCfg;
036    import org.opends.server.api.Group;
037    import org.opends.server.api.VirtualAttributeProvider;
038    import org.opends.server.core.DirectoryServer;
039    
040    import static org.opends.server.loggers.debug.DebugLogger.*;
041    import org.opends.server.loggers.debug.DebugTracer;
042    import static org.opends.server.util.Validator.*;
043    
044    
045    
046    /**
047     * This class defines a virtual attribute rule, which associates a
048     * virtual attribute provider with its associated configuration,
049     * including the attribute type for which the values should be
050     * generated; the base DN(s), group DN(s), and search filter(s) that
051     * should be used to identify which entries should have the virtual
052     * attribute, and how conflicts between real and virtual values should
053     * be handled.
054     */
055    @org.opends.server.types.PublicAPI(
056         stability=org.opends.server.types.StabilityLevel.VOLATILE,
057         mayInstantiate=false,
058         mayExtend=false,
059         mayInvoke=true)
060    public final class VirtualAttributeRule
061    {
062      /**
063       * The tracer object for the debug logger.
064       */
065      private static final DebugTracer TRACER = getTracer();
066    
067      // The attribute type for which the values should be generated.
068      private final AttributeType attributeType;
069    
070      // The set of base DNs for branches that are eligible to have this
071      // virtual attribute.
072      private final Set<DN> baseDNs;
073    
074      // The set of DNs for groups whose members are eligible to have this
075      // virtual attribute.
076      private final Set<DN> groupDNs;
077    
078      // The set of search filters for entries that are eligible to have
079      // this virtual attribute.
080      private final Set<SearchFilter> filters;
081    
082      // The virtual attribute provider used to generate the values.
083      private final VirtualAttributeProvider<
084                         ? extends VirtualAttributeCfg> provider;
085    
086      // The behavior that should be exhibited for entries that already
087      // have real values for the target attribute.
088      private final VirtualAttributeCfgDefn.ConflictBehavior
089                         conflictBehavior;
090    
091    
092    
093      /**
094       * Creates a new virtual attribute rule with the provided
095       * information.
096       *
097       * @param  attributeType     The attribute type for which the values
098       *                           should be generated.
099       * @param  provider          The virtual attribute provider to use
100       *                           to generate the values.
101       * @param  baseDNs           The set of base DNs for branches that
102       *                           are eligible to have this virtual
103       *                           attribute.
104       * @param  groupDNs          The set of DNs for groups whose members
105       *                           are eligible to have this virtual
106       *                           attribute.
107       * @param  filters           The set of search filters for entries
108       *                           that are eligible to have this virtual
109       *                           attribute.
110       * @param  conflictBehavior  The behavior that the server should
111       *                           exhibit for entries that already have
112       *                           one or more real values for the target
113       *                           attribute.
114       */
115      public VirtualAttributeRule(AttributeType attributeType,
116                  VirtualAttributeProvider<? extends VirtualAttributeCfg>
117                       provider,
118                  Set<DN> baseDNs, Set<DN> groupDNs,
119                  Set<SearchFilter> filters,
120                  VirtualAttributeCfgDefn.ConflictBehavior
121                       conflictBehavior)
122      {
123        ensureNotNull(attributeType, provider, baseDNs, groupDNs);
124        ensureNotNull(filters, conflictBehavior);
125    
126        this.attributeType    = attributeType;
127        this.provider         = provider;
128        this.baseDNs          = baseDNs;
129        this.groupDNs         = groupDNs;
130        this.filters          = filters;
131        this.conflictBehavior = conflictBehavior;
132      }
133    
134    
135    
136      /**
137       * Retrieves the attribute type for which the values should be
138       * generated.
139       *
140       * @return  The attribute type for which the values should be
141       *          generated.
142       */
143      public AttributeType getAttributeType()
144      {
145        return attributeType;
146      }
147    
148    
149    
150      /**
151       *
152       * Retrieves the virtual attribute provider used to generate the
153       * values.
154       *
155       * @return  The virtual attribute provider to use to generate the
156       *          values.
157       */
158      public VirtualAttributeProvider<? extends VirtualAttributeCfg>
159                  getProvider()
160      {
161        return provider;
162      }
163    
164    
165    
166      /**
167       * Retrieves the set of base DNs for branches that are eligible to
168       * have this virtual attribute.
169       *
170       * @return  The set of base DNs for branches that are eligible to
171       *          have this virtual attribute.
172       */
173      public Set<DN> getBaseDNs()
174      {
175        return baseDNs;
176      }
177    
178    
179    
180      /**
181       * Retrieves the set of DNs for groups whose members are eligible to
182       * have this virtual attribute.
183       *
184       * @return  The set of DNs for groups whose members are eligible to
185       *          have this virtual attribute.
186       */
187      public Set<DN> getGroupDNs()
188      {
189        return groupDNs;
190      }
191    
192    
193    
194      /**
195       * Retrieves the set of search filters for entries that are eligible
196       * to have this virtual attribute.
197       *
198       * @return  The set of search filters for entries that are eligible
199       *          to have this virtual attribute.
200       */
201      public Set<SearchFilter> getFilters()
202      {
203        return filters;
204      }
205    
206    
207    
208      /**
209       * Retrieves the behavior that the server should exhibit for entries
210       * that already have one or more real values for the target
211       * attribute.
212       *
213       * @return  The behavior that the server should exhibit for entries
214       *          that already have one or more real values for the target
215       *          attribute.
216       */
217      public VirtualAttributeCfgDefn.ConflictBehavior
218                  getConflictBehavior()
219      {
220        return conflictBehavior;
221      }
222    
223    
224    
225      /**
226       * Indicates whether this virtual attribute rule applies to the
227       * provided entry, taking into account the eligibility requirements
228       * defined in the rule.
229       *
230       * @param  entry  The entry for which to make the determination.
231       *
232       * @return  {@code true} if this virtual attribute rule may be used
233       *          to generate values for the entry, or {@code false} if
234       *          not.
235       */
236      public boolean appliesToEntry(Entry entry)
237      {
238        // We'll do this in order of expense so that the checks which are
239        // potentially most expensive are done last.  First, check to see
240        // if real values should override virtual ones and if so whether
241        // the entry already has virtual values.
242        if ((conflictBehavior == VirtualAttributeCfgDefn.ConflictBehavior.
243                                      REAL_OVERRIDES_VIRTUAL) &&
244            entry.hasAttribute(attributeType))
245        {
246          return false;
247        }
248    
249        // If there are any base DNs defined, then the entry must be below
250        // one of them.
251        DN entryDN = entry.getDN();
252        if (! baseDNs.isEmpty())
253        {
254          boolean found = false;
255          for (DN dn : baseDNs)
256          {
257            if (entryDN.isDescendantOf(dn))
258            {
259              found = true;
260              break;
261            }
262          }
263    
264          if (! found)
265          {
266            return false;
267          }
268        }
269    
270        // If there are any search filters defined, then the entry must
271        // match one of them.
272        if (! filters.isEmpty())
273        {
274          boolean found = false;
275          for (SearchFilter filter : filters)
276          {
277            try
278            {
279              if (filter.matchesEntry(entry))
280              {
281                found = true;
282                break;
283              }
284            }
285            catch (Exception e)
286            {
287              if (debugEnabled())
288              {
289                TRACER.debugCaught(DebugLogLevel.ERROR, e);
290              }
291            }
292          }
293    
294          if (! found)
295          {
296            return false;
297          }
298        }
299    
300        // If there are any group memberships defined, then the entry must
301        // be a member of one of them.
302        if (! groupDNs.isEmpty())
303        {
304          boolean found = false;
305          for (DN dn : groupDNs)
306          {
307            try
308            {
309              Group group =
310                   DirectoryServer.getGroupManager().getGroupInstance(dn);
311              if ((group != null) && group.isMember(entry))
312              {
313                found = true;
314                break;
315              }
316            }
317            catch (Exception e)
318            {
319              if (debugEnabled())
320              {
321                TRACER.debugCaught(DebugLogLevel.ERROR, e);
322              }
323            }
324          }
325    
326          if (! found)
327          {
328            return false;
329          }
330        }
331    
332        // If we've gotten here, then the rule is applicable.
333        return true;
334      }
335    
336    
337    
338      /**
339       * Retrieves a string representation of this virtual attribute rule.
340       *
341       * @return  A string representation of this virutal attribute rule.
342       */
343      public String toString()
344      {
345        StringBuilder buffer = new StringBuilder();
346        toString(buffer);
347        return buffer.toString();
348      }
349    
350    
351    
352      /**
353       * Appends a string representation of this virtual attribute rule to
354       * the provided buffer.
355       *
356       * @param  buffer  The buffer to which the information should be
357       *                 written.
358       */
359      public void toString(StringBuilder buffer)
360      {
361        buffer.append("VirtualAttributeRule(attrType=");
362        buffer.append(attributeType.getNameOrOID());
363        buffer.append(", providerDN=\"");
364        buffer.append(provider.getClass().getName());
365    
366        buffer.append("\", baseDNs={");
367        if (! baseDNs.isEmpty())
368        {
369          buffer.append("\"");
370          Iterator<DN> iterator = baseDNs.iterator();
371          buffer.append(iterator.next());
372    
373          while (iterator.hasNext())
374          {
375            buffer.append("\", \"");
376            buffer.append(iterator.next());
377          }
378    
379          buffer.append("\"");
380        }
381    
382        buffer.append("}, groupDNs={");
383        if (! groupDNs.isEmpty())
384        {
385          buffer.append("\"");
386          Iterator<DN> iterator = groupDNs.iterator();
387          buffer.append(iterator.next());
388    
389          while (iterator.hasNext())
390          {
391            buffer.append("\", \"");
392            buffer.append(iterator.next());
393          }
394    
395          buffer.append("\"");
396        }
397    
398        buffer.append("}, filters={");
399        if (! filters.isEmpty())
400        {
401          buffer.append("\"");
402          Iterator<SearchFilter> iterator = filters.iterator();
403          buffer.append(iterator.next());
404    
405          while (iterator.hasNext())
406          {
407            buffer.append("\", \"");
408            buffer.append(iterator.next());
409          }
410    
411          buffer.append("\"");
412        }
413    
414        buffer.append("}, conflictBehavior=");
415        buffer.append(conflictBehavior);
416        buffer.append(")");
417      }
418    }
419