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