Coverage Report - org.apache.commons.launcher.ChildMain
 
Classes in this File Line Coverage Branch Coverage Complexity
ChildMain
0%
0/68
0%
0/32
5.25
ChildMain$1
N/A
N/A
5.25
ChildMain$ChildWindowAdapter
0%
0/3
N/A
5.25
 
 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  
 
 18  
 package org.apache.commons.launcher;
 19  
 
 20  
 import java.awt.Frame;
 21  
 import java.awt.Image;
 22  
 import java.awt.Rectangle;
 23  
 import java.awt.Toolkit;
 24  
 import java.awt.event.WindowAdapter;
 25  
 import java.awt.event.WindowEvent;
 26  
 import java.io.FileOutputStream;
 27  
 import java.io.PrintStream;
 28  
 import java.lang.reflect.Method;
 29  
 
 30  
 /**
 31  
  * A wrapper class that invokes another class'
 32  
  * <code>main(String[])</code>. This particular class uses several system
 33  
  * properties to control features:
 34  
  * <ul>
 35  
  * <li>Redirecting System.out and System.err.
 36  
  * <li>Displaying a minimized window in the Windows taskbar.
 37  
  * </ul>
 38  
  * This class is normally not invoked directly. Instead, it is invoked by the
 39  
  * {@link LaunchTask} class.
 40  
  *
 41  
  * @author Patrick Luby
 42  
  */
 43  
 public class ChildMain extends Thread {
 44  
 
 45  
     //----------------------------------------------------------- Static Fields
 46  
 
 47  
     /**
 48  
      * The appendOutput system property name.
 49  
      */
 50  
     public final static String APPEND_OUTPUT_PROP_NAME =
 51  
         "org.apache.commons.launcher.appendOutput";
 52  
 
 53  
     /**
 54  
      * The displayMiminizedWindow system property name.
 55  
      */
 56  
     public final static String DISPLAY_MINIMIZED_WINDOW_PROP_NAME =
 57  
         "org.apache.commons.launcher.displayMinimizedWindow";
 58  
 
 59  
     /**
 60  
      * The disposeMiminizedWindow system property name.
 61  
      */
 62  
     public final static String DISPOSE_MINIMIZED_WINDOW_PROP_NAME =
 63  
         "org.apache.commons.launcher.disposeMinimizedWindow";
 64  
 
 65  
     /**
 66  
      * The executableName system property name.
 67  
      */
 68  
     public final static String EXECUTABLE_PROP_NAME =
 69  
         "org.apache.commons.launcher.executableName";
 70  
 
 71  
     /**
 72  
      * The heartbeatFile system property name.
 73  
      */
 74  
     public final static String HEARTBEAT_FILE_PROP_NAME =
 75  
         "org.apache.commons.launcher.heartbeatFile";
 76  
 
 77  
     /**
 78  
      * The miminizedWindowTitle system property name.
 79  
      */
 80  
     public final static String MINIMIZED_WINDOW_TITLE_PROP_NAME =
 81  
         "org.apache.commons.launcher.minimizedWindowTitle";
 82  
 
 83  
     /**
 84  
      * The miminizedWindowIcon system property name.
 85  
      */
 86  
     public final static String MINIMIZED_WINDOW_ICON_PROP_NAME=
 87  
         "org.apache.commons.launcher.minimizedWindowIcon";
 88  
 
 89  
     /**
 90  
      * The outputFile system property name.
 91  
      */
 92  
     public final static String OUTPUT_FILE_PROP_NAME =
 93  
         "org.apache.commons.launcher.outputFile";
 94  
 
 95  
     /**
 96  
      * The waitForChild system property name.
 97  
      */
 98  
     public final static String WAIT_FOR_CHILD_PROP_NAME =
 99  
         "org.apache.commons.launcher.waitForChild";
 100  
 
 101  
     //------------------------------------------------------------------ Fields
 102  
 
 103  
     /**
 104  
      * Cached command line arguments
 105  
      */
 106  0
     private String[] args = null;
 107  
 
 108  
     //------------------------------------------------------------ Constructors
 109  
 
 110  
     /**
 111  
      * Construct an instance of this {@link Thread} subclass and cache the
 112  
      * args parameter for use by the {@link #run()} method.
 113  
      *
 114  
      * @param group the ThreadGroup to use for this thread
 115  
      * @param args the command line arguments
 116  
      */
 117  
     private ChildMain(ThreadGroup group, String[] args) {
 118  
 
 119  0
         super(group, ChildMain.class.getName());
 120  0
         this.args = args;
 121  
 
 122  0
     }
 123  
 
 124  
     //---------------------------------------------------------- Static Methods
 125  
 
 126  
     /**
 127  
      * Main entry point for the child process. This method should only be
 128  
      * invoked by the {@link LaunchTask} class.
 129  
      *
 130  
      * @param args command line arguments
 131  
      */
 132  
     public static void main(String[] args) {
 133  
 
 134  
         // Invoke the target application in a separate thread so that we
 135  
         // caught any uncaught errors thrown by the target application
 136  0
         Thread mainThread = new ChildMain(new ExitOnErrorThreadGroup(ChildMain.class.getName()), args);
 137  0
         mainThread.start();
 138  
 
 139  0
     }
 140  
 
 141  
     //----------------------------------------------------------------- Methods
 142  
 
 143  
     /**
 144  
      * Invoke the target application.
 145  
      */
 146  
     public void run() {
 147  
 
 148  
         // If there are no command line arguments, do nothing
 149  0
         if (args == null || args.length == 0)
 150  0
             return;
 151  
 
 152  
         // Invoke the target application
 153  
         try {
 154  
 
 155  
             // Start the thread to check if the parent JVM exits.
 156  0
             boolean waitForChild = false;
 157  0
             if (System.getProperty(ChildMain.WAIT_FOR_CHILD_PROP_NAME) != null) {
 158  0
                 waitForChild = true;
 159  0
                 String heartbeatFile = System.getProperty(ChildMain.HEARTBEAT_FILE_PROP_NAME);
 160  0
                 ParentListener heartbeat = new ParentListener(heartbeatFile);
 161  
                 // Make the thread a daemon thread so that it does not
 162  
                 // prevent this process from exiting when all of the
 163  
                 // appliation's threads finish.
 164  0
                 heartbeat.setDaemon(true);
 165  0
                 heartbeat.start();
 166  
             }
 167  
 
 168  
             // If applicable, redirect output and error streams
 169  0
             String outputPath = System.getProperty(ChildMain.OUTPUT_FILE_PROP_NAME);
 170  0
             if (outputPath != null) {
 171  0
                 boolean appendOutput = false;
 172  0
                 if (System.getProperty(ChildMain.APPEND_OUTPUT_PROP_NAME) != null)
 173  0
                     appendOutput = true;
 174  0
                 PrintStream ps = new PrintStream(new FileOutputStream(outputPath, appendOutput), true);
 175  0
                 System.setOut(ps);
 176  0
                 System.setErr(ps);
 177  
             }
 178  
 
 179  
             // The first argument should be the class that we really want to
 180  
             // invoke. Try to load the class and invoke its main(String[])
 181  
             // method with the first argument shifted out.
 182  0
             Class mainClass = Class.forName(args[0]);
 183  0
             Class[] paramTypes = new Class[1];
 184  0
             Object[] paramValues = new Object[1];
 185  0
             String[] params = new String[args.length - 1];
 186  
             // Shift args[0] out of the arguments
 187  0
             for (int i = 0; i < params.length; i++)
 188  0
                 params[i] = args[i + 1];
 189  0
             paramTypes[0] = params.getClass();
 190  0
             paramValues[0] = params;
 191  
 
 192  
             // Create the icon window if this is a waitForChild task
 193  0
             Frame frame = null;
 194  0
             boolean displayMinimizedWindow = false;
 195  0
             if (System.getProperty(ChildMain.DISPLAY_MINIMIZED_WINDOW_PROP_NAME) != null)
 196  0
                 displayMinimizedWindow = true;
 197  0
             String osname = System.getProperty("os.name").toLowerCase();
 198  0
             if (displayMinimizedWindow && osname.indexOf("windows") >= 0) {
 199  
                 try {
 200  0
                     frame = new Frame();
 201  0
                     String title = System.getProperty(ChildMain.MINIMIZED_WINDOW_TITLE_PROP_NAME);
 202  0
                     if (title != null)
 203  0
                         frame.setTitle(title);
 204  0
                     frame.setState(Frame.ICONIFIED);
 205  0
                     String icon = System.getProperty(ChildMain.MINIMIZED_WINDOW_ICON_PROP_NAME);
 206  0
                     if (icon != null) {
 207  0
                         Image iconImage = Toolkit.getDefaultToolkit().createImage(icon);
 208  0
                         if (iconImage != null)
 209  0
                             frame.setIconImage(iconImage);
 210  
                     }
 211  
 
 212  
                     // Ensure that window always remains minimized
 213  0
                     frame.addWindowListener(new ChildWindowAdapter());
 214  0
                     Rectangle bounds = frame.getGraphicsConfiguration().getBounds();
 215  0
                     int width = (int)frame.getBounds().getWidth();
 216  0
                     int height = frame.getInsets().top + frame.getInsets().bottom;
 217  0
                     int x = (int)bounds.getWidth() - width;
 218  0
                     int y = (int)bounds.getHeight() - height;
 219  0
                     frame.setBounds(x, y, width, height);
 220  0
                     frame.setResizable(false);
 221  0
                     frame.setVisible(true);
 222  0
                 } catch(Exception fe) {}
 223  
             }
 224  
 
 225  
             // Invoke the main() method
 226  0
             Method mainMethod = mainClass.getDeclaredMethod("main", paramTypes);
 227  0
             mainMethod.invoke(null, paramValues);
 228  
 
 229  
             // Close the frame if it exists
 230  0
             if (frame != null && System.getProperty(ChildMain.DISPOSE_MINIMIZED_WINDOW_PROP_NAME) != null) {
 231  
                 // Exit this process. Closing or disposing of the window is not
 232  
                 // enough to allow the process to exit.
 233  0
                 System.exit(0);
 234  
             }
 235  
 
 236  0
         } catch (Throwable t) {
 237  0
             String message = t.getMessage();
 238  0
             t.printStackTrace();
 239  0
             System.exit(1);
 240  0
         }
 241  
 
 242  0
     }
 243  
 
 244  
     /**
 245  
      * A WindowAdapter subclass that causes the application to exit when its
 246  
      * {@link #windowClosing(WindowEvent)} method is invoked.
 247  
      */
 248  0
     private static class ChildWindowAdapter extends WindowAdapter {
 249  
 
 250  
         /**
 251  
          * Invoked when a window is in the process of being closed.
 252  
          *
 253  
          * @param e the event
 254  
          */
 255  
         public void windowClosing(WindowEvent e) {
 256  
 
 257  0
             System.exit(0);
 258  
 
 259  0
         }
 260  
 
 261  
     }
 262  
 
 263  
 }