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