--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/CommandLineParser.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+public abstract class CommandLineParser {
+ //
+ // Instance data
+ //
+
+ private String[] args;
+
+ //
+ // CommandLineParser methods
+ //
+
+ public String[] getArgs() {
+ return args;
+ }
+
+ public abstract boolean getIsDoneParsing();
+
+ public abstract void getNextOptArg(ParsedOption option);
+
+ public abstract ParsedOption getNextOption();
+
+ public abstract OptionFormatter getOptionFormatter();
+
+ public abstract void reset();
+
+ public abstract void resetToPreviousOption();
+
+ public void setArgs(String[] args) {
+ this.args = args;
+ reset();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/CommandLineProcessor.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,434 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+import java.beans.IntrospectionException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+import org.opensolaris.os.vp.cli.exception.*;
+import org.opensolaris.os.vp.util.*;
+
+public class CommandLineProcessor {
+ //
+ // Instance data
+ //
+
+ private OptionGroup group;
+ private CommandLineParser parser;
+ private Stack<OptionMap> processed;
+ private Map<Option, Integer> used;
+
+ //
+ // Constructors
+ //
+
+ private CommandLineProcessor(OptionGroup group, CommandLineParser parser) {
+ this.group = group;
+ this.parser = parser;
+ this.processed = new Stack<OptionMap>();
+ used = new HashMap<Option, Integer>();
+ }
+
+ //
+ // Private methods
+ //
+
+ private int getUseCount(Option option) {
+ try {
+ return used.get(option);
+ }
+ catch (NullPointerException e) {
+ return 0;
+ }
+ }
+
+ private int incUseCount(Option option) {
+ int count = getUseCount(option) + 1;
+ used.put(option, count);
+ return count;
+ }
+
+ private int decUseCount(Option option) {
+ int count = getUseCount(option) - 1;
+ used.put(option, count);
+ return count;
+ }
+
+ private boolean isUsed(Option option) {
+ return getUseCount(option) > 0;
+ }
+
+ private OptionMap[] getProcessed() {
+ return processed.toArray(new OptionMap[processed.size()]);
+ }
+
+ private void process(Option curOpt, OptionMap conflict, String indent)
+ throws OptionException {
+
+ OptionFormatter formatter = parser.getOptionFormatter();
+
+// System.out.println(indent + "Current option: " +
+// TextUtil.getClassBaseName(curOpt) + ": " +
+// formatter.getFormatted(curOpt, false));
+
+ if (parser.getIsDoneParsing()) {
+ // Last check
+ verifyRequiredOptions(group);
+ return;
+ }
+
+ OptionException exception = null;
+
+ if (curOpt instanceof OptionElement) {
+ OptionElement element = (OptionElement)curOpt;
+
+ ParsedOption parsed = parser.getNextOption();
+// System.out.println(indent + "Next option: " +
+// formatter.getFormatted(parsed.getOpt()));
+
+ // Does this OptionElement expect an opt arg?
+ if (element.getTakesArgument()) {
+ // Parse opt arg
+ parser.getNextOptArg(parsed);
+ }
+
+ // Create mapping between parsed option and option definition
+ OptionMap map = new OptionMap(parsed, (OptionElement)curOpt);
+
+// System.out.println(indent + "Used options:");
+// for (int i = 0, n = processed.size(); i < n; i++) {
+// System.out.println(indent + " " + i + ": " +
+// processed.get(i).getFormatted(formatter));
+// }
+
+ // Add the mapping to list of saved options
+ processed.push(map);
+
+ int useCount = incUseCount(element);
+
+ try {
+ // Validate syntax (throws OptionException)
+ element.validate(parsed, useCount, formatter, getProcessed());
+
+// System.out.println(indent + "Validated option: " +
+// map.getFormatted(formatter));
+
+ // The option is lexically and syntactically valid --
+ // check for conflict with previously-specified option
+ if (conflict != null) {
+ throw new ConflictingOptionsException(
+ conflict.getFormatted(formatter),
+ map.getFormatted(formatter), getProcessed());
+ }
+
+ exception = null;
+
+ // Recurse... (throws OptionException)
+ process(group, conflict, indent + " ");
+
+ // Success! All args have been parsed.
+ return;
+ }
+
+ catch (OptionException e) {
+
+// System.out.println(indent + "Should I save 1:");
+// System.out.println(indent + " " +
+// (exception == null ? "null" : exception.getMessage()));
+// System.out.println(indent + " " +
+// (e == null ? "null" : e.getMessage()));
+
+ // Save only the most significant exception to throw later
+ exception = getMostSignificantException(exception, e);
+
+// System.out.println(indent + "saved: " +
+// (exception == null ? "null" : exception.getMessage()));
+
+ decUseCount(element);
+
+ // Remove the ParsedOption from saved options
+ processed.pop();
+
+ // Un-parse previously-parsed option
+ parser.resetToPreviousOption();
+ }
+ } else
+
+ if (curOpt instanceof OptionGroup) {
+
+ OptionMap newConflict = conflict;
+
+ // If this option is represents a list of options from which only
+ // one can be chosen...
+ if (curOpt instanceof OptionChoiceGroup &&
+
+ // ...and no conflict option has thus far been specified...
+ newConflict == null) {
+
+ // Get the first option in this group, if any, which has already
+ // been specified and validated. Later, if another otherwise
+ // valid option is found, it will conflict with this option and
+ // a ConflictingOptionsException will be thrown.
+ newConflict = getFirstUsedOpt((OptionGroup)curOpt, processed);
+
+// System.out.println(indent + "Assigning conflict opt: " +
+// (newConflict == null ? "null" :
+// newConflict.getFormatted(formatter)));
+ }
+
+ for (Option subOpt : ((OptionGroup)curOpt).getOptions()) {
+ try {
+ incUseCount(curOpt);
+
+ // Recurse... (throws OptionException)
+ process(subOpt, isUsed(subOpt) ?
+ conflict : newConflict, indent + " ");
+
+ // Success! All args have been parsed.
+ return;
+ }
+
+ catch (OptionException e) {
+// System.out.println(indent + "Should I save 2:");
+// System.out.println(indent + " " +
+// (exception == null ? "null" : exception.getMessage()));
+// System.out.println(indent + " " +
+// (e == null ? "null" : e.getMessage()));
+
+ // Save only the most significant exception to throw later
+ exception = getMostSignificantException(exception, e);
+
+// System.out.println(indent + "saved: " +
+// (exception == null ? "null" : exception.getMessage()));
+
+ decUseCount(curOpt);
+ }
+ }
+ }
+
+ if (exception == null) {
+ ParsedOption parsed = parser.getNextOption();
+ exception = new InvalidOptionException(
+ formatter.getFormatted(parsed.getOpt()), getProcessed());
+ parser.resetToPreviousOption();
+ }
+
+ throw exception;
+ }
+
+ /**
+ * Retrieves the first ParsedOption from this option group.
+ */
+ private OptionMap getFirstUsedOpt(OptionGroup parent,
+ List<OptionMap> maps) {
+
+ for (Option subOpt : parent.getOptions()) {
+
+ if (isUsed(subOpt)) {
+ if (subOpt instanceof OptionElement) {
+ // Search for matching ParsedOption
+ for (OptionMap map : maps) {
+ if (((OptionElement)subOpt).matches(
+ map.getParsed())) {
+ return map;
+ }
+ }
+ // Shouldn't be here
+ } else
+
+ if (subOpt instanceof OptionGroup) {
+ OptionMap map = getFirstUsedOpt((OptionGroup)subOpt, maps);
+
+ if (map != null) {
+ return map;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private void verifyRequiredOptions(Option option)
+ throws MissingOptionException {
+
+ OptionFormatter formatter = parser.getOptionFormatter();
+
+ if (!isUsed(option)) {
+ if (option.getIsRequired()) {
+ throw new MissingOptionException(
+ formatter.getFormatted(option, false),
+ getProcessed());
+ }
+ } else {
+ if (option instanceof OptionGroup) {
+ for (Option subOpt : ((OptionGroup)option).getOptions()) {
+ verifyRequiredOptions(subOpt);
+ }
+ }
+ }
+ }
+
+ //
+ // Static methods
+ //
+
+ public static void setInBean(OptionMap[] maps, Object bean)
+ throws InvalidOptArgException, IntrospectionException,
+ IllegalAccessException, NoSuchMethodException {
+
+ // Populate bean
+ for (OptionMap map : maps) {
+
+ ParsedOption parsed = map.getParsed();
+ String opt = parsed.getOpt();
+ String optArg = parsed.getOptArg();
+
+// // Call boolean mutators for no-arg options
+// if (!map.getOption().getTakesArgument()) {
+// optArg = Boolean.toString(true);
+// }
+
+// System.out.println("opt: " + opt);
+// System.out.println("optArg: " + optArg);
+// System.out.println("argName: " + map.getOption().getArgName());
+
+ OptionElement option = map.getOption();
+ String[] names = option.getNames();
+
+ // Handle no-opt options
+ if (names.length == 1 && names[0].length() == 0) {
+ names = new String[] {option.getArgName()};
+ }
+
+ String[] mutators = new String[names.length];
+
+ for (int i = 0; i < names.length; i++) {
+ String name = names[i];
+
+// System.out.println("Looking for property: " + name);
+ try {
+ BeanUtil.setPropertyInBean(bean, name, optArg);
+ break;
+ }
+
+ // Thrown by data conversion routines
+ catch (RuntimeException e) {
+// System.out.println("Caught RuntimeException: " +
+// e.getMessage());
+ throw new InvalidOptArgException(opt, optArg, maps, e);
+ }
+
+ // Thrown by data validation routines
+ catch (InvocationTargetException e) {
+// System.out.println("Caught InvocationTargetException: " +
+// e.getMessage());
+ throw new InvalidOptArgException(opt, optArg,
+ maps, e.getTargetException());
+ }
+
+ // No appropriate mutator in bean
+ catch (NoSuchMethodException e) {
+// System.out.println("Caught NoSuchMethodException: " +
+// e.getMessage());
+
+ // Strip class from fully-qualified method
+ mutators[i] = e.getMessage().replaceFirst(".*\\.", "");
+
+ if (i == names.length - 1) {
+ // No need to internationalize since this is an error
+ // that should only be seen during development
+ throw new NoSuchMethodException(
+ "mutator method(s) not found (perhaps these " +
+ "methods are private?): " +
+ TextUtil.join(", ", (Object[])mutators));
+ }
+ }
+ }
+ }
+ }
+
+ public static OptionMap[] process(String[] args, OptionGroup group,
+ CommandLineParser parser, Object bean) throws OptionException,
+ IntrospectionException, IllegalAccessException, NoSuchMethodException {
+
+ parser.setArgs(args);
+
+ CommandLineProcessor processor =
+ new CommandLineProcessor(group, parser);
+
+ processor.process(group, null, "");
+
+ OptionMap[] maps = processor.getProcessed();
+
+ if (bean != null) {
+ processor.setInBean(maps, bean);
+ }
+
+ return maps;
+ }
+
+ private static OptionException getMostSignificantException(
+ OptionException a, OptionException b) {
+
+ // Sorted in order of significance
+ Class[] classes = {
+ InvalidOptArgException.class,
+ UnexpectedOptArgException.class,
+ MissingOptArgException.class,
+ OptionUseExceededException.class,
+ ConflictingOptionsException.class,
+ MissingOptionException.class,
+ InvalidOptionException.class,
+
+ // Catch-all (except null a and b)
+ OptionException.class
+ };
+
+ for (Class clazz : classes) {
+ boolean aIsInstance = clazz.isInstance(a);
+ boolean bIsInstance = clazz.isInstance(b);
+
+ if (aIsInstance) {
+ if (bIsInstance) {
+
+ // Return the exception that occured when the most options
+ // had been validated
+ return a.getProcessed().length >
+ b.getProcessed().length ? a : b;
+ }
+ return a;
+ }
+
+ if (bIsInstance) {
+ return b;
+ }
+ }
+
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/CommandUtil.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,63 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+import java.util.ArrayList;
+import org.opensolaris.os.vp.util.*;
+
+public class CommandUtil {
+ //
+ // Static methods
+ //
+
+ public static void exit(Throwable t, UsageFormatter usage) {
+ ArrayList<String> messages = new ArrayList<String>();
+
+ if (usage != null) {
+ messages.add(usage.getCommand());
+ }
+
+ while (t != null) {
+ messages.add(t.getMessage());
+ t = t.getCause();
+ }
+
+ String delim = Finder.getString("command.error.delim");
+ System.err.println(TextUtil.join(delim, messages));
+
+ if (usage != null) {
+ System.err.println();
+ System.err.println(usage.getUsage());
+ }
+
+ System.exit(1);
+ }
+
+ public static void exit(Throwable t) {
+ exit(t, null);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/HelpFormatter.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,149 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+import java.util.*;
+import org.opensolaris.os.vp.util.*;
+
+public class HelpFormatter {
+ //
+ // Instance data
+ //
+
+ private String description;
+ private UsageFormatter formatter;
+ private String optionsLabel = Finder.getString("command.help.options");
+
+ //
+ // Constructors
+ //
+
+ public HelpFormatter(String description, UsageFormatter formatter) {
+ this.description = description;
+ this.formatter = formatter;
+ }
+
+ //
+ // HelpFormatter methods
+ //
+
+ public String getDescription() {
+ return description;
+ }
+
+ public UsageFormatter getUsageFormatter() {
+ return formatter;
+ }
+
+ public void setOptionsLabel(String optionsLabel) {
+ this.optionsLabel = optionsLabel;
+ }
+
+ public String getOptionsLabel() {
+ return optionsLabel;
+ }
+
+ public String getHelp() {
+ UsageFormatter usage = getUsageFormatter();
+ OptionElement[] options = getOptionElements();
+ OptionFormatter formatter = usage.getOptionFormatter();
+
+ StringBuffer buffer = new StringBuffer();
+ int width = usage.getWidth();
+
+ buffer.append(usage.getUsage()).
+ append("\n\n").
+ append(TextUtil.format(getDescription(), width, "", "", false));
+
+ if (options.length > 0) {
+ int indentlen = usage.getIndent();
+ String indent2 = String.format("%" + indentlen + "s", "");
+
+ String optionsLabel = getOptionsLabel();
+ if (optionsLabel != null) {
+ buffer.append("\n\n").append(getOptionsLabel());
+ }
+
+ for (OptionElement option : options) {
+ String synopsis = formatter.getFormatted(option, true);
+ buffer.append("\n\n");
+
+ String indent1;
+ // Can synopsis and description be on the same line?
+ if (synopsis.length() + 1 <= indentlen) {
+ indent1 = String.format("%-" + indentlen + "s", synopsis);
+ } else {
+ buffer.append(synopsis).append("\n");
+ indent1 = indent2;
+ }
+
+ buffer.append(TextUtil.format(
+ option.getDescription(), width, indent1, indent2, false));
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ //
+ // Private methods
+ //
+
+ private OptionElement[] getOptionElements() {
+ // Recursively retrieve all OptionElements
+ HashMap<String, OptionElement> map =
+ new HashMap<String, OptionElement>();
+ getOptionElements(getUsageFormatter().getOption(), map);
+
+ ArrayList<OptionElement> elements = new ArrayList<OptionElement>();
+ elements.addAll(map.values());
+
+ Collections.sort(elements,
+ new Comparator<OptionElement>() {
+ public int compare(OptionElement a, OptionElement b) {
+ return a.getName().compareTo(b.getName());
+ }
+ });
+
+ return elements.toArray(new OptionElement[elements.size()]);
+ }
+
+ private void getOptionElements(
+ Option option, HashMap<String, OptionElement> map) {
+ if (option instanceof OptionElement) {
+ OptionElement element = (OptionElement)option;
+ String key = element.getName() + element.getArgName();
+ map.put(key, element);
+ } else
+
+ if (option instanceof OptionGroup) {
+ for (Option o : ((OptionGroup)option).getOptions()) {
+ getOptionElements(o, map);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/NoOptOptionElement.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,67 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+public class NoOptOptionElement extends OptionElement {
+ //
+ // Constructors
+ //
+
+ public NoOptOptionElement(boolean required,
+ String argName, String description, int useLimit) {
+
+ super(new String[] {""}, required, argName, false, description,
+ useLimit);
+ }
+
+ public NoOptOptionElement(boolean required, String argName,
+ String description) {
+
+ this(required, argName, description, 1);
+ }
+
+ //
+ // OptionElement methods
+ //
+
+ /**
+ * Returns a boolean indicating whether the given ParsedOption
+ * matches this NoOptOptionElement.
+ *
+ * @param option
+ * a ParsedOption
+ *
+ * @return <code>true</code> if the option flag is
+ * <code>null</code> or an empty string,
+ * <code>false</code> otherwise
+ */
+ @Override
+ protected boolean matches(ParsedOption option) {
+ String opt = option.getOpt();
+ return opt == null || opt.length() == 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/Option.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,35 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+public abstract class Option {
+ //
+ // Option methods
+ //
+
+ public abstract boolean getIsRequired();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/OptionChoiceGroup.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,41 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+public class OptionChoiceGroup extends OptionGroup {
+ //
+ // Constructors
+ //
+
+ public OptionChoiceGroup(boolean required) {
+ super(required);
+ }
+
+ public OptionChoiceGroup(boolean required, Option... options) {
+ super(required, options);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/OptionElement.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,244 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+import java.util.*;
+import org.opensolaris.os.vp.cli.exception.*;
+
+public class OptionElement extends Option {
+ //
+ // Instance data
+ //
+
+ private boolean required;
+ private List<String> names;
+ private String argName;
+ private boolean argOptional;
+ private String description;
+ private int useLimit;
+
+ //
+ // Constructors
+ //
+
+ public OptionElement(String[] names, boolean required,
+ String argName, boolean argOptional, String description, int useLimit) {
+ setNames(names);
+ setIsRequired(required);
+ setArgName(argName);
+ setArgOptional(argOptional);
+ setDescription(description);
+ setUseLimit(useLimit);
+ }
+
+ public OptionElement(String name, boolean required, String argName,
+ String description) {
+ this(new String[] {name}, required, argName, false, description, 1);
+ }
+
+ public OptionElement(String name, boolean required, String description) {
+ this(name, required, null, description);
+ }
+
+ public OptionElement(String name1, String name2, boolean required,
+ String argName, String description) {
+ this(new String[] {name1, name2},
+ required, argName, false, description, 1);
+ }
+
+ public OptionElement(String name1, String name2, boolean required,
+ String description) {
+ this(name1, name2, required, null, description);
+ }
+
+ //
+ // Option methods
+ //
+
+ @Override
+ public boolean getIsRequired() {
+ return required;
+ }
+
+ //
+ // OptionElement methods
+ //
+
+ public void setIsRequired(boolean required) {
+ this.required = required;
+ }
+
+ public void setNames(String[] names) {
+ this.names = Arrays.asList(names);
+ }
+
+ public String[] getNames() {
+ return names.toArray(new String[names.size()]);
+ }
+
+ public String getName() {
+ try {
+ return names.get(0);
+ }
+ catch (IndexOutOfBoundsException e) {
+ return null;
+ }
+ }
+
+ public void setArgName(String argName) {
+ this.argName = argName;
+ }
+
+ public String getArgName() {
+ return argName;
+ }
+
+ public boolean getTakesArgument() {
+ return argName != null;
+ }
+
+ public void setArgOptional(boolean argOptional) {
+ this.argOptional = argOptional;
+ }
+
+ public boolean getArgOptional() {
+ return argOptional;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setUseLimit(int useLimit) {
+ this.useLimit = useLimit;
+ }
+
+ public int getUseLimit() {
+ return useLimit;
+ }
+
+ /**
+ * Returns a boolean indicating whether the given
+ * <code>ParsedOption</code> matches this
+ * <code>OptionElement</code>.
+ */
+ protected boolean matches(ParsedOption processed) {
+ String opt = processed.getOpt();
+ if (opt != null) {
+ for (String name : getNames()) {
+// System.out.printf("Testing opt=%s optArg=%s against %s\n",
+// opt, processed.getOptArg(), name);
+
+ if (opt.equals(name)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Validates the given option and optional argument against the
+ * option/optArg that this OptionElement expects. If the option is valid,
+ * does nothing. Otherwise, an exception is thrown.
+ *
+ * @param parsed
+ * the option parsed from the command line
+ *
+ * @param useCount
+ * the number of times this option has been used
+ *
+ * @param formatter
+ * used to format the option string in exception
+ * messages
+ *
+ * @param processed
+ * the options processed so far, for use in exceptions
+ *
+ * @exception InvalidOptionException
+ * if the given option doesn't match the name of this
+ * OptionElement
+ *
+ * @exception OptionUseExceededException
+ * if this OptionElement has been used more times
+ * than it is allowed
+ *
+ * @exception MissingOptArgException
+ * if this OptionElement requires an argument but
+ * none was specified
+ *
+ * @exception UnexpectedOptArgException
+ * if this OptionElement takes no argument but
+ * one was specified
+ *
+ * @exception InvalidOptArgException
+ * if this OptionElement's argument is invalid --
+ * not thrown in this default implementation
+ */
+ protected void validate(ParsedOption parsed, int useCount,
+ OptionFormatter formatter, OptionMap[] processed) throws
+ InvalidOptionException, OptionUseExceededException,
+ MissingOptArgException, UnexpectedOptArgException,
+ InvalidOptArgException {
+
+ String opt = parsed.getOpt();
+ String optArg = parsed.getOptArg();
+ String formatted = OptionMap.getFormatted(parsed, this, formatter);
+
+// System.out.printf("Validating: opt=%s optArg=%s\n", opt, optArg);
+
+ // Verify given option identifies this OptionElement
+ if (!matches(parsed)) {
+ throw new InvalidOptionException(formatted, processed);
+ }
+
+ // Change message to reflect the option syntax, not the passed-in opt
+ formatted = formatter.getFormatted(this, false);
+
+ // Verify this option hasn't been specified too many times
+ int useLimit = getUseLimit();
+ if (useLimit >= 0 && useCount > useLimit) {
+ throw new OptionUseExceededException(
+ formatted, useLimit, processed);
+ }
+
+ // Verify optArg if required
+ if (getTakesArgument() && !getArgOptional() && optArg == null) {
+ throw new MissingOptArgException(formatted, processed);
+ }
+
+ // Verify no optArg if not expected
+ if (!getTakesArgument() && optArg != null) {
+ throw new UnexpectedOptArgException(
+ formatted, optArg, processed);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/OptionFormatter.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,122 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+import java.util.ArrayList;
+import org.opensolaris.os.vp.util.TextUtil;
+
+public abstract class OptionFormatter {
+ //
+ // Static data
+ //
+
+ public static final String OPT_LIST_DELIM = " ";
+ public static final String OPT_NAME_DELIM = ",";
+ public static final String OPT_CHOICE_DELIM = " | ";
+ public static final String OPT_REQUIRED_ENCLOSE_LEFT = "[";
+ public static final String OPT_REQUIRED_ENCLOSE_RIGHT = "]";
+ public static final String OPT_GROUP_ENCLOSE_LEFT = "(";
+ public static final String OPT_GROUP_ENCLOSE_RIGHT = ")";
+ public static final String OPT_ARG_ENCLOSE_LEFT = "<";
+ public static final String OPT_ARG_ENCLOSE_RIGHT = ">";
+ public static final String OPT_REPEAT = "...";
+
+ //
+ // OptionFormatter methods
+ //
+
+ public String getFormatted(Option opt, boolean allNames) {
+ return getFormatted(opt, allNames, false, true);
+ }
+
+ public String getFormatted(String opt) {
+ return getFormatted(new String[] {opt});
+ }
+
+ public String getFormatted(String opt, String optArg) {
+ return getFormatted(new String[] {opt}, optArg);
+ }
+
+ public abstract String getFormatted(String[] opts);
+
+ public abstract String getFormatted(String[] opts, String optArg);
+
+ //
+ // Private methods
+ //
+
+ private String getFormatted(Option opt, boolean allNames,
+ boolean showGroup, boolean required) {
+
+ StringBuffer buffer = new StringBuffer();
+
+ if (!required) {
+ buffer.append(OPT_REQUIRED_ENCLOSE_LEFT);
+ showGroup = false;
+ }
+
+ if (opt instanceof OptionElement) {
+ OptionElement element = (OptionElement)opt;
+
+ buffer.append(allNames ?
+ getFormatted(element.getNames(), element.getArgName()) :
+ getFormatted(element.getName(), element.getArgName()));
+
+ if (element.getUseLimit() < 0) {
+ buffer.append(OPT_REPEAT);
+ }
+ } else
+
+ if (opt instanceof OptionGroup) {
+ ArrayList<String> list = new ArrayList<String>();
+ String delim = opt instanceof OptionChoiceGroup ?
+ OPT_CHOICE_DELIM : OPT_LIST_DELIM;
+
+ for (Option subOpt : ((OptionGroup)opt).getOptions()) {
+ list.add(getFormatted(subOpt, allNames, showGroup,
+ opt instanceof OptionChoiceGroup ?
+ true : subOpt.getIsRequired()));
+ }
+
+ if (showGroup) {
+ buffer.append(OPT_GROUP_ENCLOSE_LEFT);
+ }
+
+ buffer.append(TextUtil.join(delim, list));
+
+ if (showGroup) {
+ buffer.append(OPT_GROUP_ENCLOSE_RIGHT);
+ }
+ }
+
+ if (!required) {
+ buffer.append(OPT_REQUIRED_ENCLOSE_RIGHT);
+ }
+
+ return buffer.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/OptionGroup.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,99 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+import java.util.*;
+
+public abstract class OptionGroup extends Option {
+ //
+ // Instance data
+ //
+
+ private boolean required;
+ private List<Option> options = new ArrayList<Option>();
+
+ // Used when processing options
+ private List<Option> usedOptions = new ArrayList<Option>();
+
+ //
+ // Constructors
+ //
+
+ public OptionGroup(boolean required) {
+ this.required = required;
+ }
+
+ public OptionGroup(boolean required, Option[] options) {
+ this(required);
+ this.options.addAll(Arrays.asList(options));
+ }
+
+ //
+ // Option methods
+ //
+
+ @Override
+ public boolean getIsRequired() {
+ return required;
+ }
+
+ //
+ // OptionGroup methods
+ //
+
+ public void addOption(Option option) {
+ synchronized (options) {
+ options.add(option);
+ }
+ }
+
+ protected List<Option> getOptions() {
+ return options;
+ }
+
+ public List<Option> getUsedOptions() {
+ return usedOptions;
+ }
+
+ protected boolean removeOption(Option option) {
+ synchronized (options) {
+ return options.remove(option);
+ }
+ }
+
+ //
+ // Private methods
+ //
+
+ private void addUsedOption(Option option) {
+ usedOptions.add(option);
+ }
+
+ private boolean removeUsedOption(Option option) {
+ return usedOptions.remove(option);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/OptionListGroup.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,41 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+public class OptionListGroup extends OptionGroup {
+ //
+ // Constructors
+ //
+
+ public OptionListGroup(boolean required) {
+ super(required);
+ }
+
+ public OptionListGroup(boolean required, Option... options) {
+ super(required, options);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/OptionMap.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,110 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+/**
+ * The <code>OptionMap</code> class provides a 1x1 mapping between a
+ * <code>ParsedOption</code> and an <code>OptionElement</code>.
+ */
+public class OptionMap {
+ //
+ // Instance data
+ //
+
+ private ParsedOption parsed;
+ private OptionElement option;
+
+ //
+ // Constructors
+ //
+
+ public OptionMap(ParsedOption parsed, OptionElement option) {
+ setParsed(parsed);
+ setOption(option);
+ }
+
+ //
+ // OptionMap methods
+ //
+
+ public void setParsed(ParsedOption parsed) {
+ this.parsed = parsed;
+ }
+
+ /**
+ * Gets the <code>ParsedOption</code> that was parsed from
+ * the command line.
+ */
+ public ParsedOption getParsed() {
+ return parsed;
+ }
+
+ public void setOption(OptionElement option) {
+ this.option = option;
+ }
+
+ /**
+ * Gets the <code>OptionElement</code> that matches the parsed
+ * option.
+ */
+ public OptionElement getOption() {
+ return option;
+ }
+
+ /**
+ * Gets a formatted representation of this option.
+ */
+ public String getFormatted(OptionFormatter formatter) {
+ return getFormatted(parsed, option, formatter);
+ }
+
+ //
+ // Static methods
+ //
+
+ /**
+ * Gets a formatted representation of this option.
+ */
+ public static String getFormatted(ParsedOption parsed, OptionElement option,
+ OptionFormatter formatter) {
+
+ // Return the formatted option if one was specified
+ String opt = parsed.getOpt();
+ if (opt != null && !opt.isEmpty()) {
+ return formatter.getFormatted(opt);
+ }
+
+ // Return the option argument if one was specified
+ String optArg = parsed.getOptArg();
+ if (optArg != null && !optArg.isEmpty()) {
+ return "\"" + optArg + "\"";
+ }
+
+ // Return the formatted option from the option definition
+ return formatter.getFormatted(option, false);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/ParsedOption.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,74 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+/**
+ * The <code>ParsedOption</code> class represents an option that has been
+ * processed from the command line. Whereas the <code>OptionElement</code>
+ * class describes the semantics of the option, this class reflects the option
+ * string that was actually parsed.
+ */
+public class ParsedOption {
+ //
+ // Instance data
+ //
+
+ private String opt;
+ private String optArg;
+
+ //
+ // Constructors
+ //
+
+ public ParsedOption(String opt, String optArg) {
+ this.opt = opt;
+ setOptArg(optArg);
+ }
+
+ //
+ // ParsedOption methods
+ //
+
+ /**
+ * Gets the option (sans leading dashes, etc.) that was processed.
+ */
+ public String getOpt() {
+ return opt;
+ }
+
+ public void setOptArg(String optArg) {
+ this.optArg = optArg;
+ }
+
+ /**
+ * Gets the option argument value, if any, that was processed with
+ * this option.
+ */
+ public String getOptArg() {
+ return optArg;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/PosixCommandLineParser.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,203 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+import java.util.*;
+import org.opensolaris.os.vp.util.TextUtil;
+
+public class PosixCommandLineParser extends CommandLineParser {
+ //
+ // Inner classes
+ //
+
+ protected static class Pointer {
+ public int argPointer;
+ public int charIndex;
+ public Pointer(int argPointer, int charIndex) {
+ this.argPointer = argPointer;
+ this.charIndex = charIndex;
+ }
+ }
+
+ //
+ // Static data
+ //
+
+ // Options consist of any character except whitespace, '-', and '='
+ private static final String ALLOWED_OPTION_CHARS = "[\\S&&[^-=]]";
+
+ // Group 1 is the short option list
+ private static final String REGEX_SHORT_OPTION =
+ "^" + PosixOptionFormatter.PREFIX_SHORT_OPTION +
+ "(" + ALLOWED_OPTION_CHARS + ".*)";
+
+ // Group 1 is the long option, group 3 is the (optional) value
+ private static final String REGEX_LONG_OPTION =
+ "^" + PosixOptionFormatter.PREFIX_LONG_OPTION +
+ "(" + ALLOWED_OPTION_CHARS + "*)(=(.*))?";
+
+ //
+ // Instance data
+ //
+
+ private int argPointer;
+ private int charIndex;
+ private Stack<Pointer> pointerStack = new Stack<Pointer>();
+ private OptionFormatter formatter = new PosixOptionFormatter();
+
+ //
+ // Constructors
+ //
+
+ public PosixCommandLineParser() {
+ reset();
+ }
+
+ //
+ // PosixCommandLineParser methods
+ //
+
+ public ParsedOption getNextOption() {
+ // Are we at the end of the raw argument list?
+ if (getIsDoneParsing()) {
+ return null;
+ }
+
+ // Save position of this option
+ pointerStack.push(new Pointer(argPointer, charIndex));
+
+ String arg = getArgs()[argPointer];
+ String opt = null;
+ String optArg = null;
+ String[] groups;
+
+ // Is the current raw argument a short option?
+ if ((groups = TextUtil.match(arg, REGEX_SHORT_OPTION)) != null) {
+
+ // Group 1 is the short option list
+ opt = groups[1].substring(charIndex, charIndex + 1);
+
+ // Have we reached the end of this raw argument?
+ if (++charIndex == groups[1].length()) {
+ // Go to next raw argument
+ argPointer++;
+ charIndex = 0;
+ }
+ } else
+
+ // Is the current raw argument a long option?
+ if ((groups = TextUtil.match(arg, REGEX_LONG_OPTION)) != null) {
+
+ // Group 1 is the long option, group 3 is the (optional) value
+ opt = groups[1];
+ optArg = groups[3];
+
+ // Go to next raw argument
+ argPointer++;
+ } else {
+
+ // The current raw argument is not an option -- return an
+ // empty short option
+ opt = "";
+ optArg = arg;
+
+ // Go to next raw argument
+ argPointer++;
+ }
+
+// System.out.println("Found option: " + opt + "=" + optArg);
+
+ ParsedOption option = new ParsedOption(opt, optArg);
+
+ return option;
+ }
+
+ public void getNextOptArg(ParsedOption option) {
+ // An opt arg must not aleady have been found
+ if (option.getOptArg() != null ||
+
+ // Are we at the end of the raw argument list?
+ getIsDoneParsing()) {
+ return;
+ }
+
+ String arg = getArgs()[argPointer];
+ String[] groups;
+
+ // Is the current raw argument a short option?
+ if ((groups = TextUtil.match(arg, REGEX_SHORT_OPTION)) != null) {
+
+ // If we are at the beginning of this arg, we can't
+ // retrieve an optArg
+ if (charIndex != 0) {
+
+ // The remainder of the short option list (group 1) is
+ // the optArg
+ option.setOptArg(groups[1].substring(charIndex));
+
+ argPointer++;
+ charIndex = 0;
+ }
+ } else
+
+ // Is the current raw argument *not* a long option?
+ if ((groups = TextUtil.match(arg, REGEX_LONG_OPTION)) == null) {
+
+ // Not an option -- return an empty short option
+ option.setOptArg(arg);
+
+ // Go to next raw argument
+ argPointer++;
+ }
+
+// System.out.println("Found optArg: " + option.getOpt() + "=" +
+// option.getOptArg());
+ }
+
+ public void reset() {
+ argPointer = 0;
+ charIndex = 0;
+ pointerStack.clear();
+ }
+
+ public void resetToPreviousOption() {
+ try {
+ Pointer pointer = pointerStack.pop();
+ argPointer = pointer.argPointer;
+ charIndex = pointer.charIndex;
+ }
+ catch (EmptyStackException ignore) {}
+ }
+
+ public boolean getIsDoneParsing() {
+ return argPointer == getArgs().length;
+ }
+
+ public OptionFormatter getOptionFormatter() {
+ return formatter;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/PosixOptionFormatter.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,86 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+public class PosixOptionFormatter extends OptionFormatter {
+ //
+ // Static data
+ //
+
+ public static final String PREFIX_SHORT_OPTION = "-";
+ public static final String PREFIX_LONG_OPTION = "--";
+ public static final String OPT_ARG_LONG_SEPARATOR = "=";
+ public static final String OPT_ARG_SHORT_SEPARATOR = " ";
+
+ //
+ // OptionFormatter methods
+ //
+
+ @Override
+ public String getFormatted(String[] opts) {
+ return getFormatted(opts, null);
+ }
+
+ @Override
+ public String getFormatted(String[] opts, String optArg) {
+ String separator = "";
+ StringBuffer buffer = new StringBuffer();
+
+ for (int i = 0; i < opts.length; i++) {
+ String opt = opts[i];
+
+ if (i != 0) {
+ buffer.append(OPT_NAME_DELIM);
+ }
+
+ // Is this a non-option opt?
+ if (opt.length() == 0) {
+ separator = "";
+ } else
+
+ // Is this a short opt?
+ if (opt.length() == 1) {
+ separator = OPT_ARG_SHORT_SEPARATOR;
+ buffer.append(PREFIX_SHORT_OPTION);
+ } else {
+
+ // This is a long opt
+ separator = OPT_ARG_LONG_SEPARATOR;
+ buffer.append(PREFIX_LONG_OPTION);
+ }
+
+ buffer.append(opt);
+
+ if (optArg != null) {
+ buffer.append(separator).append(OPT_ARG_ENCLOSE_LEFT).
+ append(optArg).append(OPT_ARG_ENCLOSE_RIGHT);
+ }
+ }
+
+ return buffer.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/UsageFormatter.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,135 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli;
+
+import java.util.*;
+import org.opensolaris.os.vp.util.*;
+
+public class UsageFormatter {
+ //
+ // Static data
+ //
+
+ public static final int _WIDTH = 65;
+ public static final int _INDENT = 4;
+
+ //
+ // Instance data
+ //
+
+ private String command;
+ private Option option;
+ private OptionFormatter formatter;
+ private String usageLabel = Finder.getString("command.usage.header");
+ private int width = _WIDTH;
+ private int indent = _INDENT;
+
+ //
+ // Constructors
+ //
+
+ public UsageFormatter(String command, Option option,
+ OptionFormatter formatter) {
+
+ this.command = command;
+ this.option = option;
+ this.formatter = formatter;
+ }
+
+ //
+ // UsageFormatter methods
+ //
+
+ public String getCommand() {
+ return command;
+ }
+
+ public Option getOption() {
+ return option;
+ }
+
+ public OptionFormatter getOptionFormatter() {
+ return formatter;
+ }
+
+ public void setUsageLabel(String usageLabel) {
+ this.usageLabel = usageLabel;
+ }
+
+ public String getUsageLabel() {
+ return usageLabel;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public void setIndent(int indent) {
+ this.indent = indent;
+ }
+
+ public int getIndent() {
+ return indent;
+ }
+
+ public String getUsage() {
+ Option option = getOption();
+ List<Option> options;
+ if (option instanceof OptionGroup) {
+ options = ((OptionGroup)option).getOptions();
+ } else {
+ options = new ArrayList<Option>();
+ options.add(option);
+ }
+
+ String usageLabel = getUsageLabel();
+ String whitespace = usageLabel.replaceAll("\\S", " ");
+ String indent2 = whitespace +
+ String.format("%" + getIndent() + "s", "");
+ int width = getWidth();
+
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0, n = options.size(); i < n; i++) {
+ String indent1 = i == 0 ? usageLabel : whitespace;
+ String synopsis = command + " " +
+ formatter.getFormatted(options.get(i), false);
+
+ buffer.append(TextUtil.format(
+ synopsis, width, indent1, indent2, false));
+
+ if (i != n - 1) {
+ buffer.append("\n");
+ }
+ }
+
+ return buffer.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/exception/ConflictingOptionsException.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,65 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli.exception;
+
+import org.opensolaris.os.vp.cli.OptionMap;
+import org.opensolaris.os.vp.util.Finder;
+
+public class ConflictingOptionsException extends OptionException {
+ //
+ // Instance data
+ //
+
+ private String opt;
+ private String optInUse;
+
+ //
+ // Constructors
+ //
+
+ public ConflictingOptionsException(String optInUse, String opt,
+ OptionMap[] processed) {
+
+ super(Finder.getString("command.error.option.conflict", opt, optInUse),
+ processed);
+
+ this.opt = opt;
+ this.optInUse = optInUse;
+ }
+
+ //
+ // ConflictingOptionsException methods
+ //
+
+ public String getOpt() {
+ return opt;
+ }
+
+ public String getOptInUse() {
+ return optInUse;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/exception/InvalidOptArgException.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,81 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli.exception;
+
+import org.opensolaris.os.vp.cli.OptionMap;
+import org.opensolaris.os.vp.util.Finder;
+
+public class InvalidOptArgException extends OptionException {
+ //
+ // Instance data
+ //
+
+ private String opt;
+ private String optArg;
+ private Throwable cause;
+
+ //
+ // Constructors
+ //
+
+ public InvalidOptArgException(String opt, String optArg,
+ OptionMap[] processed) {
+
+ super(Finder.getString(opt == null || opt.equals("") ?
+ "command.error.option.argument.invalid.noopt" :
+ "command.error.option.argument.invalid", opt, optArg), processed);
+ this.opt = opt;
+ this.optArg = optArg;
+ }
+
+ public InvalidOptArgException(String opt, String optArg,
+ OptionMap[] processed, Throwable cause) {
+ this(opt, optArg, processed);
+ this.cause = cause;
+ }
+
+ //
+ // Throwable methods
+ //
+
+ @Override
+ public Throwable getCause() {
+ return cause;
+ }
+
+ //
+ // InvalidOptArgException methods
+ //
+
+ public String getOpt() {
+ return opt;
+ }
+
+ public String getOptArg() {
+ return optArg;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/exception/InvalidOptionException.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,55 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli.exception;
+
+import org.opensolaris.os.vp.cli.OptionMap;
+import org.opensolaris.os.vp.util.Finder;
+
+public class InvalidOptionException extends OptionException {
+ //
+ // Instance data
+ //
+
+ private String opt;
+
+ //
+ // Constructors
+ //
+
+ public InvalidOptionException(String opt, OptionMap[] processed) {
+ super(Finder.getString("command.error.option.invalid", opt), processed);
+ this.opt = opt;
+ }
+
+ //
+ // InvalidOptionException methods
+ //
+
+ public String getOpt() {
+ return opt;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/exception/MissingOptArgException.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,56 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli.exception;
+
+import org.opensolaris.os.vp.cli.OptionMap;
+import org.opensolaris.os.vp.util.Finder;
+
+public class MissingOptArgException extends OptionException {
+ //
+ // Instance data
+ //
+
+ private String opt;
+
+ //
+ // Constructors
+ //
+
+ public MissingOptArgException(String opt, OptionMap[] processed) {
+ super(Finder.getString("command.error.option.argument.missing", opt),
+ processed);
+ this.opt = opt;
+ }
+
+ //
+ // MissingOptArgException methods
+ //
+
+ public String getOpt() {
+ return opt;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/exception/MissingOptionException.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,55 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli.exception;
+
+import org.opensolaris.os.vp.cli.OptionMap;
+import org.opensolaris.os.vp.util.Finder;
+
+public class MissingOptionException extends OptionException {
+ //
+ // Instance data
+ //
+
+ private String opt;
+
+ //
+ // Constructors
+ //
+
+ public MissingOptionException(String opt, OptionMap[] processed) {
+ super(Finder.getString("command.error.option.missing", opt), processed);
+ this.opt = opt;
+ }
+
+ //
+ // MissingOptionException methods
+ //
+
+ public String getOpt() {
+ return opt;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/exception/OptionException.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,53 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli.exception;
+
+import org.opensolaris.os.vp.cli.OptionMap;
+
+public class OptionException extends Exception {
+ //
+ // Instance data
+ //
+
+ private OptionMap[] processed;
+
+ //
+ // Constructors
+ //
+
+ public OptionException(String message, OptionMap[] processed) {
+ super(message);
+ this.processed = processed;
+ }
+
+ /**
+ * Gets the valid options processed before this OptionException occurred.
+ */
+ public OptionMap[] getProcessed() {
+ return processed;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/exception/OptionUseExceededException.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,65 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli.exception;
+
+import org.opensolaris.os.vp.cli.OptionMap;
+import org.opensolaris.os.vp.util.Finder;
+
+public class OptionUseExceededException extends OptionException {
+ //
+ // Instance data
+ //
+
+ private String opt;
+ private int max;
+
+ //
+ // Constructors
+ //
+
+ public OptionUseExceededException(String opt, int max,
+ OptionMap[] processed) {
+
+ super(Finder.getString("command.error.option.useexceeded." + max, opt,
+ max), processed);
+
+ this.opt = opt;
+ this.max = max;
+ }
+
+ //
+ // OptionUseExceededException methods
+ //
+
+ public String getOpt() {
+ return opt;
+ }
+
+ public int getMaximumUses() {
+ return max;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/exception/UnexpectedOptArgException.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,65 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.cli.exception;
+
+import org.opensolaris.os.vp.cli.OptionMap;
+import org.opensolaris.os.vp.util.Finder;
+
+public class UnexpectedOptArgException extends OptionException {
+ //
+ // Instance data
+ //
+
+ private String opt;
+ private String optArg;
+
+ //
+ // Constructors
+ //
+
+ public UnexpectedOptArgException(String opt, String optArg,
+ OptionMap[] processed) {
+
+ super(Finder.getString("command.error.option.argument.unexpected", opt,
+ optArg), processed);
+
+ this.opt = opt;
+ this.optArg = optArg;
+ }
+
+ //
+ // UnexpectedOptArgException methods
+ //
+
+ public String getOpt() {
+ return opt;
+ }
+
+ public String getOptArg() {
+ return optArg;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/cli/resources/Resources.properties Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,43 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+# Trailing whitespace intentional
+command.error.delim = :
+
+command.error.option.argument.invalid = {0}: invalid argument: {1}
+command.error.option.argument.invalid.noopt = invalid argument: {1}
+command.error.option.argument.missing = option requires an argument: {0}
+command.error.option.argument.unexpected = {0}: unexpected argument: {1}
+command.error.option.conflict = {0} cannot be specified with {1}
+command.error.option.invalid = unknown option: {0}
+command.error.option.missing = required option not specified: {0}
+command.error.option.useexceeded = option can only be specified {1} times: {0}
+command.error.option.useexceeded.1 = option can only be specified once: {0}
+
+command.help.options = Options:
+
+# Trailing whitespace intentional
+command.usage.header = Usage:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/java/util/org/opensolaris/os/vp/util/BeanUtil.java Thu Sep 18 17:18:30 2008 -0400
@@ -0,0 +1,179 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+package org.opensolaris.os.vp.util;
+
+import java.beans.*;
+import java.lang.reflect.*;
+
+public class BeanUtil {
+ //
+ // Static data
+ //
+
+ private static final String MUTATOR_PREFIX = "set";
+
+ //
+ // Static methods
+ //
+
+ public static void setPropertyInBean(Object bean, String property,
+ String valueAsText) throws IntrospectionException,
+ IllegalAccessException, NoSuchMethodException,
+ InvocationTargetException {
+
+ String methodName = getMutatorMethodName(property);
+ Method method = null;
+
+// System.out.println("Bean: " + bean.getClass().getName());
+
+ if (valueAsText == null) {
+// System.out.println("Looking for null setter: " + methodName);
+ // Find and invoke a mutator method with no parameters
+ try {
+ method = bean.getClass().getMethod(methodName);
+ method.invoke(bean);
+// System.out.println("Found method: " + method.getName());
+ }
+ catch (NoSuchMethodException ignore) {}
+ }
+
+ if (method == null) {
+ // Search for an appropriate mutator method (throws
+ // IntrospectionException)
+ BeanInfo info = Introspector.getBeanInfo(bean.getClass());
+
+ if (info != null) {
+ PropertyDescriptor descriptors[] =
+ info.getPropertyDescriptors();
+
+ for (PropertyDescriptor descriptor : descriptors) {
+ if (descriptor.getName().equals(property)) {
+ method = descriptor.getWriteMethod();
+
+ if (method != null) {
+ Class type = descriptor.getPropertyType();
+
+ // Is there a property editor for this type?
+ PropertyEditor editor = null;
+ Class propEdClass =
+ descriptor.getPropertyEditorClass();
+ if (propEdClass != null) {
+ try {
+ editor = (PropertyEditor)
+ propEdClass.newInstance();
+ }
+ catch (Exception ignore) {}
+ }
+
+ // No editor specifically for this
+ // property -- check the PropertyEditorManager
+ if (editor == null) {
+ editor = PropertyEditorManager.findEditor(type);
+ }
+
+ Object value = null;
+
+ // If an editor was found...
+ if (editor != null) {
+ // Use it to convert text to usable value
+ editor.setAsText(valueAsText);
+ value = editor.getValue();
+ } else {
+ // Convert text to usable value
+ value = getValueAs(type, valueAsText);
+ }
+
+ method.invoke(bean, value);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (method == null) {
+ throw new NoSuchMethodException(
+ bean.getClass().getName() + "." + methodName);
+ }
+ }
+
+ public static String getMutatorMethodName(String property) {
+ if (property == null || property.length() == 0) {
+ return null;
+ }
+ return MUTATOR_PREFIX +
+ property.substring(0, 1).toUpperCase() + property.substring(1);
+ }
+
+ //
+ // Private static methods
+ //
+
+ private static Object getValueAs(Class type, String value) {
+ if (value == null) {
+ return null;
+ }
+
+ if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) {
+ return new Boolean(value);
+ }
+
+ if (type.equals(Byte.class) || type.equals(Byte.TYPE)) {
+ return new Byte(value);
+ }
+
+ if (type.equals(Character.class) || type.equals(Character.TYPE)) {
+ return value.length() == 0 ? null : new Character(value.charAt(0));
+ }
+
+ if (type.equals(Short.class) || type.equals(Short.TYPE)) {
+ return new Short(value);
+ }
+
+ if (type.equals(Integer.class) || type.equals(Integer.TYPE)) {
+ return new Integer(value);
+ }
+
+ if (type.equals(Float.class) || type.equals(Float.TYPE)) {
+ return new Float(value);
+ }
+
+ if (type.equals(Long.class) || type.equals(Long.TYPE)) {
+ return new Long(value);
+ }
+
+ if (type.equals(Double.class) || type.equals(Double.TYPE)) {
+ return new Double(value);
+ }
+
+ if (type.isInstance(value)) {
+ return value;
+ }
+
+ return null;
+ }
+}
--- a/usr/src/java/util/org/opensolaris/os/vp/util/TextUtil.java Tue Sep 16 13:32:03 2008 -0400
+++ b/usr/src/java/util/org/opensolaris/os/vp/util/TextUtil.java Thu Sep 18 17:18:30 2008 -0400
@@ -130,6 +130,12 @@
* @param width
* the maximum width of each line
*
+ * @param indent1
+ * the indent to put on the first line
+ *
+ * @param indent2
+ * the indent to put on the second and remaining lines
+ *
* @param forceBreak
* whether to force a break in the middle of a word
* if the length of the word is greater than
@@ -137,7 +143,9 @@
*
* @return a wrapped string separated by newlines
*/
- public static String format(String text, int width, boolean forceBreak) {
+ public static String format(String text, int width,
+ String indent1, String indent2, boolean forceBreak) {
+
if (text == null) {
return text;
}
@@ -147,7 +155,8 @@
StringBuffer buffer = new StringBuffer();
- int w = width;
+ String indent = indent1;
+ int w = width - indent.length();
if (w < 1) {
w = 1;
}
@@ -173,11 +182,12 @@
buffer.append("\n");
}
- buffer.append(groups[1].trim());
+ buffer.append(indent).append(groups[1].trim());
text = groups[2];
if (i == 0) {
- w = width;
+ indent = indent2;
+ w = width - indent.length();
if (w < 1) {
w = 1;
}
@@ -187,6 +197,19 @@
return buffer.toString();
}
+ /**
+ * Shortcut for:
+ * <p>
+ * <code>
+ * {@link #format(String,int,String,String,boolean) format}
+ * (text, width, "", "", forceBreak);
+ * </code>
+ * </p>
+ */
+ public static String format(String text, int width, boolean forceBreak) {
+ return format(text, width, "", "", forceBreak);
+ }
+
public static boolean isPrintable(char c) {
return c >= 32 && c <= 126;
}
--- a/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/App.java Tue Sep 16 13:32:03 2008 -0400
+++ b/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/App.java Thu Sep 18 17:18:30 2008 -0400
@@ -1,5 +1,5 @@
/*
- * cddl header start
+ * CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
@@ -33,6 +33,7 @@
import javax.management.remote.*;
import javax.swing.*;
import org.opensolaris.os.uds.*;
+import org.opensolaris.os.vp.cli.*;
import org.opensolaris.os.vp.client.common.*;
import org.opensolaris.os.vp.jmx.connector.UDSConnector;
import org.opensolaris.os.vp.panel.common.action.ActionAbortedException;
@@ -47,9 +48,143 @@
*/
public class App extends Thread implements AppConstants {
//
+ // Inner classes
+ //
+
+ public static class CommandLineOptionsBean {
+ //
+ // Instance data
+ //
+
+ private String host = LOCAL_HOST;
+ private String user = LOCAL_USER;
+ private String role;
+ private String address;
+ private boolean newJVM;
+ private HelpFormatter help;
+
+ //
+ // Constructors
+ //
+
+ public CommandLineOptionsBean(HelpFormatter help) {
+ this.help = help;
+ }
+
+ //
+ // CommandLineOptionsBean methods
+ //
+
+ public String getAddress() {
+ return address;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public boolean getNewjvm() {
+ return newJVM;
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public void setAddress(String address) {
+ if (!address.startsWith("/")) {
+ // Assume non-relative path is a standalone shortcut
+ address = String.format("/%s/%s/%s",
+ Control.encode(AppRootControl.ID, null),
+ Control.encode(StandaloneControl.ID, null),
+ address);
+ }
+ this.address = address;
+ }
+
+ public void setHelp() {
+ System.out.println(help.getHelp());
+ System.exit(0);
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public void setNewjvm() {
+ newJVM = true;
+ }
+
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ public void setVersion() {
+ showVersion();
+ System.exit(0);
+ }
+ }
+
+ //
// Static data
//
+ private static final String ARG_NONOPT_ADDRESS = "address";
+ private static final String ARG_SHORT_HOST = "h";
+ private static final String ARG_LONG_HOST = "host";
+ private static final String ARG_SHORT_NEWJVM = "j";
+ private static final String ARG_LONG_NEWJVM = "newjvm";
+ private static final String ARG_SHORT_USER = "u";
+ private static final String ARG_LONG_USER = "user";
+ private static final String ARG_SHORT_ROLE = "r";
+ private static final String ARG_LONG_ROLE = "role";
+ private static final String ARG_SHORT_VERSION = "v";
+ private static final String ARG_LONG_VERSION = "version";
+ private static final String ARG_SHORT_HELP = "?";
+ private static final String ARG_LONG_HELP = "help";
+
+ private static final String COMMAND_NAME = "vp";
+ private static final String COMMAND_DESC =
+ Finder.getString("cli.description");
+
+ private static OptionChoiceGroup options;
+ static {
+ OptionElement addressOption = new NoOptOptionElement(
+ false, ARG_NONOPT_ADDRESS, Finder.getString("cli.arg.address"), 1);
+
+ OptionElement hostOption = new OptionElement(ARG_SHORT_HOST,
+ ARG_LONG_HOST, false, "host", Finder.getString("cli.arg.host"));
+
+ OptionElement newJVMOption = new OptionElement(ARG_SHORT_NEWJVM,
+ ARG_LONG_NEWJVM, false, Finder.getString("cli.arg.newjvm"));
+
+ OptionElement userOption = new OptionElement(ARG_SHORT_USER,
+ ARG_LONG_USER, false, "user", Finder.getString("cli.arg.user"));
+
+ OptionElement roleOption = new OptionElement(ARG_SHORT_ROLE,
+ ARG_LONG_ROLE, false, "role", Finder.getString("cli.arg.role"));
+
+ OptionElement versionOption = new OptionElement(ARG_SHORT_VERSION,
+ ARG_LONG_VERSION, false, Finder.getString("cli.arg.version"));
+
+ OptionElement helpOption = new OptionElement(ARG_SHORT_HELP,
+ ARG_LONG_HELP, false, Finder.getString("cli.arg.help"));
+
+ OptionListGroup mainGroup = new OptionListGroup(false,
+ hostOption, userOption, roleOption, newJVMOption, addressOption);
+
+ options = new OptionChoiceGroup(false, mainGroup, versionOption,
+ helpOption);
+ }
+
public static final String URI_SCHEME = "vp";
public static final String URI_USER_ROLE_SEPARATOR = ":";
@@ -339,6 +474,10 @@
thread.setName(name);
}
+ public static void showVersion() {
+ System.out.println(Finder.getString("cli.error.version", VERSION));
+ }
+
public static URI createURI(String host, String user, String role, int port,
String address) throws URISyntaxException {
@@ -349,68 +488,30 @@
return new URI(URI_SCHEME, user, host, -1, address, null, null);
}
- private static void die(int exitCode, String resource, Object... args) {
- String message = Finder.getString(resource, args);
- PrintStream out = exitCode == 0 ? System.out : System.err;
- out.println(message);
- System.exit(exitCode);
- }
-
public static void main(String args[]) {
addVersionToThreadName(Thread.currentThread());
- String host = LOCAL_HOST;
- String user = LOCAL_USER;
- String role = null;
- String address = null;
- String usage = "cli.error.usage";
- String version = "cli.error.version";
- boolean sharedVM = true;
+ CommandLineParser parser = new PosixCommandLineParser();
+ UsageFormatter usage = new UsageFormatter(
+ COMMAND_NAME, options, parser.getOptionFormatter());
+ HelpFormatter help = new HelpFormatter(COMMAND_DESC, usage);
+ CommandLineOptionsBean bean = new CommandLineOptionsBean(help);
if (System.getProperty("vpanels.debug.version") != null) {
- System.err.printf("%s\n", Finder.getString(version, VERSION));
+ showVersion();
}
- for (int i = 0; i < args.length; i++) {
- String arg = args[i];
- if (arg.matches("^-(-help|\\?)$")) {
- die(0, usage);
- } else if (arg.matches("^-(-version|v)$")) {
- die(0, version, VERSION);
- } else if (arg.matches("^-[hru]$")) {
- if (i == args.length - 1) {
- die(1, usage);
- }
+ try {
+ // Populate bean
+ CommandLineProcessor.process(args, options, parser, bean);
+ }
- String optArg = args[++i];
- if (arg.equals("-h")) {
- host = optArg;
- } else if (arg.equals("-r")) {
- role = optArg;
- } else if (arg.equals("-u")) {
- user = optArg;
- }
- } else if (arg.startsWith("--shared-vm=")) {
- int index = arg.indexOf('=') + 1;
- String value = arg.substring(index);
- sharedVM = Boolean.parseBoolean(value);
- } else {
- if (address != null) {
- die(1, usage);
- }
-
- address = arg;
- if (!address.startsWith("/")) {
- // Assume non-relative path is a standalone shortcut
- address = String.format("/%s/%s/%s",
- Control.encode(AppRootControl.ID, null),
- Control.encode(StandaloneControl.ID, null),
- address);
- }
- }
+ catch (Exception e) {
+ CommandUtil.exit(e, usage);
}
// Navigate to the console if no address given
+ String address = bean.getAddress();
if (address == null) {
address = String.format("/%s/%s",
Control.encode(AppRootControl.ID, null),
@@ -419,12 +520,14 @@
URI uri = null;
try {
- uri = createURI(host, user, role, -1, address);
+ uri = createURI(bean.getHost(), bean.getUser(), bean.getRole(), -1,
+ address);
} catch (URISyntaxException e) {
- die(1, "cli.error.uri", e.getInput());
+ System.err.println(Finder.getString("cli.error.uri", e.getInput()));
+ System.exit(1);
}
- if (sharedVM) {
+ if (!bean.getNewjvm()) {
// Check for running instance
try {
UDSocket socket = UnixDomainSocket.connect(VP_UDS);
@@ -453,7 +556,7 @@
App app = new App(uri);
app.exitIfNoInstances();
- if (sharedVM) {
+ if (!bean.getNewjvm()) {
// Start daemon thread listening for connections
app.start();
}
--- a/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/AppConstants.java.in Tue Sep 16 13:32:03 2008 -0400
+++ b/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/AppConstants.java.in Thu Sep 18 17:18:30 2008 -0400
@@ -1,5 +1,5 @@
/*
- * cddl header start
+ * CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
--- a/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/resources/Resources.properties Tue Sep 16 13:32:03 2008 -0400
+++ b/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/resources/Resources.properties Thu Sep 18 17:18:30 2008 -0400
@@ -100,7 +100,15 @@
panelload.error.fmri = panel returned invalid fmri: {0}
panelload.error.jmx = could not communicate with the JMX agent on {0}
-cli.error.usage = Usage: vp [-h <host>] [-u <user>] [-r <role>] [<address>...]\n vp -?
+cli.description = Launch Solaris system management panels.
+cli.arg.address = Specify the URI identifying the management panel to display.
+cli.arg.host = Specify an optional host to log into. The default is the local machine.
+cli.arg.user = Specify an optional user to log in as. The default is the current user.
+cli.arg.role = Specify an optional role to use when logging in.
+cli.arg.newjvm = Start a new JVM for this invocation instead of using an existing JVM.
+cli.arg.help = Show this message and exit.
+cli.arg.version = Show the version and exit.
+
cli.error.version = vp {0}
cli.error.uri = specified arguments resulted in an invalid URI: {0}