com.google.feedserver.util.CommonsCliHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.google.feedserver.util.CommonsCliHelper.java

Source

/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.feedserver.util;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Uses reflection to scan registered classes for any String or boolean ending
 * in "_FLAG" or "_HELP" and creates command line flags for these fields. Use
 * {@link #register(Class)} to register a classes flag Fields and {@link #parse}
 * to parse the command line args.
 * 
 * Fields must be static and only String and boolean are currently supported.
 * The field name up to the "_" is used as the flag name and its value is the
 * default.
 * 
 * example: to setup --filename as a flag. in class Foo with flag help.
 * 
 * public class Foo { public static String filename_FLAG = "/tmp/defaultfile";
 * public static String filename_HELP = "filename to access";
 * 
 * public static void main(String[] args) { CommonsCliHelper cliHelper = new
 * CommonsCliHelper(); cliHelper.register(Foo.class); cliHelper.parse(args);
 * System.stdout.println("Filename is " + filename_FLAG); }
 * 
 * @author r@kuci.org (Ray Colline)
 */
public class CommonsCliHelper {

    @SuppressWarnings("unchecked")
    private List<Class> classes;
    private CommandLine flags;
    private Options options;

    @SuppressWarnings("unchecked")
    public CommonsCliHelper() {
        classes = new ArrayList<Class>();
    }

    @SuppressWarnings("unchecked")
    public void register(Class flagClass) {
        classes.add(flagClass);
    }

    /**
     * With provided command line string, populates all registered classes _FLAG
     * fields with their command-line values.
     * 
     * @param args command-line.
     */
    public void parse(String[] args) {
        options = createOptions();
        GnuParser parser = new GnuParser();
        try {
            flags = parser.parse(options, args);
        } catch (ParseException e) {
            usage();
            throw new RuntimeException(e);
        }

        /*
         * Print help text and exit.
         */
        if (flags.hasOption("help")) {
            usage();
            System.exit(0);
        }
        populateClasses();
    }

    /**
     * Prints usage information.
     */
    public void usage() {
        new HelpFormatter().printHelp("Usage", options);
    }

    /**
     * Loop through each registered class and parse the command line for their
     * flags. If option isnt specified we leave the default.
     */
    @SuppressWarnings("unchecked")
    private void populateClasses() {
        for (Class flagClass : classes) {
            for (Field field : flagClass.getFields()) {
                if (field.getName().endsWith("_FLAG")) {
                    String argName = field.getName().substring(0, field.getName().length() - "_FLAG".length());
                    if (field.getType().getName().equals(Boolean.class.getName())) {
                        if (flags.hasOption(argName)) {
                            setField(field, new Boolean(true));
                        } else if (flags.hasOption("no" + argName)) {
                            setField(field, new Boolean(false));
                        }
                    } else {
                        String argValue = flags.getOptionValue(argName, null);
                        if (argValue != null) {
                            setField(field, argValue);
                        }
                    }
                }
            }
        }
    }

    /**
     * Sets value in the supplied field to the given value.
     * 
     * @param field the flag field.
     * @param value the value, usually a Boolean or a String.
     * @throws RuntimeException if the field is mis-configured.
     */
    private void setField(Field field, Object value) {
        try {
            field.set(null, value);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("Field " + field.getName() + " must be a String", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Field " + field.getName() + " must be public", e);
        } catch (NullPointerException e) {
            throw new RuntimeException("Field " + field.getName() + " must be static");
        }
    }

    /**
     * For each class registered, we extract options based on the flags set within
     * the class.
     * 
     * - Any class field ending in {prefix}_FLAG is turned into "--{prefix}" on
     * the command line. eg. "public String adminEmail_FLAG" becomes
     * "--adminEmail" - Any field defined with {prefix}_HELP will be used as the
     * help text.
     * 
     * @return Options all commandline options registered for parsing.
     */
    @SuppressWarnings("unchecked")
    private Options createOptions() {

        Options options = new Options();
        options.addOption(new Option("help", false, "Print out usage."));
        for (Class flagClass : classes) {
            for (Field field : flagClass.getFields()) {
                if (field.getName().endsWith("_FLAG")) {
                    String argName = field.getName().substring(0, field.getName().length() - "_FLAG".length());
                    String helpText = getHelpText(flagClass, argName);
                    if (field.getType().getName().equals(Boolean.class.getName())) {
                        options.addOption(new Option(argName, false, helpText));
                        options.addOption(new Option("no" + argName, true, helpText));
                    } else {
                        options.addOption(new Option(argName, true, helpText));
                    }
                }
            }
        }
        return options;
    }

    /**
     * Returns help text for the given field and class.
     * 
     * @returns String the help text.
     */
    @SuppressWarnings("unchecked")
    private String getHelpText(Class flagClass, String argumentName) {
        String helpText = "None Available";
        try {
            helpText = (String) flagClass.getField(argumentName + "_HELP").get(null);
        } catch (SecurityException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("Help text must be of type String.", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Help text must be public!", e);
        }
        return helpText;
    }
}