Clover coverage report - Ledge Container - SNAPSHOT
Coverage timestamp: Fri Nov 17 2006 05:16:03 CET
file stats: LOC: 287   Methods: 7
NCLOC: 157   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Main.java 50% 76.3% 57.1% 70%
coverage coverage
 1    //
 2    // Copyright (c) 2003, Caltha - Gajda, Krzewski, Mach, Potempski Sp.J.
 3    // All rights reserved.
 4    //
 5    // Redistribution and use in source and binary forms, with or without modification,
 6    // are permitted provided that the following conditions are met:
 7    //
 8    // * Redistributions of source code must retain the above copyright notice,
 9    // this list of conditions and the following disclaimer.
 10    // * Redistributions in binary form must reproduce the above copyright notice,
 11    // this list of conditions and the following disclaimer in the documentation
 12    // and/or other materials provided with the distribution.
 13    // * Neither the name of the Caltha - Gajda, Krzewski, Mach, Potempski Sp.J.
 14    // nor the names of its contributors may be used to endorse or promote products
 15    // derived from this software without specific prior written permission.
 16    //
 17    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 18    // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19    // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 20    // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 21    // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 22    // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 23    // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 24    // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 25    // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 26    // POSSIBILITY OF SUCH DAMAGE.
 27    //
 28   
 29    package org.objectledge.container;
 30   
 31    import java.lang.reflect.InvocationTargetException;
 32    import java.lang.reflect.Method;
 33   
 34    import org.apache.commons.cli.CommandLine;
 35    import org.apache.commons.cli.CommandLineParser;
 36    import org.apache.commons.cli.HelpFormatter;
 37    import org.apache.commons.cli.Options;
 38    import org.apache.commons.cli.ParseException;
 39    import org.apache.commons.cli.PosixParser;
 40    import org.apache.log4j.BasicConfigurator;
 41    import org.apache.log4j.Logger;
 42    import org.objectledge.filesystem.FileSystem;
 43    import org.picocontainer.PicoContainer;
 44   
 45    /**
 46    * Allows running Ledge applications from the command line.
 47    *
 48    * <p>
 49    * After the container is started and components are composed and configured,
 50    * a designated component is looked up and method
 51    * <code>void main(String[])</code> is invoked on it.
 52    * Note that it this mehtod should be non-static so it may take advantage of the actual
 53    * component instance composed by the container.
 54    * </p>
 55    *
 56    * <h3>Recognized commandline options</h3>
 57    * <p>
 58    * <table class="bodyTable">
 59    * <tr class="b">
 60    * <th>syntax</th>
 61    * <th>required</th>
 62    * <th>default</th>
 63    * <th width="100%">description</th>
 64    * </tr>
 65    * <tr class="a">
 66    * <td>-h</td>
 67    * <td>no</td>
 68    * <td>n/a</td>
 69    * <td>Display usage information and exit</td>
 70    * </tr>
 71    * <tr class="b">
 72    * <td>-v</td>
 73    * <td>no</td>
 74    * <td>n/a</td>
 75    * <td>Display version information on startup</td>
 76    * </tr>
 77    * <tr class="a">
 78    * <td>-r &lt;root&gt;</td>
 79    * <td>no</td>
 80    * <td>current working directory</td>
 81    * <td>Root directory of Ledge FileSystem</td>
 82    * </tr>
 83    * <tr class="b">
 84    * <td>-c &lt;config&gt;</td>
 85    * <td>no</td>
 86    * <td>/config</td>
 87    * <td>Base directory of the system's configuration</td>
 88    * </tr>
 89    * <tr class="a">
 90    * <td>&lt;class-name&gt;</td>
 91    * <td>yes</td>
 92    * <td>none</td>
 93    * <td>Class name of the component to be invoked</td>
 94    * </tr>
 95    * </table>
 96    *
 97    * <p>
 98    * Any command line arguments following the componen class name will be passed verbatim
 99    * to the component's main method.
 100    * </p>
 101    *
 102    * <h3>Dependencies</h3>
 103    * <ul>
 104    * <li><a href="http://jakarta.apache.org/commons/cli/">Jakarta Commons CLI</a></li>
 105    * </ul>
 106    *
 107    * <p>Created on Dec 22, 2003</p>
 108    * @author <a href="Rafal.Krzewski">rafal@caltha.pl</a>
 109    * @version $Id: Main.java,v 1.11 2005/07/07 08:30:02 zwierzem Exp $
 110    */
 111    public class Main
 112    {
 113    /** version string. */
 114    protected static final String VERSION = "0.1-dev";
 115   
 116    private static Options options = new Options();
 117   
 118    static
 119    {
 120  86 options.addOption("r", "root", true, "set local file system root directory");
 121  86 options.addOption("c", "config", true, "set config directory FS path");
 122  86 options.addOption("v", "version", false, "print version information");
 123  86 options.addOption("h", "help", false, "print usage information and exit");
 124    }
 125   
 126    /**
 127    * A private constructor - this class should be used statically only.
 128    */
 129  0 private Main()
 130    {
 131    // static access only (commandline runnable class)
 132    }
 133   
 134    /**
 135    * Command line entry point.
 136    *
 137    * @param args command line arguments.
 138    */
 139  86 public static void main(String[] args)
 140    {
 141  86 CommandLineParser parser = new PosixParser();
 142  86 try
 143    {
 144  86 CommandLine line = parser.parse(options, args);
 145  86 if(line.hasOption("v"))
 146    {
 147  0 printVersion();
 148    }
 149  86 if(line.hasOption("h"))
 150    {
 151  0 printUsage();
 152    }
 153    else
 154    {
 155  86 String root = line.getOptionValue("r", System.getProperty("user.dir"));
 156  86 String config = line.getOptionValue("c", "/config");
 157  86 int componentArgCount = line.getArgList().size()-1;
 158  86 if(componentArgCount < 0)
 159    {
 160  0 System.err.println("component class name required");
 161    }
 162    else
 163    {
 164  86 String componentClassName = (String)line.getArgList().get(0);
 165  86 String[] componentArgs = new String[componentArgCount];
 166  86 line.getArgList().subList(1, componentArgCount).toArray(componentArgs);
 167  86 run(root, config, componentClassName, componentArgs);
 168    }
 169    }
 170    }
 171    catch(ParseException exp)
 172    {
 173  0 System.err.println("Command line parsing failed: " + exp.getMessage());
 174    }
 175    }
 176   
 177    /**
 178    * Prints version information.
 179    */
 180  0 protected static void printVersion()
 181    {
 182  0 System.out.println("ObjectLedge "+VERSION);
 183    }
 184   
 185    /**
 186    * Prints usage infomration and exits.
 187    */
 188  0 protected static void printUsage()
 189    {
 190  0 HelpFormatter formatter = new HelpFormatter();
 191  0 formatter.printHelp("ledge", options);
 192    }
 193   
 194    /**
 195    * Runns LedgeContainer.
 196    *
 197    * @param root the file system root.
 198    * @param config the configuration base directory.
 199    * @param componentClassName the component to invoke.
 200    * @param componentArgs the component arguments.
 201    */
 202  86 public static void run(String root, String config, String componentClassName,
 203    String[] componentArgs)
 204    {
 205  86 BasicConfigurator.configure();
 206  86 Logger log = Logger.getLogger(Main.class);
 207  86 PicoContainer container = null;
 208  86 try
 209    {
 210  86 FileSystem fs = FileSystem.getStandardFileSystem(root);
 211  86 LedgeContainer ledgeContainer = new LedgeContainer(fs, config,
 212    Main.class.getClassLoader());
 213  86 container = ledgeContainer.getContainer();
 214  86 addShutdownHook(ledgeContainer);
 215    }
 216    catch(Exception e)
 217    {
 218  0 log.error("Container composition failed", e);
 219    }
 220  86 Class componentClass = null;
 221  86 Object component = null;
 222  86 if(container != null)
 223    {
 224  86 try
 225    {
 226  86 componentClass = Class.forName(componentClassName);
 227  86 component = container.getComponentInstance(componentClass);
 228  86 if(component == null)
 229    {
 230  0 log.error("Component "+componentClassName+" is missing from the assembly");
 231    }
 232    }
 233    catch(ClassNotFoundException e)
 234    {
 235  0 log.error("Component class "+componentClassName+" cannot be loaded", e);
 236    }
 237    }
 238  86 Method method = null;
 239  86 if(componentClass != null)
 240    {
 241  86 try
 242    {
 243  86 method = componentClass.getMethod("main",
 244    new Class[] { (new String[0]).getClass() });
 245    }
 246    catch(NoSuchMethodException e)
 247    {
 248  0 log.error("Component class "+componentClassName+
 249    " does not declare main(String[]) method", e);
 250    }
 251    }
 252  86 if(method != null)
 253    {
 254  86 try
 255    {
 256  86 method.invoke(component, new Object[] { componentArgs });
 257    }
 258    catch(InvocationTargetException e)
 259    {
 260  0 log.error("Invocation of "+componentClassName+".main(String[]) threw exception",
 261    e.getTargetException());
 262    }
 263    catch(Exception e)
 264    {
 265  0 log.error("Failed to invoke "+componentClassName+".main(String[])", e);
 266    }
 267    }
 268    }
 269   
 270  86 private static void addShutdownHook(final LedgeContainer ledgeContainer)
 271    {
 272    // add a shutdown hook that will tell the builder to kill it.
 273  86 Runnable shutdownHook = new Runnable() {
 274  84 public void run() {
 275  84 System.out.println("Shutting Down NanoContainer");
 276  83 try {
 277  83 ledgeContainer.killContainer();
 278    } catch (Exception e) {
 279  0 e.printStackTrace();
 280    } finally {
 281  78 System.out.println("Exiting VM");
 282    }
 283    }
 284    };
 285  86 Runtime.getRuntime().addShutdownHook(new Thread(shutdownHook));
 286    }
 287    }