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 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.api; 028 import org.opends.messages.Message; 029 030 031 032 import java.util.HashSet; 033 import java.util.List; 034 import java.util.Set; 035 036 import org.opends.server.admin.std.server.GroupImplementationCfg; 037 import org.opends.server.config.ConfigException; 038 import org.opends.server.types.DirectoryException; 039 import org.opends.server.types.DN; 040 import org.opends.server.types.Entry; 041 import org.opends.server.types.InitializationException; 042 import org.opends.server.types.MemberList; 043 import org.opends.server.types.SearchFilter; 044 import org.opends.server.types.SearchScope; 045 046 047 048 /** 049 * This class defines the set of methods that must be implemented by a 050 * Directory Server group. It is expected that there will be a number 051 * of different types of groups (e.g., legacy static and dynamic 052 * groups, as well as enhanced groups and virtual static groups). The 053 * following operations may be performed on an OpenDS group: 054 * <UL> 055 * <LI>Determining whether a given user is a member of this 056 * group</LI> 057 * <LI>Determining the set of members for this group, optionally 058 * filtered based on some set of criteria.</LI> 059 * <LI>Retrieving or updating the set of nested groups for this 060 * group, if the underlying group type supports nesting).</LI> 061 * <LI>Updating the set of members for this group, if the underlying 062 * group type provides the ability to explicitly add or remove 063 * members.</LI> 064 * </UL> 065 * 066 * @param <T> The type of configuration handled by this group 067 * implementation. 068 */ 069 @org.opends.server.types.PublicAPI( 070 stability=org.opends.server.types.StabilityLevel.VOLATILE, 071 mayInstantiate=false, 072 mayExtend=true, 073 mayInvoke=true) 074 public abstract class Group<T extends GroupImplementationCfg> 075 { 076 /** 077 * Initializes a "shell" instance of this group implementation that 078 * may be used to identify and instantiate instances of this type of 079 * group in the directory data. 080 * 081 * @param configuration The configuration for this group 082 * implementation. 083 * 084 * @throws ConfigException If there is a problem with the provided 085 * configuration entry. 086 * 087 * @throws InitializationException If a problem occurs while 088 * attempting to initialize this 089 * group implementation that is 090 * not related to the server 091 * configuration. 092 */ 093 public abstract void initializeGroupImplementation(T configuration) 094 throws ConfigException, InitializationException; 095 096 097 098 /** 099 * Indicates whether the provided configuration is acceptable for 100 * this group implementation. It should be possible to call this 101 * method on an uninitialized group implementation instance in order 102 * to determine whether the group implementation would be able to 103 * use the provided configuration. 104 * <BR><BR> 105 * Note that implementations which use a subclass of the provided 106 * configuration class will likely need to cast the configuration 107 * to the appropriate subclass type. 108 * 109 * @param configuration The group implementation 110 * configuration for which to make the 111 * determination. 112 * @param unacceptableReasons A list that may be used to hold the 113 * reasons that the provided 114 * configuration is not acceptable. 115 * 116 * @return {@code true} if the provided configuration is acceptable 117 * for this group implementation, or {@code false} if not. 118 */ 119 public boolean isConfigurationAcceptable( 120 GroupImplementationCfg configuration, 121 List<Message> unacceptableReasons) 122 { 123 // This default implementation does not perform any special 124 // validation. It should be overridden by group implementations 125 // that wish to perform more detailed validation. 126 return true; 127 } 128 129 130 131 /** 132 * Performs any necessary finalization that may be needed whenever 133 * this group implementation is taken out of service within the 134 * Directory Server (e.g., if it is disabled or the server is 135 * shutting down). 136 */ 137 public void finalizeGroupImplementation() 138 { 139 // No implementation is required by default. 140 } 141 142 143 144 /** 145 * Creates a new group of this type based on the definition 146 * contained in the provided entry. This method must be designed so 147 * that it may be invoked on the "shell" instance created using the 148 * default constructor and initialized with the 149 * {@code initializeGroupImplementation} method. 150 * 151 * @param groupEntry The entry containing the definition for the 152 * group to be created. 153 * 154 * @return The group instance created from the definition in the 155 * provided entry. 156 * 157 * @throws DirectoryException If a problem occurs while trying to 158 * create the group instance. 159 */ 160 public abstract Group newInstance(Entry groupEntry) 161 throws DirectoryException; 162 163 164 165 /** 166 * Retrieves a search filter that may be used to identify entries 167 * containing definitions for groups of this type in the Directory 168 * Server. This method must be designed so that it may be invoked 169 * on the "shell" instance created using the default constructor and 170 * initialized with the {@code initializeGroupImplementation} 171 * method. 172 * 173 * @return A search filter that may be used to identify entries 174 * containing definitions for groups of this type in the 175 * Directory Server. 176 * 177 * @throws DirectoryException If a problem occurs while trying to 178 * locate all of the applicable group 179 * definition entries. 180 */ 181 public abstract SearchFilter getGroupDefinitionFilter() 182 throws DirectoryException; 183 184 185 186 /** 187 * Indicates whether the provided entry contains a valid definition 188 * for this type of group. 189 * 190 * @param entry The entry for which to make the determination. 191 * 192 * @return {@code true} if the provided entry does contain a valid 193 * definition for this type of group, or {@code false} if 194 * it does not. 195 */ 196 public abstract boolean isGroupDefinition(Entry entry); 197 198 199 200 /** 201 * Retrieves the DN of the entry that contains the definition for 202 * this group. 203 * 204 * @return The DN of the entry that contains the definition for 205 * this group. 206 */ 207 public abstract DN getGroupDN(); 208 209 210 211 /** 212 * Indicates whether this group supports nesting other groups, such 213 * that the members of the nested groups will also be considered 214 * members of this group. 215 * 216 * @return {@code true} if this group supports nesting other 217 * groups, or {@code false} if it does not. 218 */ 219 public abstract boolean supportsNestedGroups(); 220 221 222 223 /** 224 * Retrieves a list of the DNs of any nested groups whose members 225 * should be considered members of this group. 226 * 227 * @return A list of the DNs of any nested groups whose members 228 * should be considered members of this group. 229 */ 230 public abstract List<DN> getNestedGroupDNs(); 231 232 233 234 /** 235 * Attempts to add the provided group DN as a nested group within 236 * this group. The change should be committed to persistent storage 237 * through an internal operation. 238 * 239 * @param nestedGroupDN The DN of the group that should be added 240 * to the set of nested groups for this 241 * group. 242 * 243 * @throws UnsupportedOperationException If this group does not 244 * support nesting. 245 * 246 * @throws DirectoryException If a problem occurs while attempting 247 * to nest the provided group DN. 248 */ 249 public abstract void addNestedGroup(DN nestedGroupDN) 250 throws UnsupportedOperationException, DirectoryException; 251 252 253 254 /** 255 * Attempts to remove the provided group as a nested group within 256 * this group. The change should be committed to persistent storage 257 * through an internal operation. 258 * 259 * @param nestedGroupDN The DN of the group that should be removed 260 * from the set of nested groups for this 261 * group. 262 * 263 * @throws UnsupportedOperationException If this group does not 264 * support nesting. 265 * 266 * @throws DirectoryException If a problem occurs while attempting 267 * to nest the provided group DN. 268 */ 269 public abstract void removeNestedGroup(DN nestedGroupDN) 270 throws UnsupportedOperationException, DirectoryException; 271 272 273 274 /** 275 * Indicates whether the user with the specified DN is a member of 276 * this group. Note that this is a point-in-time determination and 277 * the caller must not cache the result. 278 * 279 * @param userDN The DN of the user for which to make the 280 * determination. 281 * 282 * @return {@code true} if the specified user is currently a member 283 * of this group, or {@code false} if not. 284 * 285 * @throws DirectoryException If a problem occurs while attempting 286 * to make the determination. 287 */ 288 public boolean isMember(DN userDN) 289 throws DirectoryException 290 { 291 return isMember(userDN, new HashSet<DN>()); 292 } 293 294 295 296 /** 297 * Indicates whether the user with the specified DN is a member of 298 * this group. Note that this is a point-in-time determination and 299 * the caller must not cache the result. Also note that group 300 * implementations that support nesting should use this version of 301 * the method ratehr than the version that does not take a set of 302 * DNs when attempting to determine whether a nested group includes 303 * the target member. 304 * 305 * @param userDN The DN of the user for which to make the 306 * determination. 307 * @param examinedGroups A set of groups that have already been 308 * examined in the process of making the 309 * determination. This provides a mechanism 310 * to prevent infinite recursion due to 311 * circular references (e.g., two groups 312 * include each other as nested groups). 313 * Each time a group instance is checked, 314 * its DN should be added to the list, and 315 * any DN already contained in the list 316 * should be skipped. 317 * 318 * @return {@code true} if the specified user is currently a member 319 * of this group, or {@code false} if not. 320 * 321 * @throws DirectoryException If a problem occurs while attempting 322 * to make the determination. 323 */ 324 public abstract boolean isMember(DN userDN, Set<DN> examinedGroups) 325 throws DirectoryException; 326 327 328 329 /** 330 * Indicates whether the user described by the provided user entry 331 * is a member of this group. Note that this is a point-in-time 332 * determination and the caller must not cache the result. 333 * 334 * @param userEntry The entry for the user for which to make the 335 * determination. 336 * 337 * @return {@code true} if the specified user is currently a member 338 * of this group, or {@code false} if not. 339 * 340 * @throws DirectoryException If a problem occurs while attempting 341 * to make the determination. 342 */ 343 public boolean isMember(Entry userEntry) 344 throws DirectoryException 345 { 346 return isMember(userEntry, new HashSet<DN>()); 347 } 348 349 350 351 /** 352 * Indicates whether the user described by the provided user entry 353 * is a member of this group. Note that this is a point-in-time 354 * determination and the caller must not cache the result. Also 355 * note that group implementations that support nesting should use 356 * this version of the method ratehr than the version that does not 357 * take a set of DNs when attempting to determine whether a nested 358 * group includes the target member. 359 * 360 * @param userEntry The entry for the user for which to make 361 * the determination. 362 * @param examinedGroups A set of groups that have already been 363 * examined in the process of making the 364 * determination. This provides a mechanism 365 * to prevent infinite recursion due to 366 * circular references (e.g., two groups 367 * include each other as nested groups). 368 * Each time a group instance is checked, 369 * its DN should be added to the list, and 370 * any DN already contained in the list 371 * should be skipped. 372 * 373 * @return {@code true} if the specified user is currently a member 374 * of this group, or {@code false} if not. 375 * 376 * @throws DirectoryException If a problem occurs while attempting 377 * to make the determination. 378 */ 379 public abstract boolean isMember(Entry userEntry, 380 Set<DN> examinedGroups) 381 throws DirectoryException; 382 383 384 385 /** 386 * Retrieves an iterator that may be used to cursor through the 387 * entries of the members contained in this group. Note that this 388 * is a point-in-time determination, and the caller must not cache 389 * the result. Further, the determination should only include this 390 * group and not members from nested groups. 391 * 392 * @return An iterator that may be used to cursor through the 393 * entries of the members contained in this group. 394 * 395 * @throws DirectoryException If a problem occurs while attempting 396 * to retrieve the set of members. 397 */ 398 public MemberList getMembers() 399 throws DirectoryException 400 { 401 return getMembers(null, null, null); 402 } 403 404 405 406 /** 407 * Retrieves an iterator that may be used to cursor through the 408 * entries of the members contained in this group. It may 409 * optionally retrieve a subset of the member entries based on a 410 * given set of criteria. Note that this is a point-in-time 411 * determination, and the caller must not cache the result. 412 * 413 * @param baseDN The base DN that should be used when determining 414 * whether a given entry will be returned. If this 415 * is {@code null}, then all entries will be 416 * considered in the scope of the criteria. 417 * @param scope The scope that should be used when determining 418 * whether a given entry will be returned. It must 419 * not be {@code null} if the provided base DN is 420 * not {@code null}. The scope will be ignored if 421 * no base DN is provided. 422 * @param filter The filter that should be used when determining 423 * whether a given entry will be returned. If this 424 * is {@code null}, then any entry in the scope of 425 * the criteria will be included in the results. 426 * 427 * @return An iterator that may be used to cursor through the 428 * entries of the members contained in this group. 429 * 430 * @throws DirectoryException If a problem occurs while attempting 431 * to retrieve the set of members. 432 */ 433 public abstract MemberList getMembers(DN baseDN, SearchScope scope, 434 SearchFilter filter) 435 throws DirectoryException; 436 437 438 439 /** 440 * Indicates whether it is possible to alter the member list for 441 * this group (e.g., in order to add members to the group or remove 442 * members from it). 443 * 444 * @return {@code true} if it is possible to add members to this 445 * group, or {@code false} if not. 446 */ 447 public abstract boolean mayAlterMemberList(); 448 449 450 451 /** 452 * Attempts to add the provided user as a member of this group. The 453 * change should be committed to persistent storage through an 454 * internal operation. 455 * 456 * @param userEntry The entry for the user to be added as a member 457 * of this group. 458 * 459 * @throws UnsupportedOperationException If this group does not 460 * support altering the 461 * member list. 462 * 463 * @throws DirectoryException If a problem occurs while attempting 464 * to add the provided user as a member 465 * of this group. 466 */ 467 public abstract void addMember(Entry userEntry) 468 throws UnsupportedOperationException, DirectoryException; 469 470 471 472 /** 473 * Attempts to remove the specified user as a member of this group. 474 * The change should be committed to persistent storage through an 475 * internal operation. 476 * 477 * @param userDN The DN of the user to remove as a member of this 478 * group. 479 * 480 * @throws UnsupportedOperationException If this group does not 481 * support altering the 482 * member list. 483 * 484 * @throws DirectoryException If a problem occurs while attempting 485 * to remove the provided user as a 486 * member of this group. 487 */ 488 public abstract void removeMember(DN userDN) 489 throws UnsupportedOperationException, DirectoryException; 490 491 492 493 /** 494 * Retrieves a string representation of this group. 495 * 496 * @return A string representation of this group. 497 */ 498 public String toString() 499 { 500 StringBuilder buffer = new StringBuilder(); 501 toString(buffer); 502 return buffer.toString(); 503 } 504 505 506 507 /** 508 * Appends a string representation of this group to the provided 509 * buffer. 510 * 511 * @param buffer The buffer to which the string representation 512 * should be appended. 513 */ 514 public abstract void toString(StringBuilder buffer); 515 } 516