001 /** 002 * Launcher.java 003 * jCOLIBRI2 framework. 004 * @author Juan A. Recio-García. 005 * GAIA - Group for Artificial Intelligence Applications 006 * http://gaia.fdi.ucm.es 007 * 10/01/2007 008 */ 009 package jcolibri.util; 010 011 import java.io.File; 012 import java.io.IOException; 013 import java.lang.reflect.Method; 014 import java.net.URL; 015 import java.net.URLClassLoader; 016 017 import javax.xml.parsers.DocumentBuilder; 018 import javax.xml.parsers.DocumentBuilderFactory; 019 020 import org.w3c.dom.Document; 021 import org.w3c.dom.NamedNodeMap; 022 import org.w3c.dom.Node; 023 import org.w3c.dom.NodeList; 024 025 026 /** 027 * This class launches a jCOLIBRI application loading dinamically its libraries. 028 * It has a method that parses the ".classpath" file of the eclipse project to find the libraries that a project needs. 029 * Then it loads the libraries and executes an application. 030 * This eases the process of invoking a jCOLIBRI application. 031 * 032 * @author Juan A. Recio Garcia 033 * @version 2.0 034 */ 035 public class Launcher 036 { 037 038 /** 039 * Main method used to launch any application loading the libraries from a eclipse classpath file. 040 * The first argument must be the class to launch and the second (optional) is the name of the eclipse classpath file. 041 * If this second argument is not specified it tries with ".classpath". 042 */ 043 public static void main(String[] args) 044 { 045 if(args.length == 0) 046 { 047 System.out.println("Usage: jcolibri.util.Launcher MainClass [eclipse_classpath_file]"); 048 System.exit(0); 049 } 050 051 try { 052 String classpathfile = ".classpath"; 053 if(args.length==2) 054 classpathfile = args[1]; 055 056 System.out.println("Loading class path from file: "+classpathfile); 057 058 URL[] libraries = getClassPath(classpathfile); 059 for(int i=0; i<libraries.length; i++) 060 { 061 addURLtoClassLoader(libraries[i]); 062 System.out.println("Adding library: "+libraries[i]); 063 } 064 065 Class<?> mainClass = Class.forName(args[0]); 066 org.apache.commons.logging.LogFactory.getLog(Launcher.class).info("Executing class: "+args[0]); 067 Method mainMethod = mainClass.getMethod("main", args.getClass()); 068 069 String[] newargs = new String[args.length-1]; 070 for(int i=1; i<args.length; i++) 071 newargs[i-1] = args[1]; 072 073 Object[] methodparams = new Object[1]; 074 methodparams[0] = newargs; 075 mainMethod.invoke(null, methodparams); 076 } catch (Exception e) { 077 org.apache.commons.logging.LogFactory.getLog(Launcher.class).error("Launching class "+ e.getMessage()); 078 e.printStackTrace(); 079 } 080 org.apache.commons.logging.LogFactory.getLog(Launcher.class).info("Launch finished"); 081 //System.exit(0); 082 } 083 084 /** 085 * Loads a resource pointed by a URL into the Class Loader. 086 */ 087 public static void addURLtoClassLoader(URL u) throws IOException { 088 URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader(); 089 Class<URLClassLoader> sysclass = URLClassLoader.class; 090 091 try { 092 //Please don't read this code. It is a dark way to invoke a private method using reflection. 093 //The clear way consists on creating your own subclass of URLClassLoader. 094 Class[] parameters = new Class[]{URL.class}; 095 Method method = sysclass.getDeclaredMethod("addURL",parameters); 096 method.setAccessible(true); 097 method.invoke(sysloader,new Object[]{ u }); 098 } catch (Throwable t) { 099 t.printStackTrace(); 100 throw new IOException("Error, could not add URL to system classloader"); 101 }//end try catch 102 }//end method 103 104 /** 105 * Parses a eclipse classpath file returning a list of URLs to the libraries in that file. 106 */ 107 protected static URL[] getClassPath(String classpathfile) throws Exception 108 { 109 110 java.util.ArrayList<URL> CLASSPATH = new java.util.ArrayList<URL>(); 111 try 112 { 113 DocumentBuilder db = DocumentBuilderFactory.newInstance() 114 .newDocumentBuilder(); 115 Document doc = db.parse(classpathfile); 116 117 NodeList nl = doc.getElementsByTagName("classpathentry"); 118 for(int i=0; i<nl.getLength(); i++) 119 { 120 Node n = nl.item(i); 121 NamedNodeMap nnm = n.getAttributes(); 122 if(nnm.getNamedItem("kind").getNodeValue().equals("lib")) 123 { 124 String lib = nnm.getNamedItem("path").getNodeValue(); 125 File f = new File(lib); 126 CLASSPATH.add(f.toURI().toURL()); 127 } 128 } 129 } catch (Exception e) 130 { 131 org.apache.commons.logging.LogFactory.getLog(Launcher.class).error("Error obtaining classpath. Revise your classpath file \n"+e.getMessage()); 132 throw e; 133 } 134 135 return (URL[])CLASSPATH.toArray(new URL[]{}); 136 } 137 138 }