Save This Page
Home » apache-ant-1.8.1 » org.apache.tools » ant » launch » [javadoc | source]
    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.tools.ant.launch;
   19   
   20   import java.net.URL;
   21   import java.net.URLClassLoader;
   22   import java.net.MalformedURLException;
   23   import java.io.File;
   24   import java.util.StringTokenizer;
   25   import java.util.List;
   26   import java.util.ArrayList;
   27   import java.util.Iterator;
   28   
   29   
   30   
   31   /**
   32    * This is a launcher for Ant.
   33    *
   34    * @since Ant 1.6
   35    */
   36   public class Launcher {
   37   
   38       /**
   39        * The Ant Home (installation) Directory property.
   40        * {@value}
   41        */
   42       public static final String ANTHOME_PROPERTY = "ant.home";
   43   
   44       /**
   45        * The Ant Library Directory property.
   46        * {@value}
   47        */
   48       public static final String ANTLIBDIR_PROPERTY = "ant.library.dir";
   49   
   50       /**
   51        * The directory name of the per-user ant directory.
   52        * {@value}
   53        */
   54       public static final String ANT_PRIVATEDIR = ".ant";
   55   
   56       /**
   57        * The name of a per-user library directory.
   58        * {@value}
   59        */
   60       public static final String ANT_PRIVATELIB = "lib";
   61   
   62       /**
   63        * launch diagnostics flag; for debugging trouble at launch time.
   64        */
   65       public static boolean launchDiag = false;
   66   
   67       /**
   68        * The location of a per-user library directory.
   69        * <p>
   70        * It's value is the concatenation of {@link #ANT_PRIVATEDIR}
   71        * with {@link #ANT_PRIVATELIB}, with an appropriate file separator
   72        * in between. For example, on Unix, it's <code>.ant/lib</code>.
   73        */
   74       public static final String USER_LIBDIR =
   75           ANT_PRIVATEDIR + File.separatorChar + ANT_PRIVATELIB;
   76   
   77       /**
   78        * The startup class that is to be run.
   79        * {@value}
   80        */
   81       public static final String MAIN_CLASS = "org.apache.tools.ant.Main";
   82   
   83       /**
   84        * System property with user home directory.
   85        * {@value}
   86        */
   87       public static final String USER_HOMEDIR = "user.home";
   88   
   89       /**
   90        * System property with application classpath.
   91        * {@value}
   92        */
   93       private static final String JAVA_CLASS_PATH = "java.class.path";
   94   
   95       /**
   96        * Exit code on trouble
   97        */
   98       protected static final int EXIT_CODE_ERROR = 2;
   99   
  100       /**
  101        * Entry point for starting command line Ant.
  102        *
  103        * @param  args commandline arguments
  104        */
  105       public static void main(String[] args) {
  106           int exitCode;
  107           try {
  108               Launcher launcher = new Launcher();
  109               exitCode = launcher.run(args);
  110           } catch (LaunchException e) {
  111               exitCode = EXIT_CODE_ERROR;
  112               System.err.println(e.getMessage());
  113           } catch (Throwable t) {
  114               exitCode = EXIT_CODE_ERROR;
  115               t.printStackTrace(System.err);
  116           }
  117           if (exitCode != 0) {
  118               if (launchDiag) {
  119                   System.out.println("Exit code: "+exitCode);
  120               }
  121               System.exit(exitCode);
  122           }
  123       }
  124   
  125   
  126       /**
  127        * Add a CLASSPATH or -lib to lib path urls.
  128        * Only filesystem resources are supported.
  129        *
  130        * @param path        the classpath or lib path to add to the libPathULRLs
  131        * @param getJars     if true and a path is a directory, add the jars in
  132        *                    the directory to the path urls
  133        * @param libPathURLs the list of paths to add to
  134        * @throws MalformedURLException if we can't create a URL
  135        */
  136       private void addPath(String path, boolean getJars, List libPathURLs)
  137               throws MalformedURLException {
  138           StringTokenizer tokenizer = new StringTokenizer(path, File.pathSeparator);
  139           while (tokenizer.hasMoreElements()) {
  140               String elementName = tokenizer.nextToken();
  141               File element = new File(elementName);
  142               if (elementName.indexOf('%') != -1 && !element.exists()) {
  143                   continue;
  144               }
  145               if (getJars && element.isDirectory()) {
  146                   // add any jars in the directory
  147                   URL[] dirURLs = Locator.getLocationURLs(element);
  148                   for (int j = 0; j < dirURLs.length; ++j) {
  149                       if (launchDiag) { System.out.println("adding library JAR: " + dirURLs[j]);}
  150                       libPathURLs.add(dirURLs[j]);
  151                   }
  152               }
  153   
  154               URL url = Locator.fileToURL(element);
  155               if (launchDiag) { System.out.println("adding library URL: " + url) ;}
  156               libPathURLs.add(url);
  157           }
  158       }
  159   
  160       /**
  161        * Run the launcher to launch Ant.
  162        *
  163        * @param args the command line arguments
  164        * @return an exit code. As the normal ant main calls exit when it ends,
  165        *         this is for handling failures at bind-time
  166        * @throws MalformedURLException if the URLs required for the classloader
  167        *            cannot be created.
  168        * @throws LaunchException for launching problems
  169        */
  170       private int run(String[] args)
  171               throws LaunchException, MalformedURLException {
  172           String antHomeProperty = System.getProperty(ANTHOME_PROPERTY);
  173           File antHome = null;
  174   
  175           File sourceJar = Locator.getClassSource(getClass());
  176           File jarDir = sourceJar.getParentFile();
  177           String mainClassname = MAIN_CLASS;
  178   
  179           if (antHomeProperty != null) {
  180               antHome = new File(antHomeProperty);
  181           }
  182   
  183           if (antHome == null || !antHome.exists()) {
  184               antHome = jarDir.getParentFile();
  185               setProperty(ANTHOME_PROPERTY, antHome.getAbsolutePath());
  186           }
  187   
  188           if (!antHome.exists()) {
  189               throw new LaunchException("Ant home is set incorrectly or "
  190                   + "ant could not be located (estimated value="+antHome.getAbsolutePath()+")");
  191           }
  192   
  193           List libPaths = new ArrayList();
  194           String cpString = null;
  195           List argList = new ArrayList();
  196           String[] newArgs;
  197           boolean  noUserLib = false;
  198           boolean  noClassPath = false;
  199   
  200           for (int i = 0; i < args.length; ++i) {
  201               if (args[i].equals("-lib")) {
  202                   if (i == args.length - 1) {
  203                       throw new LaunchException("The -lib argument must "
  204                           + "be followed by a library location");
  205                   }
  206                   libPaths.add(args[++i]);
  207               } else if (args[i].equals("-cp")) {
  208                   if (i == args.length - 1) {
  209                       throw new LaunchException("The -cp argument must "
  210                           + "be followed by a classpath expression");
  211                   }
  212                   if (cpString != null) {
  213                       throw new LaunchException("The -cp argument must "
  214                           + "not be repeated");
  215                   }
  216                   cpString = args[++i];
  217               } else if (args[i].equals("--nouserlib") || args[i].equals("-nouserlib")) {
  218                   noUserLib = true;
  219               } else if (args[i].equals("--launchdiag")) {
  220                   launchDiag = true;
  221               } else if (args[i].equals("--noclasspath") || args[i].equals("-noclasspath")) {
  222                   noClassPath = true;
  223               } else if (args[i].equals("-main")) {
  224                   if (i == args.length - 1) {
  225                       throw new LaunchException("The -main argument must "
  226                               + "be followed by a library location");
  227                   }
  228                   mainClassname = args[++i];
  229               } else {
  230                   argList.add(args[i]);
  231               }
  232           }
  233   
  234           logPath("Launcher JAR",sourceJar);
  235           logPath("Launcher JAR directory", sourceJar.getParentFile());
  236           logPath("java.home", new File(System.getProperty("java.home")));
  237   
  238           //decide whether to copy the existing arg set, or
  239           //build a new one from the list of all args excluding the special
  240           //operations that only we handle
  241           if (argList.size() == args.length) {
  242               newArgs = args;
  243           } else {
  244               newArgs = (String[]) argList.toArray(new String[argList.size()]);
  245           }
  246   
  247           URL[] libURLs    = getLibPathURLs(
  248               noClassPath ? null : cpString, libPaths);
  249           URL[] systemURLs = getSystemURLs(jarDir);
  250           URL[] userURLs   = noUserLib ? new URL[0] : getUserURLs();
  251   
  252           File toolsJAR = Locator.getToolsJar();
  253           logPath("tools.jar",toolsJAR);
  254           URL[] jars = getJarArray(
  255               libURLs, userURLs, systemURLs, toolsJAR);
  256   
  257           // now update the class.path property
  258           StringBuffer baseClassPath
  259               = new StringBuffer(System.getProperty(JAVA_CLASS_PATH));
  260           if (baseClassPath.charAt(baseClassPath.length() - 1)
  261                   == File.pathSeparatorChar) {
  262               baseClassPath.setLength(baseClassPath.length() - 1);
  263           }
  264   
  265           for (int i = 0; i < jars.length; ++i) {
  266               baseClassPath.append(File.pathSeparatorChar);
  267               baseClassPath.append(Locator.fromURI(jars[i].toString()));
  268           }
  269   
  270           setProperty(JAVA_CLASS_PATH, baseClassPath.toString());
  271   
  272           URLClassLoader loader = new URLClassLoader(jars);
  273           Thread.currentThread().setContextClassLoader(loader);
  274           Class mainClass = null;
  275           int exitCode = 0;
  276           Throwable thrown=null;
  277           try {
  278               mainClass = loader.loadClass(mainClassname);
  279               AntMain main = (AntMain) mainClass.newInstance();
  280               main.startAnt(newArgs, null, null);
  281           } catch (InstantiationException ex) {
  282               System.err.println(
  283                   "Incompatible version of " + mainClassname + " detected");
  284               File mainJar = Locator.getClassSource(mainClass);
  285               System.err.println(
  286                   "Location of this class " + mainJar);
  287               thrown = ex;
  288           } catch (ClassNotFoundException cnfe) {
  289               System.err.println(
  290                       "Failed to locate" + mainClassname);
  291               thrown = cnfe;
  292           } catch (Throwable t) {
  293               t.printStackTrace(System.err);
  294               thrown=t;
  295           }
  296           if(thrown!=null) {
  297               System.err.println(ANTHOME_PROPERTY+": "+antHome.getAbsolutePath());
  298               System.err.println("Classpath: " + baseClassPath.toString());
  299               System.err.println("Launcher JAR: " + sourceJar.getAbsolutePath());
  300               System.err.println("Launcher Directory: " + jarDir.getAbsolutePath());
  301               exitCode = EXIT_CODE_ERROR;
  302           }
  303           return exitCode;
  304       }
  305   
  306       /**
  307        * Get the list of -lib entries and -cp entry into
  308        * a URL array.
  309        * @param cpString the classpath string
  310        * @param libPaths the list of -lib entries.
  311        * @return an array of URLs.
  312        * @throws MalformedURLException if the URLs  cannot be created.
  313        */
  314       private URL[] getLibPathURLs(String cpString, List libPaths)
  315           throws MalformedURLException {
  316           List libPathURLs = new ArrayList();
  317   
  318           if (cpString != null) {
  319               addPath(cpString, false, libPathURLs);
  320           }
  321   
  322           for (Iterator i = libPaths.iterator(); i.hasNext();) {
  323               String libPath = (String) i.next();
  324               addPath(libPath, true, libPathURLs);
  325           }
  326   
  327           return  (URL[]) libPathURLs.toArray(new URL[libPathURLs.size()]);
  328       }
  329   
  330       /**
  331        * Get the jar files in ANT_HOME/lib.
  332        * determine ant library directory for system jars: use property
  333        * or default using location of ant-launcher.jar
  334        * @param antLauncherDir the dir that ant-launcher ran from
  335        * @return the URLs
  336        * @throws MalformedURLException if the URLs cannot be created.
  337        */
  338       private URL[] getSystemURLs(File antLauncherDir) throws MalformedURLException {
  339           File antLibDir = null;
  340           String antLibDirProperty = System.getProperty(ANTLIBDIR_PROPERTY);
  341           if (antLibDirProperty != null) {
  342               antLibDir = new File(antLibDirProperty);
  343           }
  344           if ((antLibDir == null) || !antLibDir.exists()) {
  345               antLibDir = antLauncherDir;
  346               setProperty(ANTLIBDIR_PROPERTY, antLibDir.getAbsolutePath());
  347           }
  348           return Locator.getLocationURLs(antLibDir);
  349       }
  350   
  351       /**
  352        * Get the jar files in user.home/.ant/lib
  353        * @return the URLS from the user's lib dir
  354        * @throws MalformedURLException if the URLs cannot be created.
  355        */
  356       private URL[] getUserURLs() throws MalformedURLException {
  357           File userLibDir
  358               = new File(System.getProperty(USER_HOMEDIR), USER_LIBDIR);
  359   
  360           return Locator.getLocationURLs(userLibDir);
  361       }
  362   
  363       /**
  364        * Combine the various jar sources into a single array of jars.
  365        * @param libJars the jars specified in -lib command line options
  366        * @param userJars the jars in ~/.ant/lib
  367        * @param systemJars the jars in $ANT_HOME/lib
  368        * @param toolsJar   the tools.jar file
  369        * @return a combined array
  370        * @throws MalformedURLException if there is a problem.
  371        */
  372       private URL[] getJarArray (
  373           URL[] libJars, URL[] userJars, URL[] systemJars, File toolsJar)
  374           throws MalformedURLException {
  375           int numJars = libJars.length + userJars.length + systemJars.length;
  376           if (toolsJar != null) {
  377               numJars++;
  378           }
  379           URL[] jars = new URL[numJars];
  380           System.arraycopy(libJars, 0, jars, 0, libJars.length);
  381           System.arraycopy(userJars, 0, jars, libJars.length, userJars.length);
  382           System.arraycopy(systemJars, 0, jars, userJars.length + libJars.length,
  383               systemJars.length);
  384   
  385           if (toolsJar != null) {
  386               jars[jars.length - 1] = Locator.fileToURL(toolsJar);
  387           }
  388           return jars;
  389       }
  390   
  391       /**
  392        * set a system property, optionally log what is going on
  393        * @param name property name
  394        * @param value value
  395        */
  396       private void setProperty(String name, String value) {
  397           if (launchDiag) {
  398               System.out.println("Setting \"" + name + "\" to \"" + value + "\"");
  399           }
  400           System.setProperty(name, value);
  401       }
  402   
  403       private void logPath(String name,File path) {
  404           if(launchDiag) {
  405               System.out.println(name+"= \""+path+"\"");
  406           }
  407       }
  408   }

Save This Page
Home » apache-ant-1.8.1 » org.apache.tools » ant » launch » [javadoc | source]