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