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 2007-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.AdministratorProperty;
052    import org.opends.admin.ads.ADSContextException.ErrorType;
053    import org.opends.server.tools.dsconfig.ArgumentExceptionFactory;
054    import org.opends.server.types.Privilege;
055    import org.opends.server.util.args.Argument;
056    import org.opends.server.util.args.ArgumentException;
057    import org.opends.server.util.args.BooleanArgument;
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 user Admin CLI.
066     */
067    public class DsFrameworkCliGlobalAdmin 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 create-admin-user subcommand.
102         */
103        CREATE_ADMIN_USER("create-admin-user"),
104    
105        /**
106         * The delete-admin-user subcommand.
107         */
108        DELETE_ADMIN_USER("delete-admin-user"),
109    
110        /**
111         * The list-admin-user subcommand.
112         */
113        LIST_ADMIN_USER("list-admin-user"),
114    
115        /**
116         * The list-admin-user-properties subcommand.
117         */
118        LIST_ADMIN_USER_PROPERTIES("list-admin-user-properties"),
119    
120        /**
121         * The get-admin-user-properties subcommand.
122         */
123        GET_ADMIN_USER_PROPERTIES("get-admin-user-properties"),
124    
125        /**
126         * The set-admin-user-properties subcommand.
127         */
128        SET_ADMIN_USER_PROPERTIES("set-admin-user-properties");
129    
130    
131        // String representation of the value.
132        private final String name;
133    
134        // Private constructor.
135        private SubCommandNameEnum(String name)
136        {
137          this.name = name;
138        }
139    
140        /**
141         * {@inheritDoc}
142         */
143        public String toString()
144        {
145          return name;
146        }
147    
148        // A lookup table for resolving a unit from its name.
149        private static final List<String> nameToSubCmdName;
150        static
151        {
152          nameToSubCmdName = new ArrayList<String>();
153    
154          for (SubCommandNameEnum subCmd : SubCommandNameEnum.values())
155          {
156            nameToSubCmdName.add(subCmd.toString());
157          }
158        }
159    
160        public static boolean isSubCommand(String name)
161        {
162          return nameToSubCmdName.contains(name);
163        }
164      }
165    
166      /**
167       * The create-admin-user subcommand.
168       */
169      private SubCommand createAdminUserSubCmd;
170    
171      /**
172       * The 'userID' argument of the 'create-admin-user' subcommand.
173       */
174      private StringArgument createAdminUserUserIdArg;
175    
176      /**
177       * The 'set' argument of the 'create-admin-user' subcommand.
178       */
179      private StringArgument createAdminUserSetArg ;
180    
181      /**
182       * The delete-admin-user subcommand.
183       */
184      private SubCommand deleteAdminUserSubCmd;
185    
186      /**
187       * The 'userID' argument of the 'delete-admin-user' subcommand.
188       */
189      private StringArgument deleteAdminUserUserIdArg;
190    
191      /**
192       * The list-admin-user subcommand.
193       */
194      private SubCommand listAdminUserSubCmd;
195    
196      /**
197       * The get-admin-user-properties subcommand.
198       */
199      private SubCommand getAdminUserPropertiesSubCmd;
200    
201      /**
202       * The 'userID' argument of the 'get-admin-user-properties' subcommand.
203       */
204      private StringArgument getAdminUserPropertiesUserIdArg;
205    
206      /**
207       * The set-admin-user-properties subcommand.
208       */
209      private SubCommand setAdminUserPropertiesSubCmd;
210    
211      /**
212       * The 'userID' argument of the 'set-admin-user-properties' subcommand.
213       */
214      private StringArgument setAdminUserPropertiesUserIdArg;
215    
216      /**
217       * The 'set' argument of the 'set-admin-user-properties' subcommand.
218       */
219      private StringArgument setAdminUserPropertiesSetArg;
220    
221    
222      /**
223       * The list-admin-user-properties subcommand.
224       */
225      private SubCommand listAdminUserPropertiesSubCmd;
226    
227      /**
228       * Association between ADSContext enum and properties.
229       */
230      private HashMap<AdministratorProperty, Argument> userAdminProperties;
231    
232      /**
233       * List of read-only server properties.
234       */
235      private HashSet<AdministratorProperty> readonlyadminUserProperties;
236    
237    
238      /**
239       * The subcommand list.
240       */
241      private HashSet<SubCommand> subCommands = new HashSet<SubCommand>();
242    
243      /**
244       * Indicates whether this subCommand should be hidden in the usage
245       * information.
246       */
247      private boolean isHidden;
248    
249      /**
250       * The subcommand group name.
251       */
252      private String groupName;
253    
254      /**
255       * {@inheritDoc}
256       */
257      public Set<SubCommand> getSubCommands()
258      {
259        return subCommands;
260      }
261    
262      /**
263       * {@inheritDoc}
264       */
265      public boolean isHidden()
266      {
267        return isHidden;
268      }
269    
270      /**
271       * {@inheritDoc}
272       */
273      public String getGroupName()
274      {
275        return groupName;
276      }
277    
278      /**
279       * {@inheritDoc}
280       */
281      public void initializeCliGroup(DsFrameworkCliParser argParser,
282          BooleanArgument verboseArg) throws ArgumentException
283      {
284        this.verboseArg = verboseArg;
285        isHidden = false;
286        groupName = "admin-user";
287        this.argParser = argParser;
288    
289        // create-admin-user subcommand.
290        createAdminUserSubCmd = new SubCommand(argParser,
291            SubCommandNameEnum.CREATE_ADMIN_USER.toString(),
292            INFO_ADMIN_SUBCMD_CREATE_ADMIN_USER_DESCRIPTION.get());
293        subCommands.add(createAdminUserSubCmd);
294    
295        createAdminUserUserIdArg = new StringArgument("userID", null,
296            OPTION_LONG_USERID, false, true, INFO_USERID_PLACEHOLDER.get(),
297            INFO_ADMIN_ARG_USERID_DESCRIPTION.get());
298        createAdminUserSubCmd.addArgument(createAdminUserUserIdArg);
299    
300        createAdminUserSetArg = new StringArgument(OPTION_LONG_SET,
301            OPTION_SHORT_SET, OPTION_LONG_SET, false, true, true,
302            INFO_VALUE_SET_PLACEHOLDER.get(), null, null,
303            INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
304        createAdminUserSubCmd.addArgument(createAdminUserSetArg);
305    
306        // delete-admin-user subcommand.
307        deleteAdminUserSubCmd = new SubCommand(argParser,
308            SubCommandNameEnum.DELETE_ADMIN_USER.toString(),
309            INFO_ADMIN_SUBCMD_DELETE_ADMIN_USER_DESCRIPTION.get());
310        subCommands.add(deleteAdminUserSubCmd);
311    
312        deleteAdminUserUserIdArg = new StringArgument("userID", null,
313            OPTION_LONG_USERID, false, true, INFO_USERID_PLACEHOLDER.get(),
314            INFO_ADMIN_ARG_USERID_DESCRIPTION.get());
315        deleteAdminUserSubCmd.addArgument(deleteAdminUserUserIdArg);
316    
317        // list-admin-user subcommand.
318        listAdminUserSubCmd = new SubCommand(argParser,
319            SubCommandNameEnum.LIST_ADMIN_USER.toString(),
320            INFO_ADMIN_SUBCMD_LIST_ADMIN_USER_DESCRIPTION.get());
321        subCommands.add(listAdminUserSubCmd);
322    
323        // get-admin-user-properties subcommand.
324        getAdminUserPropertiesSubCmd = new SubCommand(argParser,
325            SubCommandNameEnum.GET_ADMIN_USER_PROPERTIES.toString(),
326            INFO_ADMIN_SUBCMD_GET_ADMIN_USER_PROPERTIES_DESCRIPTION.get());
327        subCommands.add(getAdminUserPropertiesSubCmd);
328    
329        getAdminUserPropertiesUserIdArg = new StringArgument("userID", null,
330            OPTION_LONG_USERID, false, true, INFO_USERID_PLACEHOLDER.get(),
331            INFO_ADMIN_ARG_USERID_DESCRIPTION.get());
332        getAdminUserPropertiesUserIdArg.setMultiValued(true);
333        getAdminUserPropertiesSubCmd.addArgument(getAdminUserPropertiesUserIdArg);
334    
335        // set-admin-user-properties subcommand.
336        setAdminUserPropertiesSubCmd = new SubCommand(argParser,
337            SubCommandNameEnum.SET_ADMIN_USER_PROPERTIES.toString(),
338            INFO_ADMIN_SUBCMD_SET_ADMIN_USER_PROPERTIES_DESCRIPTION.get());
339        subCommands.add(setAdminUserPropertiesSubCmd);
340    
341        setAdminUserPropertiesUserIdArg = new StringArgument("userID", null,
342            OPTION_LONG_USERID, false, true, INFO_USERID_PLACEHOLDER.get(),
343            INFO_ADMIN_ARG_USERID_DESCRIPTION.get());
344        setAdminUserPropertiesSubCmd.addArgument(setAdminUserPropertiesUserIdArg);
345    
346        setAdminUserPropertiesSetArg = new StringArgument(OPTION_LONG_SET,
347            OPTION_SHORT_SET, OPTION_LONG_SET, false, true, true,
348            INFO_VALUE_SET_PLACEHOLDER.get(), null, null,
349            INFO_DSCFG_DESCRIPTION_PROP_VAL.get());
350        setAdminUserPropertiesSubCmd.addArgument(setAdminUserPropertiesSetArg);
351    
352        // list-admin-user-properties subcommand.
353        listAdminUserPropertiesSubCmd = new SubCommand(argParser,
354            SubCommandNameEnum.LIST_ADMIN_USER_PROPERTIES.toString(),
355            INFO_ADMIN_SUBCMD_LIST_ADMIN_USER_PROPERTIES_DESCRIPTION.get());
356        subCommands.add(listAdminUserPropertiesSubCmd);
357    
358        // Create association between ADSContext enum and server
359        // properties
360        // Server properties are mapped to Argument.
361        userAdminProperties = new HashMap<AdministratorProperty, Argument>();
362        readonlyadminUserProperties = new HashSet<AdministratorProperty>();
363    
364        /**
365         * The ID used to identify the user.
366         */
367        {
368          AdministratorProperty prop = AdministratorProperty.UID;
369          String attName = prop.getAttributeName();
370          StringArgument arg = new StringArgument(attName, null,
371              attName, false, false, true, Message.raw(""), null, null, null);
372          userAdminProperties.put(prop, arg);
373        }
374    
375        /**
376         * The PASSWORD used to identify the user.
377         */
378        {
379          // TODO : Allow file based password
380          AdministratorProperty prop = AdministratorProperty.PASSWORD;
381          String attName = prop.getAttributeName();
382          StringArgument arg = new StringArgument(attName, null,
383              attName, false, false, true, Message.raw(""), null, null, null);
384          userAdminProperties.put(prop, arg);
385        }
386    
387        /**
388         * The DESCRIPTION used to identify the user.
389         */
390        {
391          AdministratorProperty prop = AdministratorProperty.DESCRIPTION;
392          String attName = prop.getAttributeName();
393          StringArgument arg = new StringArgument(attName, null,
394              attName, false, false, true, Message.raw(""), null, null, null);
395          userAdminProperties.put(prop, arg);
396        }
397    
398        /**
399         * The ADMINISTRATOR_DN used to identify the user.
400         */
401        {
402          AdministratorProperty prop = AdministratorProperty.ADMINISTRATOR_DN;
403          String attName = prop.getAttributeName();
404          StringArgument arg = new StringArgument(attName, null,
405              attName, false, false, true, Message.raw(""), null, null, null);
406          userAdminProperties.put(prop, arg);
407          readonlyadminUserProperties.add(prop);
408        }
409    
410        /**
411         * The PRIVILEGE associated to the user.
412         */
413        {
414          AdministratorProperty prop = AdministratorProperty.PRIVILEGE;
415          String attName = prop.getAttributeName();
416          StringArgument arg = new StringArgument(attName, null,
417              attName, true, true, true, Message.raw(""), "root", null, null);
418          userAdminProperties.put(prop, arg);
419        }
420      }
421    
422      /**
423       * {@inheritDoc}
424       */
425      public boolean isSubCommand(SubCommand subCmd)
426      {
427        return SubCommandNameEnum.isSubCommand(subCmd.getName());
428      }
429    
430      /**
431       * {@inheritDoc}
432       */
433      public DsFrameworkCliReturnCode performSubCommand(SubCommand subCmd,
434          OutputStream outStream, OutputStream errStream)
435          throws ADSContextException, ArgumentException
436      {
437    
438        ADSContext adsCtx = null;
439        InitialLdapContext ctx = null;
440        DsFrameworkCliReturnCode returnCode = ERROR_UNEXPECTED;
441    
442        try
443        {
444          // -----------------------
445          // create-admin-user subcommand.
446          // -----------------------
447          if (subCmd.getName().equals(createAdminUserSubCmd.getName()))
448          {
449            String userId  = createAdminUserUserIdArg.getValue();
450            Map<AdministratorProperty, Object> map =
451              mapSetOptionsToMap(createAdminUserSetArg,true);
452            map.put(AdministratorProperty.UID, userId);
453    
454            ctx = argParser.getContext(outStream, errStream);
455            if (ctx == null)
456            {
457              return CANNOT_CONNECT_TO_ADS;
458            }
459            adsCtx = new ADSContext(ctx);
460            adsCtx.createAdministrator(map);
461    
462            returnCode = SUCCESSFUL;
463          }
464          else
465          // -----------------------
466          // delete-admin-user subcommand.
467          // -----------------------
468          if (subCmd.getName().equals(deleteAdminUserSubCmd.getName()))
469          {
470            String userId  = deleteAdminUserUserIdArg.getValue();
471            Map<AdministratorProperty, Object> map =
472              new HashMap<AdministratorProperty, Object>();
473            map.put(AdministratorProperty.UID, userId);
474    
475            ctx = argParser.getContext(outStream, errStream);
476            if (ctx == null)
477            {
478              return CANNOT_CONNECT_TO_ADS;
479            }
480            adsCtx = new ADSContext(ctx);
481            adsCtx.deleteAdministrator(map);
482    
483            returnCode = SUCCESSFUL;
484          }
485          else
486          // -----------------------
487          // list-admin-user subcommand.
488          // -----------------------
489          if (subCmd.getName().equals(listAdminUserSubCmd.getName()))
490          {
491            ctx = argParser.getContext(outStream, errStream);
492            if (ctx == null)
493            {
494              return CANNOT_CONNECT_TO_ADS;
495            }
496            adsCtx = new ADSContext(ctx);
497            Set<Map<AdministratorProperty, Object>> adminUserList = adsCtx
498                .readAdministratorRegistry();
499    
500            PrintStream out = new PrintStream(outStream);
501            for (Map<AdministratorProperty, Object> user : adminUserList)
502            {
503              // print out server ID
504              out.println(AdministratorProperty.UID.getAttributeName() + ": "
505                  + user.get(AdministratorProperty.UID));
506            }
507            returnCode = SUCCESSFUL;
508          }
509          else
510          // -----------------------
511          // get-admin-user-properties subcommand.
512          // -----------------------
513          if (subCmd.getName().equals(getAdminUserPropertiesSubCmd.getName()))
514          {
515            ctx = argParser.getContext(outStream, errStream);
516            if (ctx == null)
517            {
518              return CANNOT_CONNECT_TO_ADS;
519            }
520            adsCtx = new ADSContext(ctx);
521            Set<Map<AdministratorProperty, Object>> adsAdminUserList = adsCtx
522                .readAdministratorRegistry();
523    
524            LinkedList<String> userAdminUserList = getAdminUserPropertiesUserIdArg
525                .getValues();
526            PrintStream out = new PrintStream(outStream);
527            for (Map<AdministratorProperty, Object> adminUser : adsAdminUserList)
528            {
529              String adminUserID = (String) adminUser
530                  .get(AdministratorProperty.UID);
531              if (!userAdminUserList.contains(adminUserID))
532              {
533                continue;
534              }
535              // print out the Admin User ID
536              out.println(AdministratorProperty.UID.getAttributeName() + ": "
537                  + adminUser.get(AdministratorProperty.UID));
538              for (AdministratorProperty ap : adminUser.keySet())
539              {
540                if (ap.equals(AdministratorProperty.UID))
541                {
542                  continue;
543                }
544                out.println(ap.getAttributeName() + ": " + adminUser.get(ap));
545              }
546              out.println();
547            }
548            returnCode = SUCCESSFUL;
549          }
550          else
551          // -----------------------
552          // set-admin-user-properties subcommand.
553          // -----------------------
554          if (subCmd.getName().equals(setAdminUserPropertiesSubCmd.getName()))
555          {
556            Map<AdministratorProperty, Object> map =
557              mapSetOptionsToMap(setAdminUserPropertiesSetArg,false);
558    
559            // if the ID is specify in the --set list, it may mean that
560            // the user wants to rename the serverID
561            String newServerId = (String) map.get(AdministratorProperty.UID) ;
562    
563            // replace the serverID in the map
564            map.put(AdministratorProperty.UID, setAdminUserPropertiesUserIdArg
565                .getValue());
566    
567            ctx = argParser.getContext(outStream, errStream);
568            if (ctx == null)
569            {
570              return CANNOT_CONNECT_TO_ADS;
571            }
572            adsCtx = new ADSContext(ctx);
573            adsCtx.updateAdministrator(map, newServerId);
574            returnCode = SUCCESSFUL;
575          }
576          else
577          // -----------------------
578          // list-admin-user-properties subcommand.
579          // -----------------------
580          if (subCmd.getName().equals(listAdminUserPropertiesSubCmd.getName()))
581          {
582            PrintStream out = new PrintStream(outStream);
583            out.println(DESCRIPTION_OPTIONS_TITLE);
584            out.println();
585            out.print(" r -- ");
586            out.println(DESCRIPTION_OPTIONS_READ);
587            out.print(" w -- ");
588            out.println(DESCRIPTION_OPTIONS_WRITE);
589            out.print(" m -- ");
590            out.println(DESCRIPTION_OPTIONS_MANDATORY);
591            out.print(" s -- ");
592            out.println(DESCRIPTION_OPTIONS_SINGLE);
593            out.println();
594    
595            TableBuilder table = new TableBuilder();
596            table.appendHeading(INFO_DSCFG_HEADING_PROPERTY_NAME.get());
597            table.appendHeading(INFO_DSCFG_HEADING_PROPERTY_OPTIONS.get());
598            table.appendHeading(INFO_DSCFG_HEADING_PROPERTY_SYNTAX.get());
599            table.appendHeading(INFO_CLI_HEADING_PROPERTY_DEFAULT_VALUE.get());
600            for (AdministratorProperty adminUserProp : userAdminProperties.keySet())
601            {
602              if (userAdminProperties.get(adminUserProp).isHidden())
603              {
604                continue;
605              }
606              table.startRow();
607              table.appendCell(adminUserProp.getAttributeName());
608              table.appendCell(getPropertyOptionSummary(userAdminProperties
609                  .get(adminUserProp)));
610              table.appendCell(adminUserProp.getAttributeSyntax());
611              if (userAdminProperties.get(adminUserProp).getDefaultValue() != null)
612              {
613                table.appendCell(userAdminProperties.get(adminUserProp)
614                    .getDefaultValue());
615              }
616              else
617              {
618                table.appendCell("-");
619              }
620            }
621            TextTablePrinter printer = new TextTablePrinter(outStream);
622            table.print(printer);
623            returnCode = SUCCESSFUL;
624          }
625          // -----------------------
626          // ERROR
627          // -----------------------
628          else
629          {
630            // Should never occurs: If we are here, it means that the code
631            // to handle to subcommand is not yet written.
632            throw new ADSContextException(ErrorType.ERROR_UNEXPECTED);
633          }
634        }
635        catch (ADSContextException e)
636        {
637          if (ctx != null)
638          {
639            try
640            {
641              ctx.close();
642            }
643            catch (NamingException x)
644            {
645            }
646          }
647          throw e;
648        }
649    
650        // Close the connection, if needed
651        if (ctx != null)
652        {
653          try
654          {
655            ctx.close();
656          }
657          catch (NamingException x)
658          {
659          }
660        }
661    
662        // return part
663        return returnCode;
664      }
665    
666      /**
667       * Translate a Set properties a to a MAP.
668       *
669       * @param propertySetArgument
670       *          The input set argument.
671       * @param createCall
672       *          Indicates if we should check the presence of mandatory
673       *          properties and add root privileges.
674       * @return The created map.
675       * @throws ArgumentException
676       *           If error error occurs during set parsing.
677       */
678      private Map<AdministratorProperty, Object> mapSetOptionsToMap(
679          StringArgument propertySetArgument, boolean createCall)
680          throws ArgumentException
681      {
682        HashMap<AdministratorProperty, Object> map =
683          new HashMap<AdministratorProperty, Object>();
684        boolean rootPrivileges = false ;
685        for (String m : propertySetArgument.getValues())
686        {
687          // Parse the property "property:value".
688          int sep = m.indexOf(':');
689    
690          if (sep < 0)
691          {
692            throw ArgumentExceptionFactory.missingSeparatorInPropertyArgument(m);
693          }
694    
695          if (sep == 0)
696          {
697            throw ArgumentExceptionFactory.missingNameInPropertyArgument(m);
698          }
699    
700          String propertyName = m.substring(0, sep);
701          String value = m.substring(sep + 1, m.length());
702          if (value.length() == 0)
703          {
704            throw ArgumentExceptionFactory.missingValueInPropertyArgument(m);
705          }
706    
707          // Check that propName is a known prop.
708          AdministratorProperty adminUserProperty = ADSContext
709              .getAdminUserPropFromName(propertyName);
710          if (adminUserProperty == null)
711          {
712            Message message = ERR_CLI_ERROR_PROPERTY_UNRECOGNIZED.get(propertyName);
713            throw new ArgumentException(message);
714          }
715    
716          // Check that propName is not hidden.
717          if (userAdminProperties.get(adminUserProperty).isHidden())
718          {
719            Message message = ERR_CLI_ERROR_PROPERTY_UNRECOGNIZED.get(propertyName);
720            throw new ArgumentException(message);
721          }
722    
723          // Check the property Syntax.
724          MessageBuilder invalidReason = new MessageBuilder();
725          Argument arg = userAdminProperties.get(adminUserProperty) ;
726          if ( ! arg.valueIsAcceptable(value, invalidReason))
727          {
728            Message message =
729                ERR_CLI_ERROR_INVALID_PROPERTY_VALUE.get(propertyName, value);
730            throw new ArgumentException(message);
731          }
732          if (adminUserProperty.equals(AdministratorProperty.PRIVILEGE))
733          {
734            // Check if 'root' privilege is requested, or
735            // if it's a valid privilege
736            if (value.equals(arg.getDefaultValue()))
737            {
738              rootPrivileges = true ;
739            }
740            else
741            {
742              String valueToCheck = value ;
743              if (value.startsWith("-"))
744              {
745                valueToCheck = value.substring(1);
746              }
747              if (Privilege.privilegeForName(valueToCheck) == null)
748              {
749                Message message = ERR_CLI_ERROR_INVALID_PROPERTY_VALUE.get(
750                    AdministratorProperty.PRIVILEGE.getAttributeName(),
751                    valueToCheck);
752                throw new ArgumentException(message);
753              }
754            }
755          }
756    
757          // Add the value to the argument.
758          arg.addValue(value);
759    
760          // add to the map.
761          if (arg.isMultiValued())
762          {
763            map.put(adminUserProperty, arg.getValues());
764          }
765          else
766          {
767            map.put(adminUserProperty, value);
768          }
769        }
770    
771        // If we are not in the create admin user, just return the
772        // provided atributes.
773        if (! createCall)
774        {
775          return map ;
776        }
777    
778        // Here, we are in the create case.
779        // If privileges was not provided by the user, set the default value
780        if (! map.containsKey(AdministratorProperty.PRIVILEGE))
781        {
782          rootPrivileges = true ;
783        }
784    
785        // If we have root privilege, translate it to the corresponding
786        // list of privileges associated to 'root' user.
787        if (rootPrivileges)
788        {
789          LinkedList<String> privilegesList = new LinkedList<String>();
790          for (Privilege p : Privilege.getDefaultRootPrivileges())
791          {
792            privilegesList.add(p.getName());
793          }
794          map.put(AdministratorProperty.PRIVILEGE,privilegesList);
795        }
796    
797        for (AdministratorProperty s : AdministratorProperty.values())
798        {
799          Argument arg = userAdminProperties.get(s);
800          if (arg.isHidden())
801          {
802            continue;
803          }
804          if (map.containsKey(s))
805          {
806            continue ;
807          }
808          if ( ! arg.isRequired())
809          {
810            continue ;
811          }
812    
813          // If we are here, it means that the argument is required
814          // but not yet is the map. Check if we have a default value.
815          if (arg.getDefaultValue() == null)
816          {
817            Message message =
818                ERR_CLI_ERROR_MISSING_PROPERTY.get(s.getAttributeName());
819            throw new ArgumentException(message);
820          }
821          else
822          {
823            map.put(s, arg.getDefaultValue());
824          }
825        }
826        return map;
827      }
828    
829      //Compute the options field.
830      private String getPropertyOptionSummary(Argument arg)
831      {
832        StringBuilder b = new StringBuilder();
833    
834        if (readonlyadminUserProperties.contains(
835            ADSContext.getServerPropFromName(arg.getName())))
836        {
837          b.append("r-"); //$NON-NLS-1$
838        }
839        else
840        {
841          b.append("rw"); //$NON-NLS-1$
842        }
843    
844        if (arg.isRequired())
845        {
846          b.append('m');
847        }
848        else
849        {
850          b.append('-');
851        }
852    
853        if (arg.isMultiValued())
854        {
855          b.append('-');
856        }
857        else
858        {
859          b.append('s');
860        }
861        return b.toString();
862      }
863    
864    }