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.admin.client.cli;
028    
029    import static org.opends.messages.AdminMessages.*;
030    import static org.opends.messages.ToolMessages.*;
031    import static org.opends.server.tools.ToolConstants.*;
032    
033    import java.io.IOException;
034    import java.io.OutputStream;
035    import java.util.ArrayList;
036    import java.util.HashMap;
037    import java.util.HashSet;
038    import java.util.List;
039    import java.util.Map;
040    import java.util.Set;
041    
042    import javax.naming.NamingException;
043    import javax.naming.ldap.InitialLdapContext;
044    import javax.naming.ldap.Rdn;
045    
046    
047    import org.opends.admin.ads.ADSContext;
048    import org.opends.admin.ads.ADSContextException;
049    import org.opends.admin.ads.ADSContext.ServerGroupProperty;
050    import org.opends.admin.ads.ADSContext.ServerProperty;
051    import org.opends.admin.ads.ADSContextException.ErrorType;
052    import org.opends.server.util.args.ArgumentException;
053    import org.opends.server.util.args.BooleanArgument;
054    import org.opends.server.util.args.StringArgument;
055    import org.opends.server.util.args.SubCommand;
056    
057    import static org.opends.server.admin.client.cli.DsFrameworkCliReturnCode.*;
058    /**
059     * This class is handling server group CLI.
060     */
061    public class DsFrameworkCliServerGroup implements DsFrameworkCliSubCommandGroup
062    {
063    
064      /**
065       * End Of Line.
066       */
067      private String EOL = System.getProperty("line.separator");
068    
069      /**
070       * The subcommand Parser.
071       */
072      DsFrameworkCliParser argParser ;
073    
074      /**
075       * The verbose argument.
076       */
077      BooleanArgument verboseArg ;
078    
079      /**
080       * The enumeration containing the different subCommand names.
081       */
082      private enum SubCommandNameEnum
083      {
084        /**
085         * The create-group subcommand.
086         */
087        CREATE_GROUP("create-group"),
088    
089        /**
090         * The delete-group subcommand.
091         */
092        DELETE_GROUP("delete-group"),
093    
094        /**
095         * The modify-group subcommand.
096         */
097        MODIFY_GROUP("modify-group"),
098    
099        /**
100         * The list-groups subcommand.
101         */
102        LIST_GROUPS("list-groups"),
103    
104        /**
105         * The list-members subcommand.
106         */
107        LIST_MEMBERS("list-members"),
108    
109        /**
110         * The list-membership subcommand.
111         */
112        LIST_MEMBERSHIP("list-membership"),
113    
114        /**
115         * The add-to-group subcommand.
116         */
117        ADD_TO_GROUP("add-to-group"),
118    
119        /**
120         * The remove-from-group subcommand.
121         */
122        REMOVE_FROM_GROUP("remove-from-group");
123    
124        // String representation of the value.
125        private final String name;
126    
127        // Private constructor.
128        private SubCommandNameEnum(String name)
129        {
130          this.name = name;
131        }
132    
133        /**
134         * {@inheritDoc}
135         */
136        public String toString()
137        {
138          return name;
139        }
140    
141        // A lookup table for resolving a unit from its name.
142        private static final List<String> nameToSubCmdName ;
143        static
144        {
145          nameToSubCmdName = new ArrayList<String>();
146    
147          for (SubCommandNameEnum subCmd : SubCommandNameEnum.values())
148          {
149            nameToSubCmdName.add(subCmd.toString());
150          }
151        }
152        public static boolean  isSubCommand(String name)
153        {
154          return nameToSubCmdName.contains(name);
155        }
156      }
157    
158      /**
159       * The 'create-group' subcommand.
160       */
161      public SubCommand createGroupSubCmd;
162    
163      /**
164       * The 'description' argument of the 'create-group' subcommand.
165       */
166      private StringArgument createGroupDescriptionArg;
167    
168      /**
169       * The 'group-name' argument of the 'create-group' subcommand.
170       */
171      private StringArgument createGroupGroupNameArg;
172    
173      /**
174       * The 'modify-group' subcommand.
175       */
176      private SubCommand modifyGroupSubCmd;
177    
178      /**
179       * The 'description' argument of the 'modify-group' subcommand.
180       */
181      private StringArgument modifyGroupDescriptionArg;
182    
183      /**
184       * The 'group-id' argument of the 'modify-group' subcommand.
185       */
186      private StringArgument modifyGroupGroupIdArg;
187    
188      /**
189       * The 'group-name' argument of the 'modify-group' subcommand.
190       */
191      private StringArgument modifyGroupGroupNameArg;
192    
193      /**
194       * The 'delete-group' subcommand.
195       */
196      private SubCommand deleteGroupSubCmd;
197    
198      /**
199       * The 'group-name' argument of the 'delete-group' subcommand.
200       */
201      private StringArgument deleteGroupGroupNameArg;
202    
203      /**
204       * The 'list-group' subcommand.
205       */
206      private SubCommand listGroupSubCmd;
207    
208      /**
209       * The 'add-to-group' subcommand.
210       */
211      private SubCommand addToGroupSubCmd;
212    
213      /**
214       * The 'group-name' argument of the 'add-to-group' subcommand.
215       */
216      private StringArgument addToGroupGroupNameArg;
217    
218      /**
219       * The 'member-id' argument of the 'add-to-group' subcommand.
220       */
221      private StringArgument addToGoupMemberNameArg;
222    
223      /**
224       * The 'remove-from-group' subcommand.
225       */
226      private SubCommand removeFromGroupSubCmd;
227    
228      /**
229       * The 'group-name' argument of the 'remove-from-group' subcommand.
230       */
231      private StringArgument removeFromGroupGroupNameArg;
232    
233      /**
234       * The 'member-id' argument of the 'remove-from-group' subcommand.
235       */
236      private StringArgument removeFromGoupMemberNameArg;
237    
238      /**
239       * The 'list-members' subcommand.
240       */
241      private SubCommand listMembersSubCmd;
242    
243      /**
244       * The 'group-name' argument of the 'list-members' subcommand.
245       */
246      private StringArgument listMembersGroupNameArg;
247    
248      /**
249       * The 'list-membership' subcommand.
250       */
251      private SubCommand listMembershipSubCmd;
252    
253      /**
254       * The 'member-name' argument of the 'list-membership' subcommand.
255       */
256      private StringArgument listMembershipMemberNameArg;
257    
258    
259      /**
260       * Association between ADSContext enum and display field.
261       */
262      private HashMap<ServerGroupProperty, String> attributeDisplayName;
263    
264      /**
265       * The subcommand list.
266       */
267      private HashSet<SubCommand> subCommands = new HashSet<SubCommand>();
268    
269      /**
270       * Indicates whether this subCommand should be hidden in the usage
271       * information.
272       */
273      private boolean isHidden;
274    
275      /**
276       * The subcommand group name.
277       */
278      private String groupName;
279    
280      /**
281       * Get the display attribute name for a given attribute.
282       * @param prop The server property
283       * @return the display attribute name for a given attribute
284       */
285      public String getAttributeDisplayName(ServerGroupProperty prop)
286      {
287        return attributeDisplayName.get(prop);
288      }
289    
290      /**
291       * {@inheritDoc}
292       */
293      public Set<SubCommand> getSubCommands()
294      {
295        return subCommands;
296      }
297    
298      /**
299       * {@inheritDoc}
300       */
301      public boolean isHidden()
302      {
303        return isHidden;
304      }
305    
306      /**
307       * {@inheritDoc}
308       */
309      public String getGroupName()
310      {
311        return groupName ;
312      }
313    
314      /**
315       * {@inheritDoc}
316       */
317      public void initializeCliGroup(DsFrameworkCliParser argParser,
318          BooleanArgument verboseArg)
319          throws ArgumentException
320      {
321        this.verboseArg = verboseArg ;
322        isHidden = false ;
323        groupName = "server-group";
324        this.argParser = argParser;
325    
326    
327        // Create-group subcommand
328        createGroupSubCmd = new SubCommand(argParser,
329            SubCommandNameEnum.CREATE_GROUP.toString(),
330            INFO_ADMIN_SUBCMD_CREATE_GROUP_DESCRIPTION.get());
331        subCommands.add(createGroupSubCmd);
332    
333        createGroupDescriptionArg = new StringArgument("description",
334            OPTION_SHORT_DESCRIPTION, OPTION_LONG_DESCRIPTION, false, false,
335            true, INFO_DESCRIPTION_PLACEHOLDER.get(), "", null,
336            INFO_ADMIN_ARG_DESCRIPTION_DESCRIPTION.get());
337        createGroupSubCmd.addArgument(createGroupDescriptionArg);
338    
339        createGroupGroupNameArg = new StringArgument("groupName",
340            OPTION_SHORT_GROUPNAME, OPTION_LONG_GROUPNAME, true, true,
341            INFO_GROUPNAME_PLACEHOLDER.get(),
342            INFO_ADMIN_ARG_CREATE_GROUP_GROUPNAME_DESCRIPTION.get());
343        createGroupSubCmd.addArgument(createGroupGroupNameArg);
344    
345        // modify-group
346        modifyGroupSubCmd = new SubCommand(argParser,
347            SubCommandNameEnum.MODIFY_GROUP.toString(),
348            INFO_ADMIN_SUBCMD_MODIFY_GROUP_DESCRIPTION.get());
349        subCommands.add(modifyGroupSubCmd);
350    
351        modifyGroupDescriptionArg = new StringArgument("new-description",
352            OPTION_SHORT_DESCRIPTION, OPTION_LONG_DESCRIPTION, false, false,
353            true, INFO_DESCRIPTION_PLACEHOLDER.get(), "", null,
354            INFO_ADMIN_ARG_NEW_DESCRIPTION_DESCRIPTION.get());
355        modifyGroupSubCmd.addArgument(modifyGroupDescriptionArg);
356    
357        modifyGroupGroupIdArg = new StringArgument("new-groupName",
358            OPTION_SHORT_NEWGROUPNAME, OPTION_LONG_NEWGROUPNAME, false, false, true,
359            INFO_GROUPNAME_PLACEHOLDER.get(), "", null,
360            INFO_ADMIN_ARG_NEW_GROUPNAME_DESCRIPTION.get());
361        modifyGroupSubCmd.addArgument(modifyGroupGroupIdArg);
362    
363        modifyGroupGroupNameArg = new StringArgument("groupName",
364            OPTION_SHORT_GROUPNAME, OPTION_LONG_GROUPNAME, true, true,
365            INFO_GROUPNAME_PLACEHOLDER.get(),
366            INFO_ADMIN_ARG_GROUPNAME_DESCRIPTION.get());
367        modifyGroupSubCmd.addArgument(modifyGroupGroupNameArg);
368    
369        // delete-group
370        deleteGroupSubCmd = new SubCommand(argParser,SubCommandNameEnum.DELETE_GROUP
371            .toString(), INFO_ADMIN_SUBCMD_DELETE_GROUP_DESCRIPTION.get());
372        subCommands.add(deleteGroupSubCmd);
373    
374        deleteGroupGroupNameArg = new StringArgument("groupName",
375            OPTION_SHORT_GROUPNAME, OPTION_LONG_GROUPNAME, true, true,
376            INFO_GROUPNAME_PLACEHOLDER.get(),
377            INFO_ADMIN_ARG_GROUPNAME_DESCRIPTION.get());
378        deleteGroupSubCmd.addArgument(deleteGroupGroupNameArg);
379    
380        // list-groups
381        listGroupSubCmd = new SubCommand(argParser, "list-groups",
382            INFO_ADMIN_SUBCMD_LIST_GROUPS_DESCRIPTION.get());
383        subCommands.add(listGroupSubCmd);
384    
385        // add-to-group
386        addToGroupSubCmd = new SubCommand(argParser,
387            SubCommandNameEnum.ADD_TO_GROUP.toString(),
388            INFO_ADMIN_SUBCMD_ADD_TO_GROUP_DESCRIPTION.get());
389        subCommands.add(addToGroupSubCmd);
390    
391        addToGoupMemberNameArg = new StringArgument("memberName",
392            OPTION_SHORT_MEMBERNAME, OPTION_LONG_MEMBERNAME, true, true,
393            INFO_MEMBERNAME_PLACEHOLDER.get(),
394            INFO_ADMIN_ARG_ADD_MEMBERNAME_DESCRIPTION.get());
395        addToGroupSubCmd.addArgument(addToGoupMemberNameArg);
396    
397        addToGroupGroupNameArg = new StringArgument("groupName",
398            OPTION_SHORT_GROUPNAME, OPTION_LONG_GROUPNAME, true, true,
399            INFO_GROUPNAME_PLACEHOLDER.get(),
400            INFO_ADMIN_ARG_GROUPNAME_DESCRIPTION.get());
401        addToGroupSubCmd.addArgument(addToGroupGroupNameArg);
402    
403        // remove-from-group
404        removeFromGroupSubCmd = new SubCommand(argParser,
405            SubCommandNameEnum.REMOVE_FROM_GROUP.toString(),
406            INFO_ADMIN_SUBCMD_REMOVE_FROM_GROUP_DESCRIPTION.get());
407        subCommands.add(removeFromGroupSubCmd);
408    
409        removeFromGoupMemberNameArg = new StringArgument("memberName",
410            OPTION_SHORT_MEMBERNAME, OPTION_LONG_MEMBERNAME, true, true,
411            INFO_MEMBERNAME_PLACEHOLDER.get(),
412            INFO_ADMIN_ARG_REMOVE_MEMBERNAME_DESCRIPTION.get());
413        removeFromGroupSubCmd.addArgument(removeFromGoupMemberNameArg);
414    
415        removeFromGroupGroupNameArg = new StringArgument("groupName",
416            OPTION_SHORT_GROUPNAME, OPTION_LONG_GROUPNAME, true, true,
417            INFO_GROUPNAME_PLACEHOLDER.get(),
418            INFO_ADMIN_ARG_GROUPNAME_DESCRIPTION.get());
419        removeFromGroupSubCmd.addArgument(removeFromGroupGroupNameArg);
420    
421    
422        // list-members
423        listMembersSubCmd = new SubCommand(argParser,SubCommandNameEnum.LIST_MEMBERS
424            .toString(), INFO_ADMIN_SUBCMD_LIST_MEMBERS_DESCRIPTION.get());
425        subCommands.add(listMembersSubCmd);
426    
427        listMembersGroupNameArg = new StringArgument("groupName",
428            OPTION_SHORT_GROUPNAME, OPTION_LONG_GROUPNAME, true, true,
429            INFO_GROUPNAME_PLACEHOLDER.get(),
430            INFO_ADMIN_ARG_GROUPNAME_DESCRIPTION.get());
431        listMembersSubCmd.addArgument(listMembersGroupNameArg);
432    
433        // list-membership
434        listMembershipSubCmd = new SubCommand(argParser,
435            SubCommandNameEnum.LIST_MEMBERSHIP.toString(),
436            INFO_ADMIN_SUBCMD_LIST_MEMBERSHIP_DESCRIPTION.get());
437        subCommands.add(listMembershipSubCmd);
438    
439        listMembershipMemberNameArg = new StringArgument("memberName",
440            OPTION_SHORT_MEMBERNAME, OPTION_LONG_MEMBERNAME, true, true,
441            INFO_MEMBERNAME_PLACEHOLDER.get(),
442            INFO_ADMIN_ARG_MEMBERNAME_DESCRIPTION.get());
443        listMembershipSubCmd.addArgument(listMembershipMemberNameArg);
444    
445        // Create association between ADSContext enum and display field
446        attributeDisplayName = new HashMap<ServerGroupProperty, String>();
447        attributeDisplayName.put(ServerGroupProperty.UID, OPTION_LONG_GROUPNAME);
448        attributeDisplayName.put(ServerGroupProperty.DESCRIPTION,
449            OPTION_LONG_DESCRIPTION);
450        attributeDisplayName.put(ServerGroupProperty.MEMBERS,
451            OPTION_LONG_MEMBERNAME);
452      }
453    
454      /**
455       * {@inheritDoc}
456       */
457      public boolean isSubCommand(SubCommand subCmd)
458      {
459          return SubCommandNameEnum.isSubCommand(subCmd.getName());
460      }
461    
462    
463      /**
464       * {@inheritDoc}
465       */
466      public DsFrameworkCliReturnCode performSubCommand(SubCommand subCmd,
467          OutputStream outStream, OutputStream errStream)
468          throws ADSContextException, ArgumentException
469      {
470        ADSContext adsCtx = null ;
471        InitialLdapContext ctx = null ;
472    
473        DsFrameworkCliReturnCode returnCode = ERROR_UNEXPECTED;
474        try
475        {
476          // -----------------------
477          // create-group subcommand
478          // -----------------------
479          if (subCmd.getName().equals(createGroupSubCmd.getName()))
480          {
481            String groupId = createGroupGroupNameArg.getValue();
482            HashMap<ServerGroupProperty, Object> serverGroupProperties =
483              new HashMap<ServerGroupProperty, Object>();
484    
485            // get the GROUP_NAME
486            serverGroupProperties.put(ServerGroupProperty.UID, groupId);
487    
488            // get the Description
489            if (createGroupDescriptionArg.isPresent())
490            {
491              serverGroupProperties.put(ServerGroupProperty.DESCRIPTION,
492                  createGroupDescriptionArg.getValue());
493            }
494    
495            // Create the group
496            ctx = argParser.getContext(outStream, errStream);
497            if (ctx == null)
498            {
499              return CANNOT_CONNECT_TO_ADS;
500            }
501            adsCtx = new ADSContext(ctx) ;
502            adsCtx.createServerGroup(serverGroupProperties);
503            returnCode = SUCCESSFUL;
504          }
505          // -----------------------
506          // delete-group subcommand
507          // -----------------------
508          else if (subCmd.getName().equals(deleteGroupSubCmd.getName()))
509          {
510            returnCode = SUCCESSFUL;
511            String groupId = deleteGroupGroupNameArg.getValue();
512            if (groupId.equals(ADSContext.ALL_SERVERGROUP_NAME))
513            {
514              return ACCESS_PERMISSION ;
515            }
516            HashMap<ServerGroupProperty, Object> serverGroupProperties =
517              new HashMap<ServerGroupProperty, Object>();
518    
519            // Get ADS context
520            ctx = argParser.getContext(outStream, errStream);
521            if (ctx == null)
522            {
523              return CANNOT_CONNECT_TO_ADS;
524            }
525            adsCtx = new ADSContext(ctx) ;
526    
527            // update server Property "GROUPS"
528            Set<String> serverList = adsCtx.getServerGroupMemberList(groupId);
529            for (String serverId : serverList)
530            {
531              // serverId contains "cn=" string, just remove it.
532              removeServerFromGroup(adsCtx, groupId,serverId.substring(3));
533            }
534    
535            // Delete the group
536            serverGroupProperties.put(ServerGroupProperty.UID, groupId);
537            adsCtx.deleteServerGroup(serverGroupProperties);
538          }
539          // -----------------------
540          // list-groups subcommand
541          // -----------------------
542          else if (subCmd.getName().equals(listGroupSubCmd.getName()))
543          {
544            ctx = argParser.getContext(outStream, errStream);
545            if (ctx == null)
546            {
547              return CANNOT_CONNECT_TO_ADS;
548            }
549            adsCtx = new ADSContext(ctx) ;
550    
551            Set<Map<ServerGroupProperty, Object>> result = adsCtx
552                .readServerGroupRegistry();
553            StringBuilder buffer = new StringBuilder();
554    
555            // if not verbose mode, print group name (1 per line)
556            if (! verboseArg.isPresent())
557            {
558              for (Map<ServerGroupProperty, Object> groupProps : result)
559              {
560                // Get the group name
561                buffer.append(groupProps.get(ServerGroupProperty.UID));
562                buffer.append(EOL);
563              }
564            }
565            else
566            {
567              // Look for the max group identifier length
568              int uidLength = 0 ;
569              for (ServerGroupProperty sgp : ServerGroupProperty.values())
570              {
571                int cur = attributeDisplayName.get(sgp).toString().length();
572                if (cur > uidLength)
573                {
574                  uidLength = cur;
575                }
576              }
577              uidLength++;
578    
579              for (Map<ServerGroupProperty, Object> groupProps : result)
580              {
581                // Get the group name
582                buffer.append(attributeDisplayName.get(ServerGroupProperty.UID));
583                // add space
584                int curLen = attributeDisplayName.get(ServerGroupProperty.UID)
585                    .length();
586                for (int i = curLen; i < uidLength; i++)
587                {
588                  buffer.append(" ");
589                }
590                buffer.append(": ");
591                buffer.append(groupProps.get(ServerGroupProperty.UID));
592                buffer.append(EOL);
593    
594                // Write other props
595                for (ServerGroupProperty propName : ServerGroupProperty.values())
596                {
597                  if (propName.compareTo(ServerGroupProperty.UID) == 0)
598                  {
599                    // We have already displayed the group Id
600                    continue;
601                  }
602                  buffer.append(attributeDisplayName.get(propName));
603                  // add space
604                  curLen = attributeDisplayName.get(propName).length();
605                  for (int i = curLen; i < uidLength; i++)
606                  {
607                    buffer.append(" ");
608                  }
609                  buffer.append(": ");
610    
611                  if (propName.compareTo(ServerGroupProperty.MEMBERS) == 0)
612                  {
613                    Set atts = (Set) groupProps.get(propName);
614                    if (atts != null)
615                    {
616                      boolean indent = false;
617                      for (Object att : atts)
618                      {
619                        if (indent)
620                        {
621                          buffer.append(EOL);
622                          for (int i = 0; i < uidLength + 2; i++)
623                          {
624                            buffer.append(" ");
625                          }
626                        }
627                        else
628                        {
629                          indent = true;
630                        }
631                        buffer.append(att.toString().substring(3));
632                      }
633                    }
634                  }
635                  else
636                  {
637                    if (groupProps.get(propName) != null)
638                    {
639                      buffer.append(groupProps.get(propName));
640                    }
641                  }
642                  buffer.append(EOL);
643                }
644                buffer.append(EOL);
645              }
646            }
647            try
648            {
649              outStream.write(buffer.toString().getBytes());
650            }
651            catch (IOException e)
652            {
653            }
654            returnCode = SUCCESSFUL;
655          }
656          // -----------------------
657          // modify-group subcommand
658          // -----------------------
659          else if (subCmd.getName().equals(modifyGroupSubCmd.getName()))
660          {
661            String groupId = modifyGroupGroupNameArg.getValue();
662            HashMap<ServerGroupProperty, Object> serverGroupProperties =
663              new HashMap<ServerGroupProperty, Object>();
664            HashSet<ServerGroupProperty> serverGroupPropertiesToRemove =
665              new HashSet<ServerGroupProperty>();
666    
667            Boolean updateRequired = false;
668            Boolean removeRequired = false;
669            // get the GROUP_ID
670            if (modifyGroupGroupIdArg.isPresent())
671            {
672              // rename the entry !
673              serverGroupProperties.put(ServerGroupProperty.UID,
674                  modifyGroupGroupIdArg.getValue());
675              updateRequired = true;
676            }
677            else
678            {
679              serverGroupProperties.put(ServerGroupProperty.UID, groupId) ;
680            }
681    
682    
683            // get the Description
684            if (modifyGroupDescriptionArg.isPresent())
685            {
686              String newDesc = modifyGroupDescriptionArg.getValue();
687              if (newDesc.length() == 0)
688              {
689                serverGroupPropertiesToRemove.add(ServerGroupProperty.DESCRIPTION);
690                removeRequired = true;
691              }
692              else
693              {
694                serverGroupProperties.put(ServerGroupProperty.DESCRIPTION,
695                    modifyGroupDescriptionArg.getValue());
696                updateRequired = true;
697              }
698            }
699    
700    
701            // Update the server group
702            if ( ! (updateRequired || removeRequired ) )
703            {
704              returnCode = SUCCESSFUL_NOP;
705            }
706    
707            // We need to perform an update
708            ctx = argParser.getContext(outStream, errStream);
709            if (ctx == null)
710            {
711              return CANNOT_CONNECT_TO_ADS;
712            }
713            adsCtx = new ADSContext(ctx) ;
714    
715            if (updateRequired)
716            {
717              adsCtx.updateServerGroup(groupId, serverGroupProperties);
718            }
719            if (removeRequired)
720            {
721              adsCtx.removeServerGroupProp(groupId,
722                  serverGroupPropertiesToRemove);
723            }
724    
725            returnCode = SUCCESSFUL;
726          }
727          // -----------------------
728          // add-to-group subcommand
729          // -----------------------
730          else if (subCmd.getName().equals(addToGroupSubCmd.getName()))
731          {
732            String groupId = addToGroupGroupNameArg.getValue();
733    
734            ctx = argParser.getContext(outStream, errStream);
735            if (ctx == null)
736            {
737              return CANNOT_CONNECT_TO_ADS;
738            }
739            adsCtx = new ADSContext(ctx) ;
740    
741            // Check if the server is registered inside to ADS
742            Set<Map<ServerProperty, Object>> serverList = adsCtx
743                .readServerRegistry();
744            boolean found = false ;
745            Map<ServerProperty, Object> foundServerProperties = null ;
746            for (Map<ServerProperty, Object> serverProperties : serverList)
747            {
748              String serverId = ADSContext
749                  .getServerIdFromServerProperties(serverProperties);
750              if (addToGoupMemberNameArg.getValue().equals(serverId))
751              {
752                found = true;
753                foundServerProperties = serverProperties ;
754                break;
755              }
756            }
757            if ( !found )
758            {
759              throw new ADSContextException (ErrorType.NOT_YET_REGISTERED) ;
760            }
761    
762            // Add the server inside the group
763            returnCode = addServerTogroup(adsCtx, groupId, foundServerProperties);
764          }
765          // -----------------------
766          // remove-from-group subcommand
767          // -----------------------
768          else if (subCmd.getName().equals(removeFromGroupSubCmd.getName()))
769          {
770            ctx = argParser.getContext(outStream, errStream);
771            if (ctx == null)
772            {
773              return CANNOT_CONNECT_TO_ADS;
774            }
775            adsCtx = new ADSContext(ctx) ;
776    
777            returnCode = removeServerFromGroup(adsCtx,
778                removeFromGroupGroupNameArg.getValue(),
779                removeFromGoupMemberNameArg.getValue());
780          }
781          // -----------------------
782          // list-members subcommand
783          // -----------------------
784          else if (subCmd.getName().equals(listMembersSubCmd.getName()))
785          {
786            String groupId = listMembersGroupNameArg.getValue();
787    
788            ctx = argParser.getContext(outStream, errStream);
789            if (ctx == null)
790            {
791              return CANNOT_CONNECT_TO_ADS;
792            }
793            adsCtx = new ADSContext(ctx) ;
794    
795            // get the current member list
796            Set<String> memberList = adsCtx.getServerGroupMemberList(groupId);
797            if (memberList == null)
798            {
799              returnCode = SUCCESSFUL;
800            }
801            StringBuilder buffer = new StringBuilder();
802            for (String member : memberList)
803            {
804              // We shouldn't print out the "cn="
805              buffer.append(member.substring(3));
806              buffer.append(EOL);
807            }
808            try
809            {
810              outStream.write(buffer.toString().getBytes());
811            }
812            catch (IOException e)
813            {
814            }
815    
816            returnCode = SUCCESSFUL;
817          }
818          // -----------------------
819          // list-membership subcommand
820          // -----------------------
821          else if (subCmd.getName().equals(listMembershipSubCmd.getName()))
822          {
823    
824            ctx = argParser.getContext(outStream, errStream);
825            if (ctx == null)
826            {
827              return CANNOT_CONNECT_TO_ADS;
828            }
829            adsCtx = new ADSContext(ctx) ;
830    
831            Set<Map<ServerGroupProperty, Object>> result = adsCtx
832                .readServerGroupRegistry();
833            String MemberId = listMembershipMemberNameArg.getValue();
834    
835            StringBuilder buffer = new StringBuilder();
836            for (Map<ServerGroupProperty, Object> groupProps : result)
837            {
838              // Get the group name;
839              String groupId = groupProps.get(ServerGroupProperty.UID).toString();
840    
841              // look for member list attribute
842              for (ServerGroupProperty propName : groupProps.keySet())
843              {
844                if (propName.compareTo(ServerGroupProperty.MEMBERS) != 0)
845                {
846                  continue;
847                }
848                // Check if the member list contains the member-id
849                Set atts = (Set) groupProps.get(propName);
850                for (Object att : atts)
851                {
852                  if (att.toString().substring(3).toLowerCase().equals(
853                      MemberId.toLowerCase()))
854                  {
855                    buffer.append(groupId);
856                    buffer.append(EOL);
857                    break;
858                  }
859                }
860                break;
861              }
862            }
863            try
864            {
865              outStream.write(buffer.toString().getBytes());
866            }
867            catch (IOException e)
868            {
869            }
870            returnCode = SUCCESSFUL;
871          }
872          else
873          {
874            // Should never occurs: If we are here, it means that the code to
875            // handle to subcommand is not yet written.
876            returnCode = ERROR_UNEXPECTED;
877          }
878        }
879        catch (ADSContextException e)
880        {
881         if (ctx != null)
882         {
883           try
884           {
885             ctx.close();
886           }
887           catch (NamingException x)
888           {
889           }
890         }
891         throw e;
892        }
893    
894        // Close the connection, if needed
895        if (ctx != null)
896        {
897          try
898          {
899            ctx.close();
900          }
901          catch (NamingException x)
902          {
903          }
904        }
905    
906        // return part
907        return returnCode;
908    
909      }
910    
911      /**
912       * Remove a server from a group.
913       *
914       * @param adsCtx
915       *          The ADS context to use.
916       * @param groupId
917       *          The group identifier from which a server has to be
918       *          remove.
919       * @param serverId
920       *          The server identifier to be removed.
921       * @return The return code.
922       * @throws ADSContextException
923       *           If there is a problem with any of the parameters used
924       *           to create this argument.
925       */
926      static DsFrameworkCliReturnCode removeServerFromGroup(ADSContext adsCtx,
927          String groupId, String serverId)
928          throws ADSContextException
929      {
930        DsFrameworkCliReturnCode returnCode = SUCCESSFUL;
931    
932        // get the current group member list
933        Set<String> memberList = adsCtx.getServerGroupMemberList(groupId);
934        if (memberList == null)
935        {
936          returnCode = NOT_YET_REGISTERED;
937        }
938        String memberToRemove = "cn="
939            + Rdn.escapeValue(serverId);
940        if (!memberList.contains(memberToRemove))
941        {
942          returnCode = NOT_YET_REGISTERED;
943        }
944    
945        memberList.remove(memberToRemove);
946        HashMap<ServerGroupProperty, Object> serverGroupProperties =
947          new HashMap<ServerGroupProperty, Object>();
948        serverGroupProperties.put(ServerGroupProperty.MEMBERS, memberList);
949    
950        // Update the server group
951        adsCtx.updateServerGroup(groupId, serverGroupProperties);
952    
953        // Update the server property "GROUPS"
954        Set<Map<ServerProperty,Object>> serverList = adsCtx.readServerRegistry() ;
955        boolean found = false;
956        Map<ServerProperty,Object> serverProperties = null ;
957        for (Map<ServerProperty,Object> elm : serverList)
958        {
959          if (serverId.equals(elm.get(ServerProperty.ID)))
960          {
961            found = true ;
962            serverProperties = elm ;
963            break ;
964          }
965        }
966        if ( ! found )
967        {
968          return SERVER_NOT_REGISTERED ;
969        }
970    
971        Set rawGroupList = (Set) serverProperties.get(ServerProperty.GROUPS);
972        Set<String> groupList = new HashSet<String>();
973        if (rawGroupList != null)
974        {
975          for (Object elm :rawGroupList.toArray() )
976          {
977            if (groupId.equals(elm))
978            {
979              continue ;
980            }
981            groupList.add(elm.toString());
982          }
983        }
984        serverProperties.put(ServerProperty.GROUPS, groupList);
985        adsCtx.updateServer(serverProperties, null);
986    
987        return returnCode;
988      }
989    
990      /**
991       * Add a server inside a group.
992       *
993       * @param adsCtx
994       *          The ADS context to use.
995       * @param groupId
996       *          The group identifier in which a server has to be added.
997       * @param map
998       *          The properties of the server that have to be added to the
999       *          group.
1000       * @return the return code.
1001       * @throws ADSContextException
1002       *           If there is a problem with any of the parameters used
1003       *           to create this argument.
1004       */
1005      static DsFrameworkCliReturnCode addServerTogroup(ADSContext adsCtx,
1006          String groupId, Map<ServerProperty, Object> map)
1007          throws ADSContextException
1008      {
1009        DsFrameworkCliReturnCode returnCode = SUCCESSFUL;
1010        String serverId = (String) map.get(ServerProperty.ID);
1011    
1012        // Add the server inside the group
1013        HashMap<ServerGroupProperty, Object> serverGroupProperties =
1014          new HashMap<ServerGroupProperty, Object>();
1015        Set<String> memberList = adsCtx.getServerGroupMemberList(groupId);
1016        if (memberList == null)
1017        {
1018          memberList = new HashSet<String>();
1019        }
1020        String newMember = "cn="
1021            + Rdn.escapeValue(serverId);
1022        if (memberList.contains(newMember))
1023        {
1024          returnCode = ALREADY_REGISTERED;
1025        }
1026        memberList.add(newMember);
1027        serverGroupProperties.put(ServerGroupProperty.MEMBERS, memberList);
1028    
1029        adsCtx.updateServerGroup(groupId, serverGroupProperties);
1030    
1031    
1032        // Update the server property "GROUPS"
1033        Set rawGroupList = (Set) map.get(ServerProperty.GROUPS);
1034        Set<String> groupList = new HashSet<String>();
1035        if (rawGroupList != null)
1036        {
1037          for (Object elm :rawGroupList.toArray() )
1038          {
1039            groupList.add(elm.toString());
1040          }
1041        }
1042        groupList.add(groupId) ;
1043        map.put(ServerProperty.GROUPS, groupList);
1044        adsCtx.updateServer(map, null);
1045    
1046        return returnCode;
1047      }
1048    }