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.extensions; 028 029 030 031 import java.util.Collections; 032 import java.util.LinkedHashSet; 033 import java.util.LinkedList; 034 import java.util.List; 035 import java.util.Set; 036 037 import org.opends.messages.Message; 038 import org.opends.server.admin.std.server.GroupImplementationCfg; 039 import org.opends.server.admin.std.server.StaticGroupImplementationCfg; 040 import org.opends.server.api.Group; 041 import org.opends.server.core.ModifyOperationBasis; 042 import org.opends.server.core.DirectoryServer; 043 import org.opends.server.config.ConfigException; 044 import org.opends.server.loggers.ErrorLogger; 045 import org.opends.server.loggers.debug.DebugTracer; 046 import org.opends.server.protocols.internal.InternalClientConnection; 047 import org.opends.server.types.Attribute; 048 import org.opends.server.types.AttributeType; 049 import org.opends.server.types.AttributeValue; 050 import org.opends.server.types.Control; 051 import org.opends.server.types.DebugLogLevel; 052 import org.opends.server.types.DirectoryConfig; 053 import org.opends.server.types.DirectoryException; 054 import org.opends.server.types.DN; 055 import org.opends.server.types.Entry; 056 import org.opends.server.types.InitializationException; 057 import org.opends.server.types.MemberList; 058 import org.opends.server.types.MembershipException; 059 import org.opends.server.types.Modification; 060 import org.opends.server.types.ModificationType; 061 import org.opends.server.types.ObjectClass; 062 import org.opends.server.types.ResultCode; 063 import org.opends.server.types.SearchFilter; 064 import org.opends.server.types.SearchScope; 065 066 import static org.opends.messages.ExtensionMessages.*; 067 import static org.opends.server.loggers.debug.DebugLogger.*; 068 import static org.opends.server.util.ServerConstants.*; 069 import static org.opends.server.util.Validator.*; 070 071 072 073 /** 074 * This class provides a static group implementation, in which the DNs 075 * of all members are explicitly listed. There are two variants of 076 * static groups: one based on the {@code groupOfNames} object class, 077 * which stores the member list in the {@code member} attribute, and 078 * one based on the {@code groupOfUniqueNames} object class, which 079 * stores the member list in the {@code uniqueMember} attribute. 080 */ 081 public class StaticGroup 082 extends Group<StaticGroupImplementationCfg> 083 { 084 /** 085 * The tracer object for the debug logger. 086 */ 087 private static final DebugTracer TRACER = getTracer(); 088 089 // The attribute type used to hold the membership list for this group. 090 private AttributeType memberAttributeType; 091 092 // The DN of the entry that holds the definition for this group. 093 private DN groupEntryDN; 094 095 // The set of the DNs of the members for this group. 096 private LinkedHashSet<DN> memberDNs; 097 098 //The list of nested group DNs for this group. 099 private LinkedList<DN> nestedGroups = new LinkedList<DN>(); 100 101 //Passed to the group manager to see if the nested group list needs to be 102 //refreshed. 103 private long nestedGroupRefreshToken = 104 DirectoryServer.getGroupManager().refreshToken(); 105 106 107 108 /** 109 * Creates a new, uninitialized static group instance. This is intended for 110 * internal use only. 111 */ 112 public StaticGroup() 113 { 114 super(); 115 116 117 // No initialization is required here. 118 } 119 120 121 122 /** 123 * Creates a new static group instance with the provided information. 124 * 125 * @param groupEntryDN The DN of the entry that holds the definition 126 * for this group. 127 * @param memberAttributeType The attribute type used to hold the membership 128 * list for this group. 129 * @param memberDNs The set of the DNs of the members for this 130 * group. 131 */ 132 public StaticGroup(DN groupEntryDN, AttributeType memberAttributeType, 133 LinkedHashSet<DN> memberDNs) 134 { 135 super(); 136 137 138 ensureNotNull(groupEntryDN, memberAttributeType, memberDNs); 139 140 this.groupEntryDN = groupEntryDN; 141 this.memberAttributeType = memberAttributeType; 142 this.memberDNs = memberDNs; 143 } 144 145 146 147 /** 148 * {@inheritDoc} 149 */ 150 @Override() 151 public void initializeGroupImplementation( 152 StaticGroupImplementationCfg configuration) 153 throws ConfigException, InitializationException 154 { 155 // No additional initialization is required. 156 } 157 158 159 160 161 /** 162 * {@inheritDoc} 163 */ 164 @Override() 165 public StaticGroup newInstance(Entry groupEntry) 166 throws DirectoryException 167 { 168 ensureNotNull(groupEntry); 169 170 171 // Determine whether it is a groupOfNames or groupOfUniqueNames entry. If 172 // neither, then that's a problem. 173 AttributeType memberAttributeType; 174 ObjectClass groupOfEntriesClass = 175 DirectoryConfig.getObjectClass(OC_GROUP_OF_ENTRIES_LC, true); 176 ObjectClass groupOfNamesClass = 177 DirectoryConfig.getObjectClass(OC_GROUP_OF_NAMES_LC, true); 178 ObjectClass groupOfUniqueNamesClass = 179 DirectoryConfig.getObjectClass(OC_GROUP_OF_UNIQUE_NAMES_LC, true); 180 if (groupEntry.hasObjectClass(groupOfEntriesClass)) 181 { 182 if (groupEntry.hasObjectClass(groupOfNamesClass)) 183 { 184 Message message = ERR_STATICGROUP_INVALID_OC_COMBINATION. 185 get(String.valueOf(groupEntry.getDN()), OC_GROUP_OF_ENTRIES, 186 OC_GROUP_OF_NAMES); 187 throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message); 188 } 189 else if (groupEntry.hasObjectClass(groupOfUniqueNamesClass)) 190 { 191 Message message = ERR_STATICGROUP_INVALID_OC_COMBINATION. 192 get(String.valueOf(groupEntry.getDN()), OC_GROUP_OF_ENTRIES, 193 OC_GROUP_OF_UNIQUE_NAMES); 194 throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message); 195 } 196 197 memberAttributeType = DirectoryConfig.getAttributeType(ATTR_MEMBER, true); 198 } 199 else if (groupEntry.hasObjectClass(groupOfNamesClass)) 200 { 201 if (groupEntry.hasObjectClass(groupOfUniqueNamesClass)) 202 { 203 Message message = ERR_STATICGROUP_INVALID_OC_COMBINATION. 204 get(String.valueOf(groupEntry.getDN()), OC_GROUP_OF_NAMES, 205 OC_GROUP_OF_UNIQUE_NAMES); 206 throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message); 207 } 208 209 memberAttributeType = DirectoryConfig.getAttributeType(ATTR_MEMBER, true); 210 } 211 else if (groupEntry.hasObjectClass(groupOfUniqueNamesClass)) 212 { 213 memberAttributeType = 214 DirectoryConfig.getAttributeType(ATTR_UNIQUE_MEMBER_LC, true); 215 } 216 else 217 { 218 Message message = ERR_STATICGROUP_NO_VALID_OC. 219 get(String.valueOf(groupEntry.getDN()), OC_GROUP_OF_NAMES, 220 OC_GROUP_OF_UNIQUE_NAMES); 221 throw new DirectoryException(ResultCode.OBJECTCLASS_VIOLATION, message); 222 } 223 224 225 LinkedHashSet<DN> memberDNs = new LinkedHashSet<DN>(); 226 List<Attribute> memberAttrList = 227 groupEntry.getAttribute(memberAttributeType); 228 if (memberAttrList != null) 229 { 230 for (Attribute a : memberAttrList) 231 { 232 for (AttributeValue v : a.getValues()) 233 { 234 try 235 { 236 DN memberDN = DN.decode(v.getValue()); 237 memberDNs.add(memberDN); 238 } 239 catch (DirectoryException de) 240 { 241 if (debugEnabled()) 242 { 243 TRACER.debugCaught(DebugLogLevel.ERROR, de); 244 } 245 246 Message message = ERR_STATICGROUP_CANNOT_DECODE_MEMBER_VALUE_AS_DN. 247 get(v.getStringValue(), memberAttributeType.getNameOrOID(), 248 String.valueOf(groupEntry.getDN()), de.getMessageObject()); 249 ErrorLogger.logError(message); 250 } 251 } 252 } 253 } 254 255 256 return new StaticGroup(groupEntry.getDN(), memberAttributeType, memberDNs); 257 } 258 259 260 261 /** 262 * {@inheritDoc} 263 */ 264 @Override() 265 public SearchFilter getGroupDefinitionFilter() 266 throws DirectoryException 267 { 268 // FIXME -- This needs to exclude enhanced groups once we have support for 269 // them. 270 String filterString = 271 "(&(|(objectClass=groupOfNames)(objectClass=groupOfUniqueNames)" + 272 "(objectClass=groupOfEntries))" + 273 "(!(objectClass=ds-virtual-static-group)))"; 274 return SearchFilter.createFilterFromString(filterString); 275 } 276 277 278 279 /** 280 * {@inheritDoc} 281 */ 282 @Override() 283 public boolean isGroupDefinition(Entry entry) 284 { 285 ensureNotNull(entry); 286 287 // FIXME -- This needs to exclude enhanced groups once we have support for 288 //them. 289 ObjectClass virtualStaticGroupClass = 290 DirectoryConfig.getObjectClass(OC_VIRTUAL_STATIC_GROUP, true); 291 if (entry.hasObjectClass(virtualStaticGroupClass)) 292 { 293 return false; 294 } 295 296 ObjectClass groupOfEntriesClass = 297 DirectoryConfig.getObjectClass(OC_GROUP_OF_ENTRIES_LC, true); 298 ObjectClass groupOfNamesClass = 299 DirectoryConfig.getObjectClass(OC_GROUP_OF_NAMES_LC, true); 300 ObjectClass groupOfUniqueNamesClass = 301 DirectoryConfig.getObjectClass(OC_GROUP_OF_UNIQUE_NAMES_LC, true); 302 if (entry.hasObjectClass(groupOfEntriesClass)) 303 { 304 if (entry.hasObjectClass(groupOfNamesClass) || 305 entry.hasObjectClass(groupOfUniqueNamesClass)) 306 { 307 return false; 308 } 309 310 return true; 311 } 312 else if (entry.hasObjectClass(groupOfNamesClass)) 313 { 314 if (entry.hasObjectClass(groupOfUniqueNamesClass)) 315 { 316 return false; 317 } 318 319 return true; 320 } 321 else if (entry.hasObjectClass(groupOfUniqueNamesClass)) 322 { 323 return true; 324 } 325 else 326 { 327 return false; 328 } 329 } 330 331 332 333 /** 334 * {@inheritDoc} 335 */ 336 @Override() 337 public DN getGroupDN() 338 { 339 return groupEntryDN; 340 } 341 342 343 344 /** 345 * {@inheritDoc} 346 */ 347 @Override() 348 public boolean supportsNestedGroups() 349 { 350 return true; 351 } 352 353 354 355 /** 356 * {@inheritDoc} 357 */ 358 @Override() 359 public List<DN> getNestedGroupDNs() 360 { 361 try { 362 reloadIfNeeded(); 363 } catch (DirectoryException ex) { 364 return Collections.<DN>emptyList(); 365 } 366 return nestedGroups; 367 } 368 369 370 371 /** 372 * {@inheritDoc} 373 */ 374 @Override() 375 public void addNestedGroup(DN nestedGroupDN) 376 throws UnsupportedOperationException, DirectoryException 377 { 378 ensureNotNull(nestedGroupDN); 379 380 synchronized (this) 381 { 382 if (nestedGroups.contains(nestedGroupDN)) 383 { 384 Message msg = ERR_STATICGROUP_ADD_NESTED_GROUP_ALREADY_EXISTS.get( 385 String.valueOf(nestedGroupDN), 386 String.valueOf(groupEntryDN)); 387 throw new DirectoryException( 388 ResultCode.ATTRIBUTE_OR_VALUE_EXISTS, msg); 389 } 390 391 LinkedHashSet<AttributeValue> values = 392 new LinkedHashSet<AttributeValue>(1); 393 values.add(new AttributeValue(memberAttributeType, 394 nestedGroupDN.toString())); 395 396 Attribute attr = new Attribute(memberAttributeType, 397 memberAttributeType.getNameOrOID(), 398 values); 399 400 LinkedList<Modification> mods = new LinkedList<Modification>(); 401 mods.add(new Modification(ModificationType.ADD, attr)); 402 403 LinkedList<Control> requestControls = new LinkedList<Control>(); 404 requestControls.add(new Control(OID_INTERNAL_GROUP_MEMBERSHIP_UPDATE, 405 false)); 406 407 InternalClientConnection conn = 408 InternalClientConnection.getRootConnection(); 409 ModifyOperationBasis modifyOperation = 410 new ModifyOperationBasis(conn, 411 InternalClientConnection.nextOperationID(), 412 InternalClientConnection.nextMessageID(), requestControls, 413 groupEntryDN, mods); 414 modifyOperation.run(); 415 if (modifyOperation.getResultCode() != ResultCode.SUCCESS) 416 { 417 Message msg = ERR_STATICGROUP_ADD_MEMBER_UPDATE_FAILED.get( 418 String.valueOf(nestedGroupDN), 419 String.valueOf(groupEntryDN), 420 modifyOperation.getErrorMessage().toString()); 421 throw new DirectoryException(modifyOperation.getResultCode(), 422 msg); 423 } 424 425 426 LinkedList<DN> newNestedGroups = new LinkedList<DN>(nestedGroups); 427 newNestedGroups.add(nestedGroupDN); 428 nestedGroups = newNestedGroups; 429 //Add it to the member DN list. 430 LinkedHashSet<DN> newMemberDNs = new LinkedHashSet<DN>(memberDNs); 431 newMemberDNs.add(nestedGroupDN); 432 memberDNs = newMemberDNs; 433 } 434 } 435 436 437 438 /** 439 * {@inheritDoc} 440 */ 441 @Override() 442 public void removeNestedGroup(DN nestedGroupDN) 443 throws UnsupportedOperationException, DirectoryException 444 { 445 ensureNotNull(nestedGroupDN); 446 447 synchronized (this) 448 { 449 if (! nestedGroups.contains(nestedGroupDN)) 450 { 451 throw new DirectoryException( 452 ResultCode.NO_SUCH_ATTRIBUTE, 453 ERR_STATICGROUP_REMOVE_NESTED_GROUP_NO_SUCH_GROUP.get( 454 String.valueOf(nestedGroupDN), 455 String.valueOf(groupEntryDN))); 456 } 457 458 LinkedHashSet<AttributeValue> values = 459 new LinkedHashSet<AttributeValue>(1); 460 values.add(new AttributeValue(memberAttributeType, 461 nestedGroupDN.toString())); 462 463 Attribute attr = new Attribute(memberAttributeType, 464 memberAttributeType.getNameOrOID(), 465 values); 466 467 LinkedList<Modification> mods = new LinkedList<Modification>(); 468 mods.add(new Modification(ModificationType.DELETE, attr)); 469 470 LinkedList<Control> requestControls = new LinkedList<Control>(); 471 requestControls.add(new Control(OID_INTERNAL_GROUP_MEMBERSHIP_UPDATE, 472 false)); 473 474 InternalClientConnection conn = 475 InternalClientConnection.getRootConnection(); 476 ModifyOperationBasis modifyOperation = 477 new ModifyOperationBasis(conn, 478 InternalClientConnection.nextOperationID(), 479 InternalClientConnection.nextMessageID(), requestControls, 480 groupEntryDN, mods); 481 modifyOperation.run(); 482 if (modifyOperation.getResultCode() != ResultCode.SUCCESS) 483 { 484 throw new DirectoryException( 485 modifyOperation.getResultCode(), 486 ERR_STATICGROUP_REMOVE_MEMBER_UPDATE_FAILED.get( 487 String.valueOf(nestedGroupDN), 488 String.valueOf(groupEntryDN), 489 modifyOperation.getErrorMessage())); 490 } 491 492 493 LinkedList<DN> newNestedGroups = new LinkedList<DN>(nestedGroups); 494 newNestedGroups.remove(nestedGroupDN); 495 nestedGroups = newNestedGroups; 496 //Remove it from the member DN list. 497 LinkedHashSet<DN> newMemberDNs = new LinkedHashSet<DN>(memberDNs); 498 newMemberDNs.remove(nestedGroupDN); 499 memberDNs = newMemberDNs; 500 } 501 } 502 503 504 505 /** 506 * {@inheritDoc} 507 */ 508 @Override() 509 public boolean isMember(DN userDN, Set<DN> examinedGroups) 510 throws DirectoryException 511 { 512 reloadIfNeeded(); 513 if(memberDNs.contains(userDN)) 514 { 515 return true; 516 } 517 else if (! examinedGroups.add(getGroupDN())) 518 { 519 return false; 520 } 521 else 522 { 523 for(DN nestedGroupDN : nestedGroups) 524 { 525 Group<? extends GroupImplementationCfg> g = 526 (Group<? extends GroupImplementationCfg>) 527 DirectoryServer.getGroupManager().getGroupInstance(nestedGroupDN); 528 if((g != null) && (g.isMember(userDN, examinedGroups))) 529 { 530 return true; 531 } 532 } 533 } 534 return false; 535 } 536 537 538 539 /** 540 * {@inheritDoc} 541 */ 542 @Override() 543 public boolean isMember(Entry userEntry, Set<DN> examinedGroups) 544 throws DirectoryException 545 { 546 return isMember(userEntry.getDN(), examinedGroups); 547 } 548 549 550 551 /** 552 * Check if the group manager has registered a new group instance or removed a 553 * a group instance that might impact this group's membership list. 554 */ 555 private void 556 reloadIfNeeded() throws DirectoryException 557 { 558 //Check if group instances have changed by passing the group manager 559 //the current token. 560 if(DirectoryServer.getGroupManager(). 561 hasInstancesChanged(nestedGroupRefreshToken)) 562 { 563 synchronized (this) 564 { 565 Group thisGroup = 566 DirectoryServer.getGroupManager().getGroupInstance(groupEntryDN); 567 //Check if the group itself has been removed 568 if(thisGroup == null) { 569 throw new DirectoryException( 570 ResultCode.NO_SUCH_ATTRIBUTE, 571 ERR_STATICGROUP_GROUP_INSTANCE_INVALID.get( 572 String.valueOf(groupEntryDN))); 573 } else if(thisGroup != this) { 574 LinkedHashSet<DN> newMemberDNs = new LinkedHashSet<DN>(); 575 MemberList memberList=thisGroup.getMembers(); 576 while (memberList.hasMoreMembers()) { 577 try { 578 newMemberDNs.add(memberList.nextMemberDN()); 579 } catch (MembershipException ex) {} 580 } 581 memberDNs=newMemberDNs; 582 } 583 LinkedList<DN> newNestedGroups = new LinkedList<DN>(); 584 for(DN dn : memberDNs) 585 { 586 Group gr=DirectoryServer.getGroupManager().getGroupInstance(dn); 587 if(gr != null) 588 { 589 newNestedGroups.add(gr.getGroupDN()); 590 } 591 } 592 nestedGroupRefreshToken = 593 DirectoryServer.getGroupManager().refreshToken(); 594 nestedGroups=newNestedGroups; 595 } 596 } 597 } 598 599 600 /** 601 * {@inheritDoc} 602 */ 603 @Override() 604 public MemberList getMembers() 605 throws DirectoryException 606 { 607 reloadIfNeeded(); 608 return new SimpleStaticGroupMemberList(groupEntryDN, memberDNs); 609 } 610 611 612 613 /** 614 * {@inheritDoc} 615 */ 616 @Override() 617 public MemberList getMembers(DN baseDN, SearchScope scope, 618 SearchFilter filter) 619 throws DirectoryException 620 { 621 reloadIfNeeded(); 622 if ((baseDN == null) && (filter == null)) 623 { 624 return new SimpleStaticGroupMemberList(groupEntryDN, memberDNs); 625 } 626 else 627 { 628 return new FilteredStaticGroupMemberList(groupEntryDN, memberDNs, baseDN, 629 scope, filter); 630 } 631 } 632 633 634 635 /** 636 * {@inheritDoc} 637 */ 638 @Override() 639 public boolean mayAlterMemberList() 640 { 641 return true; 642 } 643 644 645 646 /** 647 * {@inheritDoc} 648 */ 649 @Override() 650 public void addMember(Entry userEntry) 651 throws UnsupportedOperationException, DirectoryException 652 { 653 ensureNotNull(userEntry); 654 655 synchronized (this) 656 { 657 DN userDN = userEntry.getDN(); 658 if (memberDNs.contains(userDN)) 659 { 660 Message message = ERR_STATICGROUP_ADD_MEMBER_ALREADY_EXISTS.get( 661 String.valueOf(userDN), String.valueOf(groupEntryDN)); 662 throw new DirectoryException(ResultCode.ATTRIBUTE_OR_VALUE_EXISTS, 663 message); 664 } 665 666 LinkedHashSet<AttributeValue> values = 667 new LinkedHashSet<AttributeValue>(1); 668 values.add(new AttributeValue(memberAttributeType, userDN.toString())); 669 670 Attribute attr = new Attribute(memberAttributeType, 671 memberAttributeType.getNameOrOID(), 672 values); 673 674 LinkedList<Modification> mods = new LinkedList<Modification>(); 675 mods.add(new Modification(ModificationType.ADD, attr)); 676 677 LinkedList<Control> requestControls = new LinkedList<Control>(); 678 requestControls.add(new Control(OID_INTERNAL_GROUP_MEMBERSHIP_UPDATE, 679 false)); 680 681 InternalClientConnection conn = 682 InternalClientConnection.getRootConnection(); 683 ModifyOperationBasis modifyOperation = 684 new ModifyOperationBasis(conn, conn.nextOperationID(), 685 conn.nextMessageID(), requestControls, 686 groupEntryDN, mods); 687 modifyOperation.run(); 688 if (modifyOperation.getResultCode() != ResultCode.SUCCESS) 689 { 690 Message message = ERR_STATICGROUP_ADD_MEMBER_UPDATE_FAILED. 691 get(String.valueOf(userDN), String.valueOf(groupEntryDN), 692 modifyOperation.getErrorMessage().toString()); 693 throw new DirectoryException(modifyOperation.getResultCode(), message); 694 } 695 696 697 LinkedHashSet<DN> newMemberDNs = 698 new LinkedHashSet<DN>(memberDNs.size()+1); 699 newMemberDNs.addAll(memberDNs); 700 newMemberDNs.add(userDN); 701 memberDNs = newMemberDNs; 702 } 703 } 704 705 706 707 /** 708 * {@inheritDoc} 709 */ 710 @Override() 711 public void removeMember(DN userDN) 712 throws UnsupportedOperationException, DirectoryException 713 { 714 ensureNotNull(userDN); 715 716 synchronized (this) 717 { 718 if (! memberDNs.contains(userDN)) 719 { 720 Message message = ERR_STATICGROUP_REMOVE_MEMBER_NO_SUCH_MEMBER.get( 721 String.valueOf(userDN), String.valueOf(groupEntryDN)); 722 throw new DirectoryException(ResultCode.NO_SUCH_ATTRIBUTE, message); 723 } 724 725 726 LinkedHashSet<AttributeValue> values = 727 new LinkedHashSet<AttributeValue>(1); 728 values.add(new AttributeValue(memberAttributeType, userDN.toString())); 729 730 Attribute attr = new Attribute(memberAttributeType, 731 memberAttributeType.getNameOrOID(), 732 values); 733 734 LinkedList<Modification> mods = new LinkedList<Modification>(); 735 mods.add(new Modification(ModificationType.DELETE, attr)); 736 737 LinkedList<Control> requestControls = new LinkedList<Control>(); 738 requestControls.add(new Control(OID_INTERNAL_GROUP_MEMBERSHIP_UPDATE, 739 false)); 740 741 InternalClientConnection conn = 742 InternalClientConnection.getRootConnection(); 743 ModifyOperationBasis modifyOperation = 744 new ModifyOperationBasis(conn, conn.nextOperationID(), 745 conn.nextMessageID(), requestControls, 746 groupEntryDN, mods); 747 modifyOperation.run(); 748 if (modifyOperation.getResultCode() != ResultCode.SUCCESS) 749 { 750 Message message = ERR_STATICGROUP_REMOVE_MEMBER_UPDATE_FAILED. 751 get(String.valueOf(userDN), String.valueOf(groupEntryDN), 752 modifyOperation.getErrorMessage().toString()); 753 throw new DirectoryException(modifyOperation.getResultCode(), message); 754 } 755 756 757 LinkedHashSet<DN> newMemberDNs = new LinkedHashSet<DN>(memberDNs); 758 newMemberDNs.remove(userDN); 759 memberDNs = newMemberDNs; 760 //If it is in the nested group list remove it. 761 if(nestedGroups.contains(userDN)) { 762 LinkedList<DN> newNestedGroups = new LinkedList<DN>(nestedGroups); 763 newNestedGroups.remove(userDN); 764 nestedGroups = newNestedGroups; 765 } 766 } 767 } 768 769 770 771 /** 772 * {@inheritDoc} 773 */ 774 @Override() 775 public void toString(StringBuilder buffer) 776 { 777 buffer.append("StaticGroup("); 778 buffer.append(groupEntryDN); 779 buffer.append(")"); 780 } 781 } 782