Home » geronimo-2.2-source-release » org.apache.geronimo.cli » [javadoc | source]

    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   package org.apache.geronimo.cli;
   18   
   19   import java.io.BufferedReader;
   20   import java.io.IOException;
   21   import java.io.OutputStream;
   22   import java.io.PrintWriter;
   23   import java.io.StringReader;
   24   import java.util.ArrayList;
   25   import java.util.Collection;
   26   import java.util.Collections;
   27   import java.util.Comparator;
   28   import java.util.Iterator;
   29   import java.util.List;
   30   
   31   import org.apache.commons.cli.Option;
   32   import org.apache.commons.cli.OptionGroup;
   33   import org.apache.commons.cli.Options;
   34   
   35   /**
   36    * This code is borrowed from commons-cli <code>org.apache.commons.cli.HelpFormatter</code> class. Its authors are 
   37    * Slawek Zachcial and John Keyes (john at integralsource.com). This class has been slightly updated to meet specific
   38    * requirements.
   39    * 
   40    * @version $Rev: 476049 $ $Date: 2006-11-17 15:35:17 +1100 (Fri, 17 Nov 2006) $
   41    */
   42   public class PrintHelper {
   43   
   44       public static String reformat(String source, int indent, int width) {
   45           int endCol = width;
   46           if (endCol == 0) {
   47               endCol = DEFAULT_WIDTH;
   48           }
   49           if(endCol-indent < 10) {
   50               throw new IllegalArgumentException("Need at least 10 spaces for " +
   51                   "printing, but indent=" + indent + " and endCol=" + endCol);
   52           }
   53           StringBuffer buf = new StringBuffer((int)(source.length()*1.1));
   54           String prefix = indent == 0 ? "" : buildIndent(indent);
   55           try {
   56               BufferedReader in = new BufferedReader(new StringReader(source));
   57               String line;
   58               int pos;
   59               while((line = in.readLine()) != null) {
   60                   if(buf.length() > 0) {
   61                       buf.append('\n');
   62                   }
   63                   while(line.length() > 0) {
   64                       line = prefix + line;
   65                       if(line.length() > endCol) {
   66                           pos = line.lastIndexOf(' ', endCol);
   67                           if(pos < indent) {
   68                               pos = line.indexOf(' ', endCol);
   69                               if(pos < indent) {
   70                                   pos = line.length();
   71                               }
   72                           }
   73                           buf.append(line.substring(0, pos)).append('\n');
   74                           if(pos < line.length()-1) {
   75                               line = line.substring(pos+1);
   76                           } else {
   77                               break;
   78                           }
   79                       } else {
   80                           buf.append(line).append("\n");
   81                           break;
   82                       }
   83                   }
   84               }
   85           } catch (IOException e) {
   86               throw new AssertionError("This should be impossible");
   87           }
   88           return buf.toString();
   89       }
   90   
   91       private static String buildIndent(int indent) {
   92           StringBuffer buf = new StringBuffer(indent);
   93           for(int i=0; i<indent; i++) {
   94               buf.append(' ');
   95           }
   96           return buf.toString();
   97       }
   98   
   99       public static final int DEFAULT_WIDTH = 76;
  100       public static final int DEFAULT_LEFT_PAD = 1;
  101       public static final int DEFAULT_DESC_PAD = 3;
  102       public static final String DEFAULT_SYNTAX_PREFIX = "usage: ";
  103       public static final String DEFAULT_OPT_PREFIX = "-";
  104       public static final String DEFAULT_LONG_OPT_PREFIX = "--";
  105       public static final String DEFAULT_ARG_NAME = "arg";
  106   
  107       private final OutputStream outputStream;
  108       public int defaultWidth;
  109       public int defaultLeftPad;
  110       public int defaultDescPad;
  111       public String defaultSyntaxPrefix;
  112       public String defaultNewLine;
  113       public String defaultOptPrefix;
  114       public String defaultLongOptPrefix;
  115       public String defaultArgName;
  116   
  117       public PrintHelper(OutputStream outputStream) {
  118           if (null == outputStream) {
  119               throw new IllegalArgumentException("outputStream is required");
  120           }
  121           this.outputStream = outputStream;
  122           
  123           defaultWidth = DEFAULT_WIDTH;
  124           defaultLeftPad = DEFAULT_LEFT_PAD;
  125           defaultDescPad = DEFAULT_DESC_PAD;
  126           defaultSyntaxPrefix = DEFAULT_SYNTAX_PREFIX;
  127           defaultNewLine = System.getProperty("line.separator");
  128           defaultOptPrefix = DEFAULT_OPT_PREFIX;
  129           defaultLongOptPrefix = DEFAULT_LONG_OPT_PREFIX;
  130           defaultArgName = DEFAULT_ARG_NAME;
  131       }
  132   
  133       public void printHelp(String cmdLineSyntax, String header, Options options, String footer, boolean autoUsage) {
  134           printHelp(defaultWidth, cmdLineSyntax, header, options, footer, autoUsage);
  135       }
  136   
  137       public void printHelp(int width,
  138               String cmdLineSyntax,
  139               String header,
  140               Options options,
  141               String footer,
  142               boolean autoUsage) {
  143           PrintWriter pw = new PrintWriter(outputStream);
  144           printHelp(pw, width, cmdLineSyntax, header, options, defaultLeftPad, defaultDescPad, footer, autoUsage);
  145           pw.flush();
  146       }
  147   
  148       public void printHelp(PrintWriter pw,
  149               int width,
  150               String cmdLineSyntax,
  151               String header,
  152               Options options,
  153               int leftPad,
  154               int descPad,
  155               String footer,
  156               boolean autoUsage) throws IllegalArgumentException {
  157           if (cmdLineSyntax == null || cmdLineSyntax.length() == 0) {
  158               throw new IllegalArgumentException("cmdLineSyntax not provided");
  159           }
  160   
  161           if (autoUsage) {
  162               printUsage(pw, width, cmdLineSyntax, options);
  163           } else {
  164               printUsage(pw, width, cmdLineSyntax);
  165           }
  166   
  167           if (header != null && header.trim().length() > 0) {
  168               printWrapped(pw, width, header);
  169           }
  170           printOptions(pw, width, options, leftPad, descPad);
  171           if (footer != null && footer.trim().length() > 0) {
  172               printWrapped(pw, width, footer);
  173           }
  174       }
  175   
  176       public void printUsage(PrintWriter pw, int width, String app, Options options) {
  177           // create a list for processed option groups
  178           ArrayList list = new ArrayList();
  179   
  180           StringBuffer optionsBuff = new StringBuffer();
  181           
  182           // temp variable
  183           Option option;
  184   
  185           // iterate over the options
  186           for (Iterator i = options.getOptions().iterator(); i.hasNext();) {
  187               // get the next Option
  188               option = (Option) i.next();
  189   
  190               // check if the option is part of an OptionGroup
  191               OptionGroup group = options.getOptionGroup(option);
  192   
  193               // if the option is part of a group and the group has not already
  194               // been processed
  195               if (group != null && !list.contains(group)) {
  196   
  197                   // add the group to the processed list
  198                   list.add(group);
  199   
  200                   // get the names of the options from the OptionGroup
  201                   Collection names = group.getNames();
  202   
  203                   optionsBuff.append("[");
  204   
  205                   // for each option in the OptionGroup
  206                   for (Iterator iter = names.iterator(); iter.hasNext();) {
  207                       optionsBuff.append(iter.next());
  208                       if (iter.hasNext()) {
  209                           optionsBuff.append("|");
  210                       }
  211                   }
  212                   optionsBuff.append("] ");
  213               } else if (group == null) {
  214                   // if the Option is not part of an OptionGroup
  215                   // if the Option is not a required option
  216                   if (!option.isRequired()) {
  217                       optionsBuff.append("[");
  218                   }
  219   
  220                   if (!" ".equals(option.getOpt())) {
  221                       optionsBuff.append("-").append(option.getOpt());
  222                   } else {
  223                       optionsBuff.append("--").append(option.getLongOpt());
  224                   }
  225   
  226                   if (option.hasArg()) {
  227                       optionsBuff.append(" ");
  228                   }
  229   
  230                   // if the Option has a value
  231                   if (option.hasArg()) {
  232                       optionsBuff.append(option.getArgName());
  233                   }
  234   
  235                   // if the Option is not a required option
  236                   if (!option.isRequired()) {
  237                       optionsBuff.append("]");
  238                   }
  239                   optionsBuff.append(" ");
  240               }
  241           }
  242           
  243           app = app.replace("$options", optionsBuff.toString());
  244   
  245           // call printWrapped
  246           printWrapped(pw, width, app.indexOf(' ') + 1, app);
  247       }
  248   
  249       public void printUsage(PrintWriter pw, int width, String cmdLineSyntax) {
  250           int argPos = cmdLineSyntax.indexOf(' ') + 1;
  251           printWrapped(pw, width, defaultSyntaxPrefix.length() + argPos, defaultSyntaxPrefix + cmdLineSyntax);
  252       }
  253   
  254       public void printOptions(PrintWriter pw, int width, Options options, int leftPad, int descPad) {
  255           StringBuffer sb = new StringBuffer();
  256           renderOptions(sb, width, options, leftPad, descPad, true);
  257           pw.println(sb.toString());
  258       }
  259       
  260       public void printOptions(PrintWriter pw, Options options) {
  261           StringBuffer sb = new StringBuffer();
  262           renderOptions(sb, defaultWidth, options, defaultLeftPad, defaultDescPad, true);
  263           pw.println(sb.toString());
  264       }
  265       
  266       public void printOptionsNoDesc(PrintWriter pw, Options options) {
  267           StringBuffer sb = new StringBuffer();
  268           renderOptions(sb, defaultWidth, options, defaultLeftPad, defaultDescPad, false);
  269           pw.println(sb.toString());
  270       }
  271   
  272       public void printWrapped(PrintWriter pw, int width, String text) {
  273           printWrapped(pw, width, 0, text);
  274       }
  275   
  276       public void printWrapped(PrintWriter pw, int width, int nextLineTabStop, String text) {
  277           StringBuffer sb = new StringBuffer(text.length());
  278           renderWrappedText(sb, width, nextLineTabStop, text);
  279           pw.println(sb.toString());
  280       }
  281   
  282       protected StringBuffer renderOptions(StringBuffer sb, int width, Options options, int leftPad, int descPad, boolean displayDesc) {
  283           final String lpad = createPadding(leftPad);
  284           final String dpad = createPadding(descPad);
  285   
  286           //first create list containing only <lpad>-a,--aaa where -a is opt and --aaa is
  287           //long opt; in parallel look for the longest opt string
  288           //this list will be then used to sort options ascending
  289           int max = 0;
  290           StringBuffer optBuf;
  291           List prefixList = new ArrayList();
  292           Option option;
  293           List optList = new ArrayList(options.getOptions());
  294           Collections.sort(optList, new StringBufferComparator());
  295           for (Iterator i = optList.iterator(); i.hasNext();) {
  296               option = (Option) i.next();
  297               optBuf = new StringBuffer(8);
  298   
  299               if (option.getOpt().equals(" ")) {
  300                   optBuf.append(lpad).append("   " + defaultLongOptPrefix).append(option.getLongOpt());
  301               } else {
  302                   optBuf.append(lpad).append(defaultOptPrefix).append(option.getOpt());
  303                   if (option.hasLongOpt()) {
  304                       optBuf.append(',').append(defaultLongOptPrefix).append(option.getLongOpt());
  305                   }
  306   
  307               }
  308   
  309               if (option.hasArg()) {
  310                   if (option.hasArgName()) {
  311                       optBuf.append(" <").append(option.getArgName()).append('>');
  312                   } else {
  313                       optBuf.append(' ');
  314                   }
  315               }
  316   
  317               prefixList.add(optBuf);
  318               max = optBuf.length() > max ? optBuf.length() : max;
  319           }
  320           int x = 0;
  321           for (Iterator i = optList.iterator(); i.hasNext();) {
  322               option = (Option) i.next();
  323               optBuf = new StringBuffer(prefixList.get(x++).toString());
  324   
  325               if (optBuf.length() < max) {
  326                   optBuf.append(createPadding(max - optBuf.length()));
  327               }
  328               optBuf.append(dpad);
  329               
  330               if (displayDesc) {
  331                   optBuf.append(option.getDescription());
  332               }
  333               int nextLineTabStop = max + descPad;
  334               renderWrappedText(sb, width, nextLineTabStop, optBuf.toString());
  335               if (i.hasNext()) {
  336                   sb.append(defaultNewLine);
  337                   if (displayDesc) {
  338                       sb.append(defaultNewLine);
  339                   }
  340               }
  341           }
  342   
  343           return sb;
  344       }
  345   
  346       protected StringBuffer renderWrappedText(StringBuffer sb, int width, int nextLineTabStop, String text) {
  347           int pos = findWrapPos(text, width, 0);
  348           if (pos == -1) {
  349               sb.append(rtrim(text));
  350               return sb;
  351           } else {
  352               sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
  353           }
  354   
  355           //all following lines must be padded with nextLineTabStop space characters
  356           final String padding = createPadding(nextLineTabStop);
  357   
  358           while (true) {
  359               text = padding + text.substring(pos).trim();
  360               pos = findWrapPos(text, width, 0);
  361               if (pos == -1) {
  362                   sb.append(text);
  363                   return sb;
  364               }
  365   
  366               sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
  367           }
  368   
  369       }
  370   
  371       protected int findWrapPos(String text, int width, int startPos) {
  372           int pos = -1;
  373           // the line ends before the max wrap pos or a new line char found
  374           if (((pos = text.indexOf('\n', startPos)) != -1 && pos <= width)
  375                   || ((pos = text.indexOf('\t', startPos)) != -1 && pos <= width)) {
  376               return pos;
  377           } else if ((startPos + width) >= text.length()) {
  378               return -1;
  379           }
  380   
  381           //look for the last whitespace character before startPos+width
  382           pos = startPos + width;
  383           char c;
  384           while (pos >= startPos && (c = text.charAt(pos)) != ' ' && c != '\n' && c != '\r') {
  385               --pos;
  386           }
  387           //if we found it - just return
  388           if (pos > startPos) {
  389               return pos;
  390           } else {
  391               //must look for the first whitespace chearacter after startPos + width
  392               pos = startPos + width;
  393               while (pos <= text.length() && (c = text.charAt(pos)) != ' ' && c != '\n' && c != '\r') {
  394                   ++pos;
  395               }
  396               return pos == text.length() ? -1 : pos;
  397           }
  398       }
  399   
  400       protected String createPadding(int len) {
  401           StringBuffer sb = new StringBuffer(len);
  402           for (int i = 0; i < len; ++i) {
  403               sb.append(' ');
  404           }
  405           return sb.toString();
  406       }
  407   
  408       protected String rtrim(String s) {
  409           if (s == null || s.length() == 0) {
  410               return s;
  411           }
  412   
  413           int pos = s.length();
  414           while (pos >= 0 && Character.isWhitespace(s.charAt(pos - 1))) {
  415               --pos;
  416           }
  417           return s.substring(0, pos);
  418       }
  419   
  420       private static class StringBufferComparator implements Comparator {
  421   
  422           public int compare(Object o1, Object o2) {
  423               String str1 = stripPrefix(o1.toString());
  424               String str2 = stripPrefix(o2.toString());
  425               return (str1.compareTo(str2));
  426           }
  427   
  428           private String stripPrefix(String strOption) {
  429               // Strip any leading '-' characters
  430               int iStartIndex = strOption.lastIndexOf('-');
  431               if (iStartIndex == -1) {
  432                   iStartIndex = 0;
  433               }
  434               return strOption.substring(iStartIndex);
  435   
  436           }
  437       }
  438   
  439   }

Home » geronimo-2.2-source-release » org.apache.geronimo.cli » [javadoc | source]