1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.  Oracle designates this
  10  * particular file as subject to the "Classpath" exception as provided
  11  * by Oracle in the LICENSE file that accompanied this code.
  12  *
  13  * This code is distributed in the hope that it will be useful, but WITHOUT
  14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16  * version 2 for more details (a copy is included in the LICENSE file that
  17  * accompanied this code).
  18  *
  19  * You should have received a copy of the GNU General Public License version
  20  * 2 along with this work; if not, write to the Free Software Foundation,
  21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  22  *
  23  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  24  * or visit www.oracle.com if you need additional information or have any
  25  * questions.
  26  */
  27 package com.sun.javatest.tool;
  28 
  29 import java.awt.Component;
  30 import java.awt.Container;
  31 import java.awt.Window;
  32 
  33 import java.io.File;
  34 import java.io.IOException;
  35 import java.io.PrintWriter;
  36 import java.net.URL;
  37 import java.text.DateFormat;
  38 import java.util.*;
  39 
  40 import com.sun.javatest.Harness;
  41 import com.sun.javatest.ProductInfo;
  42 import com.sun.javatest.tool.jthelp.HelpBroker;
  43 import com.sun.javatest.tool.jthelp.HelpSet;
  44 import com.sun.javatest.tool.jthelp.JTHelpBroker;
  45 import com.sun.javatest.util.HelpTree;
  46 import com.sun.javatest.util.I18NResourceBundle;
  47 import com.sun.javatest.util.WrapWriter;
  48 
  49 /**
  50  * A manager for command line help.
  51  */
  52 public class HelpManager extends CommandManager
  53 {
  54     /**
  55      * Create a HelpManager to manage the command line help
  56      * for a set of command managers.
  57      * The command managers should be set with setCommandManagers.
  58      */
  59     public HelpManager() {
  60     }
  61 
  62     /**
  63      * Create a HelpManager to manage the command line help
  64      * for a set of command managers.
  65      * @param commandManagers the command managers for which
  66      * to give command line help
  67      */
  68     public HelpManager(CommandManager[] commandManagers) {
  69         setCommandManagers(commandManagers);
  70     }
  71 
  72     @Override
  73     public HelpTree.Node getHelp() {
  74         String[] helpOptions = {
  75             "help",
  76             "onlineHelp",
  77             "query1",
  78             "query2",
  79             "usage",
  80             "version"
  81         };
  82         return new HelpTree.Node(i18n, "help.cmd.opts", helpOptions);
  83     }
  84 
  85     /**
  86      * Parse a command (and any arguments it might take).
  87      * @param cmd the command to be parsed
  88      * @param argIter an iterator from which to get any arguments that
  89      * might be required by the option
  90      * @param ctx a context object to use while parsing the command
  91      * @return true if the command is recognized and successfully parsed,
  92      * and false otherwise
  93      */
  94     @Override
  95     public boolean parseCommand(String cmd, ListIterator<String> argIter, CommandContext ctx) {
  96         if (cmd.equalsIgnoreCase("help")
  97             || cmd.equalsIgnoreCase("usage")
  98             || cmd.equalsIgnoreCase("?")) {
  99             List<String> v = new ArrayList<>();
 100             while (argIter.hasNext()) {
 101                 v.add(argIter.next().toLowerCase());
 102             }
 103             commandLineHelpFlag = true;
 104             commandLineHelpQuery = v.toArray(new String[v.size()]);
 105             return true;
 106         }
 107 
 108         if (cmd.equalsIgnoreCase("onlineHelp") || cmd.equalsIgnoreCase("userGuide")) {
 109             StringBuilder sb = new StringBuilder();
 110             while (argIter.hasNext()) {
 111                 if (sb.length() > 0) {
 112                     sb.append(' ');
 113                 }
 114                 sb.append(argIter.next());
 115             }
 116             onlineHelpFlag = true;
 117             onlineHelpQuery = sb.toString();
 118             return true;
 119         }
 120 
 121         if (cmd.equalsIgnoreCase("version")) {
 122             versionFlag = true;
 123             return true;
 124         }
 125 
 126         return false;
 127     }
 128 
 129     /**
 130      * Set the command managers for which to generate command line help.
 131      * @param commandManagers the command managers for which to generate command line help
 132      */
 133     public void setCommandManagers(CommandManager[] commandManagers) {
 134         this.commandManagers = commandManagers;
 135     }
 136 
 137     boolean isInfoRequired() {
 138         return (versionFlag || commandLineHelpFlag || onlineHelpFlag);
 139     }
 140 
 141     void showRequiredInfo(PrintWriter out, CommandContext ctx) {
 142         if (versionFlag) {
 143             showVersion(out);
 144         }
 145 
 146         if (commandLineHelpFlag) {
 147             showCommandLineHelp(out);
 148         }
 149 
 150         if (onlineHelpFlag) {
 151             showOnlineHelp(out, ctx);
 152         }
 153     }
 154 
 155     /**
 156      * Print out info about the options accepted by the command line decoder.
 157      * @param out A stream to which to write the information.
 158      */
 159     void showCommandLineHelp(PrintWriter out) {
 160         HelpTree commandHelpTree = new HelpTree();
 161 
 162         Integer nodeIndent = Integer.getInteger("javatest.help.nodeIndent");
 163         if (nodeIndent != null) {
 164             commandHelpTree.setNodeIndent(nodeIndent.intValue());
 165         }
 166 
 167         Integer descIndent = Integer.getInteger("javatest.help.descIndent");
 168         if (descIndent != null) {
 169             commandHelpTree.setDescriptionIndent(descIndent.intValue());
 170         }
 171 
 172         // sort the command manager help nodes according to their name
 173         TreeMap<String, HelpTree.Node> tm = new TreeMap<>();
 174         for (int i = 0; i < commandManagers.length; i++) {
 175             HelpTree.Node n = commandManagers[i].getHelp();
 176             tm.put(n.getName(), n);
 177         }
 178 
 179         for (Iterator iter = tm.values().iterator(); iter.hasNext(); ) {
 180             commandHelpTree.addNode((HelpTree.Node) (iter.next()));
 181         }
 182 
 183         // now add file types
 184         String[] fileTypes = {
 185             "ts",
 186             "wd",
 187             "jti"
 188         };
 189         HelpTree.Node filesNode = new HelpTree.Node(i18n, "help.cmd.files", fileTypes);
 190         commandHelpTree.addNode(filesNode);
 191 
 192         // now add syntax info
 193         String[] syntaxTypes = {
 194             "opts",
 195             "string",
 196             "atfile",
 197             "readfile",
 198             "encode"
 199         };
 200         HelpTree.Node syntaxNode = new HelpTree.Node(i18n, "help.cmd.syntax", syntaxTypes);
 201         commandHelpTree.addNode(syntaxNode);
 202 
 203         String progName =
 204             System.getProperty("program", "java " + Main.class.getName());
 205 
 206         try {
 207             WrapWriter ww = new WrapWriter(out);
 208 
 209             if (commandLineHelpQuery == null || commandLineHelpQuery.length == 0) {
 210                 // no keywords given
 211                 ww.write(i18n.getString("help.cmd.proto", progName));
 212                 ww.write("\n\n");
 213                 ww.write(i18n.getString("help.cmd.introHead"));
 214                 ww.write('\n');
 215                 commandHelpTree.writeSummary(ww);
 216             }
 217             else if (Arrays.asList(commandLineHelpQuery).contains("all")) {
 218                 // -help all
 219                 ww.write(i18n.getString("help.cmd.proto", progName));
 220                 ww.write("\n\n");
 221                 ww.write(i18n.getString("help.cmd.fullHead"));
 222                 ww.write('\n');
 223                 commandHelpTree.write(ww);
 224             }
 225             else {
 226                 HelpTree.Selection s = commandHelpTree.find(commandLineHelpQuery);
 227                 if (s != null) {
 228                     commandHelpTree.write(ww, s);
 229                 }
 230                 else {
 231                     ww.write(i18n.getString("help.cmd.noEntriesFound"));
 232                     ww.write("\n\n");
 233                     ww.write(i18n.getString("help.cmd.summaryHead"));
 234                     ww.write('\n');
 235                     commandHelpTree.writeSummary(ww);
 236                 }
 237             }
 238 
 239             ww.write('\n');
 240             ww.write(i18n.getString("help.cmd.tail"));
 241             ww.write("\n\n");
 242             ww.write(i18n.getString("help.copyright.txt"));
 243             ww.write("\n\n");
 244 
 245             ww.flush();
 246         }
 247         catch (IOException e) {
 248             // should not happen, from PrintWriter
 249         }
 250 
 251     }
 252 
 253     /**
 254      * Show the JT Harness online help, and exit when it is closed.
 255      * @param out the stream to which to write the help
 256      */
 257     void showOnlineHelp(PrintWriter out, CommandContext ctx) {
 258         out.println(i18n.getString("help.onlineHelp.pleaseWait"));
 259         out.flush();
 260 
 261         final Command[] cmds = ctx.getCommands();
 262         ClassLoader theLoader = null;
 263         URL u = null;      // URL for help set
 264         // uses the first custom help loader found.
 265         // use a customized HelpBroker that will exit the VM when closed.
 266         for (int i = 0; i < cmds.length; i++) {
 267             theLoader = cmds[i].getCustomHelpLoader();
 268 
 269             // could also upgrade this to accept a different help set name
 270             u = HelpSet.findHelpSet(theLoader, "jthelp.hs");
 271             if (u != null) {
 272                 break;
 273             }
 274         }   // for
 275 
 276         if (u == null) {
 277             // could also upgrade this to accept a different help set name
 278             theLoader = this.getClass().getClassLoader();
 279             u = HelpSet.findHelpSet(theLoader, "com/sun/javatest/help/jthelp.hs");
 280         }
 281 
 282         if (u != null) {
 283             HelpSet helpSet = new HelpSet(theLoader, u);
 284             //CustomHelpBroker b = new CustomHelpBroker(helpSet);
 285             HelpBroker b = new JTHelpBroker();
 286             if (onlineHelpQuery != null && onlineHelpQuery.length() > 0) {
 287                 b.displayCurrentID(onlineHelpQuery);
 288             }
 289             else {
 290                 b.displayCurrentID("command.intro.csh");
 291             }
 292         }
 293     }
 294 
 295     /**
 296      * Show version information for JT Harness.
 297      * @param out the stream to which to write the information
 298      */
 299     void showVersion(PrintWriter out) {
 300         File classDir = Harness.getClassDir();
 301         String classDirPath =
 302             (classDir == null ? i18n.getString("help.version.unknown") : classDir.getPath());
 303         DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
 304 
 305         Object[] versionArgs = {
 306             /*product*/ ProductInfo.getName(),
 307             /*version*/ ProductInfo.getVersion(),
 308             /*milestone*/ ProductInfo.getMilestone(),
 309             /*build*/ ProductInfo.getBuildNumber(),
 310             /*type of product*/ ProductInfo.getHarnessVariety(),
 311             /*type of the product */ ProductInfo.getPackagingType(),
 312             /*Installed in*/ classDirPath,
 313             /*Running on platform version*/ System.getProperty("java.version"),
 314             /*from*/ System.getProperty("java.home"),
 315             /*Built with*/ ProductInfo.getBuildJavaVersion(),
 316             /*Built on*/ df.format(ProductInfo.getBuildDate())
 317         };
 318 
 319         out.println(i18n.getString("help.version.txt", versionArgs));
 320         out.println(i18n.getString("help.copyright.txt"));
 321     }
 322 
 323     /**
 324      * @return a string that shortly describes functionality set included
 325      * into the harness.
 326      */
 327     String getHarnessType() {
 328         //help.harnessType.lite.txt
 329         return i18n.getString("help.harnessType.full.txt");
 330     }
 331 
 332     private CommandManager[] commandManagers;
 333     private boolean commandLineHelpFlag;
 334     private String[] commandLineHelpQuery;
 335     private boolean onlineHelpFlag;
 336     private String onlineHelpQuery;
 337     private boolean versionFlag;
 338 
 339     private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(HelpManager.class);
 340 
 341     /*private static class CustomHelpBroker
 342         extends DefaultHelpBroker
 343     {
 344         CustomHelpBroker(HelpSet hs) {
 345             super(hs);
 346             ExitCount.inc();
 347         }
 348 
 349         void search(String s) {
 350             initPresentation();
 351             JFrame frame = (JFrame) (getHelpWindow());
 352             Container root = frame.getContentPane();
 353             JHelpSearchNavigator searchNav =
 354                 (JHelpSearchNavigator) (findComponent(root, JHelpSearchNavigator.class));
 355             if (searchNav == null) {
 356                 return;
 357             }
 358             JTextField searchField =
 359                 (JTextField) (findComponent(searchNav, JTextField.class));
 360             if (searchField == null) {
 361                 return;
 362             }
 363             searchField.setText(s);
 364             searchField.postActionEvent();
 365             setCurrentView("Search"); // name defined in jthelp.hs
 366         }
 367 
 368         public void setDisplayed(boolean b) {
 369             super.setDisplayed(b);
 370             // can't use setDefaultActionOnClose because of
 371             // JavaTestSecurityManager
 372             JFrame frame = (JFrame) (getHelpWindow());
 373             frame.addWindowListener(new java.awt.event.WindowAdapter() {
 374                 @Override
 375                     public void windowClosing(java.awt.event.WindowEvent e) {
 376                         ExitCount.dec();
 377                     }
 378                 });
 379         }
 380 
 381         private Component findComponent(Container cont, Class targetClass) {
 382             for (int i = 0; i < cont.getComponentCount(); i++) {
 383                 Component c = cont.getComponent(i);
 384                 if (targetClass.isInstance(c)) {
 385                     return c;
 386                 }
 387                 if (c instanceof Container) {
 388                     Component child = findComponent((Container) c, targetClass);
 389                     if (child != null) {
 390                         return child;
 391                     }
 392                 }
 393             }
 394             return null;
 395         }
 396 
 397         private Window getHelpWindow() {
 398             return getWindowPresentation().getHelpWindow();
 399         }
 400     }*/
 401 }