1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 1996, 2014, 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.agent;
  28 
  29 import java.awt.Dimension;
  30 import java.awt.EventQueue;
  31 import java.awt.Frame;
  32 import java.awt.GridBagConstraints;
  33 import java.awt.GridBagLayout;
  34 import java.awt.Toolkit;
  35 import java.awt.event.ActionEvent;
  36 import java.awt.event.ActionListener;
  37 import java.awt.event.WindowAdapter;
  38 import java.awt.event.WindowEvent;
  39 import java.io.IOException;
  40 import java.io.PrintStream;
  41 import java.lang.reflect.InvocationTargetException;
  42 import java.lang.reflect.Method;
  43 
  44 import com.sun.javatest.JavaTestSecurityManager;
  45 import com.sun.javatest.util.ExitCount;
  46 import com.sun.javatest.util.MainFrame;
  47 
  48 /**
  49  * A free-standing window that displays and controls a Agent.
  50  *
  51  * @see Agent
  52  * @see AgentMain
  53  * @see AgentApplet
  54  *
  55  **/
  56 
  57 public class AgentFrame extends Frame
  58 {
  59     /**
  60      * Create and start a AgentFrame, based on the supplied command line arguments.
  61      *
  62      * @param args      The command line arguments
  63      * <table>
  64      * <tr><td> -help                           <td> print a short summary of the command usage
  65      * <tr><td> -usage                          <td> print a short summary of the command usage
  66      * <tr><td> -active                         <td> set mode to be active
  67      * <tr><td> -activeHost  <em>hostname</em>  <td> set the host for active connections (implies -active)
  68      * <tr><td> -activePort  <em>port</em>      <td> set the port for active connections (implies -active)
  69      * <tr><td> -passive                        <td> set mode to be passive
  70      * <tr><td> -passivePort <em>port</em>      <td> set the port for passive connections (implies -passive)
  71      * <tr><td> -map         <em>file</em>      <td> map file for translating arguments of incoming requests
  72      * <tr><td> -concurrency <em>number</em>    <td> set the maximum number of simultaneous connections
  73      * <tr><td> -history     <em>number</em>    <td> set the size of the execution history
  74      * <tr><td> -trace                          <td> trace the execution of the agent
  75      * <tr><td> -observer    <em>classname</em> <td> add an observer to the agent that is used
  76      * </table>
  77      */
  78     public static void main(String[] args) {
  79         ModeOptions mode = null;
  80         String activeHost = null;
  81         int activePort = -1;
  82         int passivePort = -1;
  83         String serialPort = null;
  84         int concurrency = -1;
  85         String mapFile = null;
  86         int history = -1;
  87         boolean start = false;
  88         boolean useSharedFrame = true;
  89         String observerClassName = null;
  90         boolean tracing = false;
  91 
  92         ActiveModeOptions amo = new ActiveModeOptions();
  93         PassiveModeOptions pmo = new PassiveModeOptions();
  94         ModeOptions smo = null;
  95 
  96         try {
  97             Class<? extends ModeOptions> serial =
  98                     Class.forName("com.sun.javatest.agent.SerialPortModeOptions").asSubclass(ModeOptions.class);
  99             smo = serial.getDeclaredConstructor().newInstance();
 100         } catch (Exception e) {
 101             System.err.println("There is no support for serial port");
 102         }
 103 
 104         for (int i = 0; i < args.length; i++) {
 105             try {
 106                 if (args[i].equalsIgnoreCase("-active")) {
 107                     mode = amo;
 108                 }
 109                 else if (args[i].equalsIgnoreCase("-passive")) {
 110                     mode = pmo;
 111                 }
 112                 else if (args[i].equalsIgnoreCase("-activeHost")) {
 113                     mode = amo;
 114                     activeHost = args[++i];
 115                 }
 116                 else if (args[i].equalsIgnoreCase("-activePort")) {
 117                     mode = amo;
 118                     activePort = Integer.parseInt(args[++i]);
 119                 }
 120                 else if (args[i].equalsIgnoreCase("-passivePort")) {
 121                     mode = pmo;
 122                     passivePort = Integer.parseInt(args[++i]);
 123                 }
 124                 else if (args[i].equalsIgnoreCase("-serialPort")) {
 125                     mode = smo;
 126                     serialPort = args[++i];
 127                 }
 128                 else if (args[i].equalsIgnoreCase("-concurrency")) {
 129                     concurrency = Integer.parseInt(args[++i]);
 130                 }
 131                 else if (args[i].equalsIgnoreCase("-map")) {
 132                     mapFile = args[++i];
 133                 }
 134                 else if (args[i].equalsIgnoreCase("-history")) {
 135                     history = Integer.parseInt(args[++i]);
 136                 }
 137                 else if (args[i].equalsIgnoreCase("-start")) {
 138                     start = true;
 139                 }
 140                 else if (args[i].equalsIgnoreCase("-trace")) {
 141                     tracing = true;
 142                 }
 143                 else if ("-observer".equalsIgnoreCase(args[i]) && i < args.length - 1) {
 144                     if (observerClassName != null) {
 145                         System.err.println("duplicate use of -observer");
 146                         usage(System.err, 1);
 147                     }
 148                     observerClassName = args[++i];
 149                 }
 150                 else if (args[i].equalsIgnoreCase("-useSharedFrame")) {
 151                     System.err.println("Note: -useSharedFrame is now the default");
 152                     System.err.println("Use -noSharedFrame to disable this feature.");
 153                     useSharedFrame = true;
 154                 }
 155                 else if (args[i].equalsIgnoreCase("-noSharedFrame")) {
 156                     useSharedFrame = false;
 157                 }
 158                 else if (args[i].equalsIgnoreCase("-help") || args[i].equalsIgnoreCase("-usage") ) {
 159                     usage(System.err, 0);
 160                 }
 161                 else {
 162                     System.err.println("Unrecognised option: " + args[i]);
 163                     usage(System.err, 1);
 164                 }
 165             }
 166             catch (ArrayIndexOutOfBoundsException e) {
 167                 System.err.println("Missing argument for " + args[args.length - 1]);
 168                 usage(System.err, 1);
 169             }
 170             catch (NumberFormatException e) {
 171                 System.err.println("Number expected: " + args[i]);
 172                 usage(System.err, 1);
 173             }
 174         }
 175 
 176 
 177         if (activeHost != null)
 178             amo.setHost(activeHost);
 179 
 180         if (activePort != -1)
 181             amo.setPort(activePort);
 182 
 183         if (passivePort != -1)
 184             pmo.setPort(passivePort);
 185 
 186         if (serialPort != null) {
 187             if (smo == null) {
 188                 System.err.println("Could not initialize serial ports");
 189                 System.exit(1);
 190             }
 191             else {
 192                 try {
 193                     Method setPortMethod = smo.getClass().getMethod("setPort", String.class);
 194                     setPortMethod.invoke(smo, serialPort);
 195                 }
 196                 catch (SecurityException | NoSuchMethodException |
 197                         IllegalArgumentException| InvocationTargetException |
 198                         IllegalAccessException e) {
 199                     System.err.println("Could not set serial port:");
 200                     e.printStackTrace();
 201                 }
 202             }
 203         }
 204 
 205 
 206         ModeOptions[] modeOptions = new ModeOptions[] {amo, pmo, smo};
 207 
 208         final AgentFrame sf = new AgentFrame(modeOptions);
 209 
 210         if (observerClassName != null) {
 211             try {
 212                 Class<? extends Agent.Observer> observerClass =
 213                         Class.forName(observerClassName).asSubclass(Agent.Observer.class);
 214                 Agent.Observer observer = observerClass.getDeclaredConstructor().newInstance();
 215                 sf.panel.addObserver(observer);
 216             }
 217             catch (ClassCastException e) {
 218                 System.err.println("observer is not of type " +
 219                         Agent.Observer.class.getName() + ": " + observerClassName);
 220                 System.exit(1);
 221             }
 222             catch (ClassNotFoundException e) {
 223                 System.err.println("cannot find observer class: " + observerClassName);
 224                 System.exit(1);
 225             }
 226             catch (Exception e) {
 227                 System.err.println("problem instantiating observer: " + e);
 228                 System.exit(1);
 229             }
 230         }
 231 
 232         if (useSharedFrame)
 233             MainFrame.setFrame(sf);
 234 
 235         AgentPanel sp = sf.panel;
 236         sp.setTracing(tracing, System.out);
 237 
 238         if (mode != null)
 239             sp.setMode(mode.getModeName());
 240 
 241         if (concurrency != -1)
 242             sp.setConcurrency(concurrency);
 243 
 244         if (mapFile != null)
 245             sp.setMapFile(mapFile);
 246 
 247         if (history != -1)
 248             sp.setHistoryLimit(history);
 249 
 250         Integer delay = Integer.getInteger("agent.retry.delay");
 251         if (delay != null)
 252             sp.setRetryDelay(delay.intValue());
 253 
 254         // install our own permissive security manager, to prevent anyone else
 255         // installing a less permissive one; moan if it can't be installed.
 256         JavaTestSecurityManager.install();
 257 
 258         if (start)
 259             sp.start();
 260 
 261         try {
 262             Method invokeLater = EventQueue.class.getMethod("invokeLater", new Class<?>[] { Runnable.class });
 263             invokeLater.invoke(null, new Object[] { new Runnable() {
 264                     public void run() {
 265                         sf.showCentered();
 266                     }
 267                 } });
 268         }
 269         catch (NoSuchMethodException e) {
 270             // must be JDK 1.1
 271             sf.showCentered();
 272         }
 273         catch (Throwable t) {
 274             t.printStackTrace();
 275         }
 276 
 277     }
 278 
 279     /**
 280      * Display the set of options recognized by main(), and exit.
 281      *
 282      * @param out       The output stream to which to write the
 283      *                  command line help.
 284      * @param exitCode  The exit code to be passed to System.exit.
 285      */
 286     public static void usage(PrintStream out, int exitCode) {
 287         String className = AgentFrame.class.getName();
 288         out.println("Usage:");
 289         out.println("    java " + className + " [options]");
 290         out.println("        -help             print this message");
 291         out.println("        -usage            print this message");
 292         out.println("        -active           set mode to be active");
 293         out.println("        -activeHost host  set the host for active connections (implies -active)");
 294         out.println("        -activePort port  set the port for active connections (implies -active)");
 295         out.println("        -passive          set mode to be passive");
 296         out.println("        -passivePort port set the port for passive connections (implies -passive)");
 297         out.println("        -serialPort port  set the port for serial port connections");
 298         out.println("        -concurrency num  set the maximum number of simultaneous connections");
 299         out.println("        -map file         map file for translating arguments of incoming requests");
 300         out.println("        -history num      set the maximum number of requests remembered in the history list");
 301         out.println("        -start            automatically start a agent");
 302         out.println("        -trace            trace the execution of the agent");
 303         out.println("        -observer class   add an observer to the agent");
 304         out.println("        -useSharedFrame   share the application frame with any tests that require it");
 305         System.exit(exitCode);
 306     }
 307 
 308     /**
 309      * Create a AgentFrame.
 310      * @param modeOptions An array of option panels for different connection modes.
 311      */
 312     public AgentFrame(ModeOptions[] modeOptions) {
 313         super(Agent.productName);
 314 
 315         ExitCount.inc();
 316         addWindowListener(new WindowAdapter() {
 317             public void windowClosing(WindowEvent e) {
 318                 setVisible(false);
 319                 AgentFrame.this.dispose();
 320             }
 321 
 322             public void windowClosed(WindowEvent e) {
 323                 ExitCount.dec();
 324             }
 325         });
 326 
 327         setLayout(new GridBagLayout());
 328 
 329         GridBagConstraints c = new GridBagConstraints();
 330 
 331         panel = new AgentPanel(modeOptions, new AgentPanel.MapReader() {
 332             public Map read(String name) throws IOException {
 333                 // Experiments indicate that the following code works OK
 334                 // on versions of PersonalJava that do not support local file systems.
 335                 // Just specify the map file as an http: URL.
 336                 if (name == null || name.length() == 0)
 337                     return null;
 338                 else
 339                     return Map.readFileOrURL(name);
 340             }
 341         });
 342 
 343         c.fill = GridBagConstraints.BOTH;
 344         c.weightx = 1;
 345         c.weighty = 1;
 346         add(panel, c);
 347     }
 348 
 349     private void showCentered() {
 350         pack();
 351 
 352         Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
 353         Dimension size = getSize();
 354         setLocation(screenSize.width/2 - size.width/2, screenSize.height/2 - size.height/2);
 355         show();
 356     }
 357 
 358     private class Listener implements ActionListener {
 359         public void actionPerformed(ActionEvent e) {
 360             String cmd = e.getActionCommand();
 361             if (cmd.equals(EXIT)) {
 362                 AgentFrame.this.dispose();
 363             }
 364         }
 365     }
 366 
 367     private Listener listener = new Listener();
 368     private AgentPanel panel;
 369     private boolean tracing;
 370 
 371     // action commands
 372     private static final String EXIT = "Exit";
 373 }