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    import org.opends.messages.Message;
029    import org.opends.messages.MessageBuilder;
030    
031    import static org.opends.messages.AdminMessages.*;
032    import static org.opends.messages.DSConfigMessages.*;
033    import static org.opends.messages.ToolMessages.*;
034    import static org.opends.server.tools.ToolConstants.*;
035    
036    import java.io.OutputStream;
037    import java.io.PrintStream;
038    import java.util.ArrayList;
039    import java.util.HashMap;
040    import java.util.HashSet;
041    import java.util.LinkedList;
042    import java.util.List;
043    import java.util.Map;
044    import java.util.Set;
045    
046    import javax.naming.NamingException;
047    import javax.naming.ldap.InitialLdapContext;
048    
049    import org.opends.admin.ads.ADSContext;
050    import org.opends.admin.ads.ADSContextException;
051    import org.opends.admin.ads.ADSContext.ServerProperty;
052    import org.opends.admin.ads.ADSContextException.ErrorType;
053    import org.opends.server.tools.dsconfig.ArgumentExceptionFactory;
054    import org.opends.server.util.args.Argument;
055    import org.opends.server.util.args.ArgumentException;
056    import org.opends.server.util.args.BooleanArgument;
057    import org.opends.server.util.args.IntegerArgument;
058    import org.opends.server.util.args.StringArgument;
059    import org.opends.server.util.args.SubCommand;
060    import org.opends.server.util.table.TableBuilder;
061    import org.opends.server.util.table.TextTablePrinter;
062    
063    import static org.opends.server.admin.client.cli.DsFrameworkCliReturnCode.*;
064    /**
065     * This class is handling server group CLI.
066     */
067    public class DsFrameworkCliServer implements DsFrameworkCliSubCommandGroup
068    {
069      // Strings used in property help.
070      private final static Message DESCRIPTION_OPTIONS_TITLE =
071        INFO_DSCFG_HELP_DESCRIPTION_OPTION.get();
072    
073      private final static Message DESCRIPTION_OPTIONS_READ =
074        INFO_DSCFG_HELP_DESCRIPTION_READ.get();
075    
076      private final static Message DESCRIPTION_OPTIONS_WRITE =
077        INFO_DSCFG_HELP_DESCRIPTION_WRITE.get();
078    
079      private final static Message DESCRIPTION_OPTIONS_MANDATORY =
080        INFO_DSCFG_HELP_DESCRIPTION_MANDATORY.get();
081    
082      private final static Message DESCRIPTION_OPTIONS_SINGLE =
083        INFO_DSCFG_HELP_DESCRIPTION_SINGLE_VALUED.get();
084    
085      /**
086       * The subcommand Parser.
087       */
088      private DsFrameworkCliParser argParser;
089    
090      /**
091       * The verbose argument.
092       */
093      private BooleanArgument verboseArg;
094    
095      /**
096       * The enumeration containing the different subCommand names.
097       */
098      private enum SubCommandNameEnum
099      {
100        /**
101         * The register-server subcommand.
102         */
103        REGISTER_SERVER("register-server"),
104    
105        /**
106         * The unregister-server subcommand.
107         */
108        UNREGISTER_SERVER("unregister-server"),
109    
110        /**
111         * The list-servers subcommand.
112         */
113        LIST_SERVERS("list-servers"),
114    
115        /**
116         * The get-server-properties subcommand.
117         */
118        GET_SERVER_PROPERTIES("get-server-properties"),
119    
120        /**
121         * The set-server-properties subcommand.
122         */
123        SET_SERVER_PROPERTIES("set-server-properties"),
124    
125        /**
126         * The list-servers subcommand.
127         */
128        LIST_SERVER_PROPERTIES("list-server-properties");
129    
130        // String representation of the value.
131        private final String name;
132    
133        // Private constructor.
134        private SubCommandNameEnum(String name)
135        {
136          this.name = name;
137        }
138    
139        /**
140         * {@inheritDoc}
141         */
142        public String toString()
143        {
144          return name;
145        }
146    
147        // A lookup table for resolving a unit from its name.
148        private static final List<String> nameToSubCmdName;
149        static
150        {
151          nameToSubCmdName = new ArrayList<String>();
152    
153          for (SubCommandNameEnum subCmd : SubCommandNameEnum.values())
154          {
155            nameToSubCmdName.add(subCmd.toString());
156          }
157        }
158    
159        public static boolean isSubCommand(String name)
160        {
161          return nameToSubCmdName.contains(name);
162        }
163      }
164    
165      /**
166       * The 'register-server' subcommand.
167       */
168      private SubCommand registerServerSubCmd;
169    
170      /**
171       * The 'serverID' argument of the 'register-server' subcommand.
172       */
173      private StringArgument registerServerServerIdArg;
174    
175      /**
176       * The 'serverName' argument of the 'register-server' subcommand.
177       */
178      private StringArgument registerServerSetArg;
179    
180      /**
181       * The 'unregister-server' subcommand.
182       */
183      private SubCommand unregisterServerSubCmd;
184    
185      /**
186       * The 'serverHost' argument of the 'unregister-server' subcommand.
187       */
188      private StringArgument unregisterServerServerIDArg;
189    
190      /**
191       * The 'list-server-properties' subcommand.
192       */
193      private SubCommand listServerPropertiesSubCmd;
194    
195      /**
196       * The 'list-servers' subcommand.
197       */
198      private SubCommand listServersSubCmd;
199    
200      /**
201       * The 'get-server-properties' subcommand.
202       */
203      private SubCommand getServerPropertiesSubCmd;
204    
205      /**
206       * The 'serverID' argument of the 'get-server-properties' subcommand.
207       */
208      private StringArgument getServerPropertiesServerIdArg;
209    
210      /**
211       * The 'set-server-properties' subcommand.
212       */
213      private SubCommand setServerPropertiesSubCmd;
214    
215      /**
216       * The 'serverID' argument of the 'set-server-properties' subcommand.
217       */
218      private StringArgument setServerPropertiesServerIdArg;
219    
220      /**
221       * The 'serverName' argument of the 'set-server-properties' subcommand.
222       */
223      private StringArgument setServerPropertiesSetArg;
224    
225      /**
226       * Association between ADSContext enum and properties.
227       */
228      private HashMap<ServerProperty, Argument> serverProperties;
229    
230      /**
231       * List of read-only server properties.
232       */
233      private HashSet<ServerProperty> readonlyServerProperties;
234    
235      /**
236       * The subcommand list.
237       */
238      private HashSet<SubCommand> subCommands = new HashSet<SubCommand>();
239    
240      /**
241       * Indicates whether this subCommand should be hidden in the usage
242       * information.
243       */
244      private boolean isHidden;
245    
246      /**
247       * The subcommand group name.
248       */
249      private String groupName;
250    
251      /**
252       * {@inheritDoc}
253       */
254      public Set<SubCommand> getSubCommands()
255      {
256        return subCommands;
257      }
258    
259      /**
260       * {@inheritDoc}
261       */
262      public boolean isHidden()
263      {
264        return isHidden;
265      }
266    
267      /**
268       * {@inheritDoc}
269       */
270      public String getGroupName()
271      {
272        return groupName;
273      }
274    
275      /**
276       * {@inheritDoc}
277       */
278      public void initializeCliGroup(DsFrameworkCliParser argParser,
279          BooleanArgument verboseArg) throws ArgumentException
280      {
281        this.verboseArg = verboseArg;
282        isHidden = false;
283        groupName = "server";
284        this.argParser = argParser;
285    
286        // list-server-properties subcommand
287        listServerPropertiesSubCmd = new SubCommand(argParser,
288            SubCommandNameEnum.LIST_SERVER_PROPERTIES.toString(),
289            INFO_ADMIN_SUBCMD_LIST_SERVER_PROPS_DESCRIPTION.get());
290        subCommands.add(listServerPropertiesSubCmd);
291    
292        // register-server subcommand
293        registerServerSubCmd = new SubCommand(argParser,
294            SubCommandNameEnum.REGISTER_SERVER.toString(),
295            INFO_ADMIN_SUBCMD_REGISTER_SERVER_DESCRIPTION.get());
296        subCommands.add(registerServerSubCmd);
297    
298        registerServerServerIdArg = new StringArgument("serverID", null,
299            OPTION_LONG_SERVERID, false, true, INFO_SERVERID_PLACEHOLDER.get(),
300            INFO_ADMIN_ARG_SERVERID_DESCRIPTION.get());
301        registerServerSubCmd.addArgument(registerServerServerIdArg);
302    
303        registerServerSetArg = new StringArgument(OPTION_LONG_SET,
304            OPTION_SHORT_SET, OPTION_LONG_SET, false, true, true,
305            INFO_VALUE_SET_PLACEHOLDER.get(), null, null,
306            INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
307        registerServerSubCmd.addArgument(registerServerSetArg);
308    
309        // unregister-server subcommand
310        unregisterServerSubCmd = new SubCommand(argParser,
311            SubCommandNameEnum.UNREGISTER_SERVER.toString(),
312            INFO_ADMIN_SUBCMD_UNREGISTER_SERVER_DESCRIPTION.get());
313        subCommands.add(unregisterServerSubCmd);
314    
315        unregisterServerServerIDArg = new StringArgument("serverID", null,
316            OPTION_LONG_SERVERID, false, true, INFO_SERVERID_PLACEHOLDER.get(),
317            INFO_ADMIN_ARG_SERVERID_DESCRIPTION.get());
318        unregisterServerSubCmd.addArgument(unregisterServerServerIDArg);
319    
320        // list-servers subcommand
321        listServersSubCmd = new SubCommand(argParser,
322            SubCommandNameEnum.LIST_SERVERS.toString(),
323            INFO_ADMIN_SUBCMD_LIST_SERVERS_DESCRIPTION.get());
324        subCommands.add(listServersSubCmd);
325    
326        // get-server-properties subcommand
327        getServerPropertiesSubCmd = new SubCommand(argParser,
328            SubCommandNameEnum.GET_SERVER_PROPERTIES.toString(),
329            INFO_ADMIN_SUBCMD_GET_SERVER_PROPERTIES_DESCRIPTION.get());
330        subCommands.add(getServerPropertiesSubCmd);
331    
332        getServerPropertiesServerIdArg = new StringArgument("serverID", null,
333            OPTION_LONG_SERVERID, false, true, INFO_SERVERID_PLACEHOLDER.get(),
334            INFO_ADMIN_ARG_SERVERID_DESCRIPTION.get());
335        getServerPropertiesServerIdArg.setMultiValued(true);
336        getServerPropertiesSubCmd.addArgument(getServerPropertiesServerIdArg);
337    
338    
339        // set-server-properties subcommand
340        setServerPropertiesSubCmd = new SubCommand(argParser,
341            SubCommandNameEnum.SET_SERVER_PROPERTIES.toString(),
342            INFO_ADMIN_SUBCMD_SET_SERVER_PROPERTIES_DESCRIPTION.get());
343        subCommands.add(setServerPropertiesSubCmd);
344    
345        setServerPropertiesServerIdArg = new StringArgument("serverID", null,
346            OPTION_LONG_SERVERID, true, true, INFO_SERVERID_PLACEHOLDER.get(),
347            INFO_ADMIN_ARG_SERVERID_DESCRIPTION.get());
348        setServerPropertiesSubCmd.addArgument(setServerPropertiesServerIdArg);
349    
350        setServerPropertiesSetArg = new StringArgument(OPTION_LONG_SET,
351            OPTION_SHORT_SET, OPTION_LONG_SET, false, true, true,
352            INFO_VALUE_SET_PLACEHOLDER.get(), null, null,
353            INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
354        setServerPropertiesSubCmd.addArgument(setServerPropertiesSetArg);
355    
356    
357        // Create association between ADSContext enum and server
358        // properties
359        // Server properties are mapped to Argument.
360        serverProperties = new HashMap<ServerProperty, Argument>();
361        readonlyServerProperties = new HashSet<ServerProperty>();
362    
363        /**
364         * The ID used to identify the server.
365         */
366        {
367          ServerProperty prop = ServerProperty.ID;
368          String attName = prop.getAttributeName();
369          StringArgument arg = new StringArgument(attName, null,
370              prop.getAttributeName(), false, false, true, Message.raw(""), null,
371              null, null);
372          serverProperties.put(prop, arg);
373        }
374    
375        /**
376         * The host name of the server.
377         */
378        {
379          ServerProperty prop = ServerProperty.HOST_NAME;
380          String attName = prop.getAttributeName();
381          readonlyServerProperties.add(prop);
382          StringArgument arg = new StringArgument(attName, null, attName, true,
383              false, true, Message.raw(""), "localhost", null, null);
384          serverProperties.put(prop, arg);
385        }
386    
387        /**
388         * The LDAP port of the server.
389         */
390        {
391          ServerProperty prop = ServerProperty.LDAP_PORT;
392          String attName = prop.getAttributeName();
393          IntegerArgument arg = new IntegerArgument(attName, null, attName, true,
394              true, true, Message.raw(attName), 389, null, null);
395          serverProperties.put(prop, arg);
396        }
397    
398        /**
399         * The JMX port of the server.
400         */
401        {
402          ServerProperty prop = ServerProperty.JMX_PORT;
403          String attName = prop.getAttributeName();
404          IntegerArgument arg = new IntegerArgument(attName, null, attName,
405              false, true, Message.raw(attName), null);
406          arg.setMultiValued(true);
407          serverProperties.put(prop, arg);
408        }
409    
410        /**
411         * The JMX secure port of the server.
412         */
413        {
414          ServerProperty prop = ServerProperty.JMXS_PORT;
415          String attName = prop.getAttributeName();
416          IntegerArgument arg = new IntegerArgument(attName, null, attName,
417              false, true, Message.raw(attName), null);
418          arg.setMultiValued(true);
419          serverProperties.put(prop, arg);
420        }
421    
422        /**
423         * The LDAPS port of the server.
424         */
425        {
426          ServerProperty prop = ServerProperty.LDAPS_PORT;
427          String attName = prop.getAttributeName();
428          IntegerArgument arg = new IntegerArgument(attName, null, attName,
429              false, true, Message.raw(attName), null);
430          arg.setMultiValued(true);
431          serverProperties.put(prop, arg);
432        }
433    
434        /**
435         * The certificate used by the server.
436         */
437        {
438          ServerProperty prop = ServerProperty.CERTIFICATE;
439          String attName = prop.getAttributeName();
440          StringArgument arg = new StringArgument(attName, null, attName, false,
441              false, true, Message.raw(attName), null, null, null);
442          serverProperties.put(prop, arg);
443        }
444    
445        /**
446         * The path where the server is installed.
447         */
448        {
449          ServerProperty prop = ServerProperty.INSTANCE_PATH;
450          String attName = prop.getAttributeName();
451          StringArgument arg = new StringArgument(attName, null, attName, false,
452              false, true, Message.raw(attName), null, null, null);
453          serverProperties.put(prop, arg);
454        }
455    
456        /**
457         * The description of the server.
458         */
459        {
460          ServerProperty prop = ServerProperty.DESCRIPTION;
461          String attName = prop.getAttributeName();
462          StringArgument arg = new StringArgument(attName, null, attName, false,
463              false, true, Message.raw(attName), null, null, null);
464          serverProperties.put(prop, arg);
465        }
466    
467        /**
468         * The OS of the machine where the server is installed.
469         */
470        {
471          ServerProperty prop = ServerProperty.HOST_OS;
472          String attName = prop.getAttributeName();
473          StringArgument arg = new StringArgument(attName, null, attName, false,
474              false, true, Message.raw(attName), null, null, null);
475          serverProperties.put(prop, arg);
476        }
477    
478        /**
479         * Whether LDAP is enabled or not.
480         */
481        {
482          ServerProperty prop = ServerProperty.LDAP_ENABLED;
483          String attName = prop.getAttributeName();
484          BooleanArgument arg = new BooleanArgument(attName, null, attName, null);
485          arg.setDefaultValue("false");
486          serverProperties.put(prop, arg);
487        }
488    
489        /**
490         * Whether LDAPS is enabled or not.
491         */
492        {
493          ServerProperty prop = ServerProperty.LDAPS_ENABLED;
494          String attName = prop.getAttributeName();
495          BooleanArgument arg = new BooleanArgument(attName, null, attName, null);
496          arg.setDefaultValue("false");
497          serverProperties.put(prop, arg);
498        }
499    
500        /**
501         * Whether StartTLS is enabled or not.
502         */
503        {
504          ServerProperty prop = ServerProperty.STARTTLS_ENABLED;
505          String attName = prop.getAttributeName();
506          BooleanArgument arg = new BooleanArgument(attName, null, attName, null);
507          arg.setDefaultValue("false");
508          serverProperties.put(prop, arg);
509        }
510    
511        /**
512         * Whether JMX is enabled or not.
513         */
514        {
515          ServerProperty prop = ServerProperty.JMX_ENABLED;
516          String attName = prop.getAttributeName();
517          BooleanArgument arg = new BooleanArgument(attName, null, attName, null);
518          arg.setDefaultValue("false");
519          serverProperties.put(prop, arg);
520        }
521    
522        /**
523         * Whether JMXS is enabled or not.
524         */
525        {
526          ServerProperty prop = ServerProperty.JMXS_ENABLED;
527          String attName = prop.getAttributeName();
528          BooleanArgument arg = new BooleanArgument(attName, null, attName, null);
529          arg.setDefaultValue("false");
530          serverProperties.put(prop, arg);
531        }
532    
533        /**
534         * The location of the server.
535         */
536        {
537          ServerProperty prop = ServerProperty.LOCATION;
538          String attName = prop.getAttributeName();
539          StringArgument arg = new StringArgument(attName, null, attName, false,
540              false, true, Message.raw(attName), null, null, null);
541          serverProperties.put(prop, arg);
542        }
543    
544        /**
545         * The list of groups in which the server is registered.
546         */
547        {
548          ServerProperty prop = ServerProperty.GROUPS;
549          String attName = prop.getAttributeName();
550          StringArgument arg = new StringArgument(attName, null, attName, false,
551              true, true, Message.raw(attName), null, null, null);
552          arg.setHidden(true);
553          serverProperties.put(prop, arg);
554        }
555    
556       /**
557        * The INSTANCE_KEY_ID used to identify the server key ID.
558        */
559        {
560          ServerProperty prop = ServerProperty.INSTANCE_KEY_ID;
561          String attName = prop.getAttributeName();
562          StringArgument arg = new StringArgument(attName, null, prop
563              .getAttributeName(), false, false, true, Message.raw(""), null, null,
564              null);
565          serverProperties.put(prop, arg);
566        }
567    
568        /**
569         * The INSTANCE_PUBLIC_KEY_CERTIFICATE associated to the server.
570         */
571        {
572          ServerProperty prop = ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE;
573          String attName = prop.getAttributeName();
574          StringArgument arg = new StringArgument(attName, null, prop
575              .getAttributeName(), false, false, true, Message.raw(""), null, null,
576              null);
577          serverProperties.put(prop, arg);
578        }
579      }
580    
581      /**
582       * {@inheritDoc}
583       */
584      public boolean isSubCommand(SubCommand subCmd)
585      {
586        return SubCommandNameEnum.isSubCommand(subCmd.getName());
587      }
588    
589      /**
590       * {@inheritDoc}
591       */
592      public DsFrameworkCliReturnCode performSubCommand(SubCommand subCmd,
593          OutputStream outStream, OutputStream errStream)
594          throws ADSContextException, ArgumentException
595      {
596    
597        ADSContext adsCtx = null;
598        InitialLdapContext ctx = null;
599        DsFrameworkCliReturnCode returnCode = ERROR_UNEXPECTED;
600    
601        try
602        {
603          // -----------------------
604          // register-server subcommand
605          // -----------------------
606          if (subCmd.getName().equals(registerServerSubCmd.getName()))
607          {
608            String serverId ;
609            Map<ServerProperty, Object> map =
610              mapSetOptionsToMap(registerServerSetArg);
611            if (registerServerServerIdArg.isPresent())
612            {
613              serverId = registerServerServerIdArg.getValue();
614            }
615            else
616            {
617              serverId = ADSContext.getServerIdFromServerProperties(map);
618            }
619            map.put(ServerProperty.ID, serverId);
620    
621            ctx = argParser.getContext(outStream, errStream);
622            if (ctx == null)
623            {
624              return CANNOT_CONNECT_TO_ADS;
625            }
626            adsCtx = new ADSContext(ctx);
627            adsCtx.registerServer(map);
628    
629            returnCode = SUCCESSFUL;
630          }
631          else
632          // -----------------------
633          // unregister-server subcommand
634          // -----------------------
635          if (subCmd.getName().equals(unregisterServerSubCmd.getName()))
636          {
637            returnCode = SUCCESSFUL;
638    
639            Map<ServerProperty, Object> map = new HashMap<ServerProperty, Object>();
640            String serverId = null;
641            if (unregisterServerServerIDArg.isPresent())
642            {
643              serverId = unregisterServerServerIDArg.getValue();
644            }
645            else
646            {
647              serverId = ADSContext.getServerIdFromServerProperties(map);
648            }
649            map.put(ServerProperty.ID,serverId);
650    
651            ctx = argParser.getContext(outStream, errStream);
652            if (ctx == null)
653            {
654              return CANNOT_CONNECT_TO_ADS;
655            }
656            adsCtx = new ADSContext(ctx);
657    
658            // update groups in which server was registered
659            Set<Map<ServerProperty, Object>> serverList =
660              adsCtx.readServerRegistry();
661            boolean found = false;
662            for (Map<ServerProperty,Object> elm : serverList)
663            {
664              if (serverId.equals(elm.get(ServerProperty.ID)))
665              {
666                found = true ;
667                break ;
668              }
669            }
670            if ( ! found )
671            {
672              throw new ADSContextException (ErrorType.NOT_YET_REGISTERED) ;
673            }
674    
675            // unregister the server
676            adsCtx.unregisterServer(map);
677          }
678          else
679          // -----------------------
680          // list-servers subcommand
681          // -----------------------
682          if (subCmd.getName().equals(listServersSubCmd.getName()))
683          {
684            ctx = argParser.getContext(outStream, errStream);
685            if (ctx == null)
686            {
687              return CANNOT_CONNECT_TO_ADS;
688            }
689            adsCtx = new ADSContext(ctx);
690            Set<Map<ServerProperty, Object>> serverList = adsCtx
691                .readServerRegistry();
692    
693            PrintStream out = new PrintStream(outStream);
694            for (Map<ServerProperty, Object> server : serverList)
695            {
696              // print out server ID
697              out.println(ServerProperty.ID.getAttributeName() + ": "
698                  + server.get(ServerProperty.ID));
699            }
700            returnCode = SUCCESSFUL;
701          }
702          else
703          // -----------------------
704          // get-server-properties subcommand
705          // -----------------------
706          if (subCmd.getName().equals(getServerPropertiesSubCmd.getName()))
707          {
708            ctx = argParser.getContext(outStream, errStream);
709            if (ctx == null)
710            {
711              return CANNOT_CONNECT_TO_ADS;
712            }
713            adsCtx = new ADSContext(ctx);
714            Set<Map<ServerProperty, Object>> adsServerList = adsCtx
715                .readServerRegistry();
716    
717            LinkedList<String> userServerList = getServerPropertiesServerIdArg
718                .getValues();
719            PrintStream out = new PrintStream(outStream);
720            for (Map<ServerProperty, Object> server : adsServerList)
721            {
722              String serverID = (String) server.get(ServerProperty.ID);
723              if (!userServerList.contains(serverID))
724              {
725                continue;
726              }
727              // print out server ID
728              out.println(ServerProperty.ID.getAttributeName() + ": "
729                  + server.get(ServerProperty.ID));
730              for (ServerProperty sp : server.keySet())
731              {
732                if (sp.equals(ServerProperty.ID))
733                {
734                  continue;
735                }
736                out.println(sp.getAttributeName() + ": " + server.get(sp));
737              }
738              out.println();
739            }
740            returnCode = SUCCESSFUL;
741          }
742          else
743          // -----------------------
744          // set-server-properties subcommand
745          // -----------------------
746          if (subCmd.getName().equals(setServerPropertiesSubCmd.getName()))
747          {
748            Map<ServerProperty, Object> map =
749              mapSetOptionsToMap(setServerPropertiesSetArg);
750    
751            // if the ID is specify in the --set list, it may mean that
752            // the user wants to rename the serverID
753            String newServerId = (String) map.get(ServerProperty.ID) ;
754    
755            // replace the serverID in the map
756            map.put(ServerProperty.ID, setServerPropertiesServerIdArg.getValue());
757    
758            ctx = argParser.getContext(outStream, errStream);
759            if (ctx == null)
760            {
761              return CANNOT_CONNECT_TO_ADS;
762            }
763            adsCtx = new ADSContext(ctx);
764            adsCtx.updateServer(map, newServerId);
765            returnCode = SUCCESSFUL;
766          }
767          else
768          // -----------------------
769          // list-server-properties subcommand
770          // -----------------------
771          if (subCmd.getName().equals(listServerPropertiesSubCmd.getName()))
772          {
773            PrintStream out = new PrintStream(outStream);
774            out.println(DESCRIPTION_OPTIONS_TITLE);
775            out.println();
776            out.print(" r -- ");
777            out.println(DESCRIPTION_OPTIONS_READ);
778            out.print(" w -- ");
779            out.println(DESCRIPTION_OPTIONS_WRITE);
780            out.print(" m -- ");
781            out.println(DESCRIPTION_OPTIONS_MANDATORY);
782            out.print(" s -- ");
783            out.println(DESCRIPTION_OPTIONS_SINGLE);
784            out.println();
785    
786            TableBuilder table = new TableBuilder();
787            table.appendHeading(INFO_DSCFG_HEADING_PROPERTY_NAME.get());
788            table.appendHeading(INFO_DSCFG_HEADING_PROPERTY_OPTIONS.get());
789            table.appendHeading(INFO_DSCFG_HEADING_PROPERTY_SYNTAX.get());
790            table.appendHeading(INFO_CLI_HEADING_PROPERTY_DEFAULT_VALUE.get());
791            for (ServerProperty serverProp : serverProperties.keySet())
792            {
793              if (serverProperties.get(serverProp).isHidden())
794              {
795                continue;
796              }
797              table.startRow();
798              table.appendCell(serverProp.getAttributeName());
799              table.appendCell(getPropertyOptionSummary(serverProperties
800                  .get(serverProp)));
801              table.appendCell(serverProp.getAttributeSyntax());
802              if (serverProperties.get(serverProp).getDefaultValue() != null)
803              {
804                table.appendCell(serverProperties.get(serverProp)
805                    .getDefaultValue());
806              }
807              else
808              {
809                table.appendCell("-");
810              }
811            }
812            TextTablePrinter printer = new TextTablePrinter(outStream);
813            table.print(printer);
814            returnCode = SUCCESSFUL;
815          }
816          else
817          {
818            // Should never occurs: If we are here, it means that the code
819            // to
820            // handle to subcommand is not yet written.
821            returnCode = ERROR_UNEXPECTED;
822          }
823        }
824        catch (ADSContextException e)
825        {
826          if (ctx != null)
827          {
828            try
829            {
830              ctx.close();
831            }
832            catch (NamingException x)
833            {
834            }
835          }
836          throw e;
837        }
838    
839        // Close the connection, if needed
840        if (ctx != null)
841        {
842          try
843          {
844            ctx.close();
845          }
846          catch (NamingException x)
847          {
848          }
849        }
850    
851        // return part
852        return returnCode;
853      }
854    
855      // Compute the options field.
856      private String getPropertyOptionSummary(Argument arg)
857      {
858        StringBuilder b = new StringBuilder();
859    
860        if (readonlyServerProperties.contains(
861            ADSContext.getServerPropFromName(arg.getName())))
862        {
863          b.append("r-"); //$NON-NLS-1$
864        }
865        else
866        {
867          b.append("rw"); //$NON-NLS-1$
868        }
869    
870        if (arg.isRequired())
871        {
872          b.append('m');
873        }
874        else
875        {
876          b.append('-');
877        }
878    
879        if (arg.isMultiValued())
880        {
881          b.append('-');
882        }
883        else
884        {
885          b.append('s');
886        }
887        return b.toString();
888      }
889    
890      /**
891       * Translate a Set properties a to a MAP.
892       *
893       * @param propertySetArgument
894       *          The input set argument.
895       * @return The created map.
896       * @throws ArgumentException
897       *           If error error occurs during set parsing.
898       */
899      private Map<ServerProperty, Object> mapSetOptionsToMap(
900          StringArgument propertySetArgument) throws ArgumentException
901      {
902        HashMap<ServerProperty, Object> map = new HashMap<ServerProperty, Object>();
903        for (String m : propertySetArgument.getValues())
904        {
905          // Parse the property "property:value".
906          int sep = m.indexOf(':');
907    
908          if (sep < 0)
909          {
910            throw ArgumentExceptionFactory.missingSeparatorInPropertyArgument(m);
911          }
912    
913          if (sep == 0)
914          {
915            throw ArgumentExceptionFactory.missingNameInPropertyArgument(m);
916          }
917    
918          String propertyName = m.substring(0, sep);
919          String value = m.substring(sep + 1, m.length());
920          if (value.length() == 0)
921          {
922            throw ArgumentExceptionFactory.missingValueInPropertyArgument(m);
923          }
924    
925          // Check that propName is a known prop.
926          ServerProperty serverProperty = ADSContext
927              .getServerPropFromName(propertyName);
928          if (serverProperty == null)
929          {
930            Message message = ERR_CLI_ERROR_PROPERTY_UNRECOGNIZED.get(propertyName);
931            throw new ArgumentException(message);
932          }
933    
934          // Check that propName is not hidden.
935          if (serverProperties.get(serverProperty).isHidden())
936          {
937            Message message = ERR_CLI_ERROR_PROPERTY_UNRECOGNIZED.get(propertyName);
938            throw new ArgumentException(message);
939          }
940    
941          // Check the property Syntax.
942          MessageBuilder invalidReason = new MessageBuilder();
943          Argument arg = serverProperties.get(serverProperty) ;
944          if ( ! arg.valueIsAcceptable(value, invalidReason))
945          {
946            Message message =
947                ERR_CLI_ERROR_INVALID_PROPERTY_VALUE.get(propertyName, value);
948            throw new ArgumentException(message);
949          }
950          serverProperties.get(serverProperty).addValue(value);
951    
952          // add to the map.
953          map.put(serverProperty, value);
954        }
955    
956        // Check that all mandatory props are set.
957        for (ServerProperty s : ServerProperty.values())
958        {
959          Argument arg = serverProperties.get(s);
960          if (arg.isHidden())
961          {
962            continue;
963          }
964          if (map.containsKey(s))
965          {
966            continue ;
967          }
968          if ( ! arg.isRequired())
969          {
970            continue ;
971          }
972    
973          // If we are here, it means that the argument is required
974          // but not yet is the map. Check if we have a default value.
975          if (arg.getDefaultValue() == null)
976          {
977            Message message =
978                ERR_CLI_ERROR_MISSING_PROPERTY.get(s.getAttributeName());
979            throw new ArgumentException(message);
980          }
981          else
982          {
983            map.put(s, arg.getDefaultValue());
984          }
985        }
986        return map;
987      }
988    }