001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package com.hs.mail.container; 019 020 import java.io.File; 021 import java.lang.reflect.InvocationTargetException; 022 import java.lang.reflect.Method; 023 import java.net.JarURLConnection; 024 import java.net.MalformedURLException; 025 import java.net.URI; 026 import java.net.URL; 027 import java.net.URLClassLoader; 028 import java.util.ArrayList; 029 import java.util.Arrays; 030 import java.util.Comparator; 031 import java.util.Iterator; 032 import java.util.LinkedList; 033 import java.util.List; 034 035 public class Main { 036 037 private File appHome; 038 private ClassLoader classLoader; 039 private List classpaths = new ArrayList(5); 040 041 public static void main(String[] args) { 042 Main app = new Main(); 043 044 if (args.length < 1) { 045 System.out.println("Main class was not specified"); 046 System.exit(0); 047 } 048 049 // Convert arguments to collection for easier management 050 List tokens = new LinkedList(Arrays.asList(args)); 051 String taskClass = (String) tokens.remove(0); 052 053 // Add the following to the classpath: 054 // ${app.home}/lib 055 // 056 app.addClassPath(new File(app.getAppHome(), "lib")); 057 058 try { 059 app.runTaskClass(taskClass, tokens); 060 } catch (ClassNotFoundException e) { 061 System.out.println("Could not load class: " + e.getMessage()); 062 try { 063 ClassLoader cl = app.getClassLoader(); 064 if (cl != null) { 065 System.out.println("Class loader setup: "); 066 printClassLoaderTree(cl); 067 } 068 } catch (MalformedURLException me) { 069 } 070 } catch (Throwable e) { 071 System.out.println("Failed to execute main task. Reason: " + e); 072 } 073 } 074 075 /** 076 * Print out what's in the classloader tree being used. 077 */ 078 private static int printClassLoaderTree(ClassLoader cl) { 079 int depth = 0; 080 if (cl.getParent() != null) { 081 depth = printClassLoaderTree(cl.getParent()) + 1; 082 } 083 084 StringBuffer indent = new StringBuffer(); 085 for (int i = 0; i < depth; i++) { 086 indent.append(" "); 087 } 088 089 if (cl instanceof URLClassLoader) { 090 URLClassLoader ucl = (URLClassLoader) cl; 091 System.out.println(indent + cl.getClass().getName() + " {"); 092 URL[] urls = ucl.getURLs(); 093 for (int i = 0; i < urls.length; i++) { 094 System.out.println(indent + " " + urls[i]); 095 } 096 System.out.println(indent + "}"); 097 } else { 098 System.out.println(indent + cl.getClass().getName()); 099 } 100 return depth; 101 } 102 103 public void runTaskClass(String taskClass, List tokens) throws Throwable { 104 ClassLoader cl = getClassLoader(); 105 106 // Use reflection to run the task. 107 try { 108 String[] args = (String[]) tokens.toArray(new String[tokens.size()]); 109 Class task = cl.loadClass(taskClass); 110 Method runTask = task.getMethod("main", new Class[] { String[].class }); 111 runTask.invoke(task.newInstance(), new Object[] { args }); 112 } catch (InvocationTargetException e) { 113 throw e.getCause(); 114 } 115 } 116 117 private void addClassPath(File file) { 118 classpaths.add(file); 119 } 120 121 public ClassLoader getClassLoader() throws MalformedURLException { 122 if (classLoader == null) { 123 // Setup the ClassLoader 124 classLoader = Main.class.getClassLoader(); 125 if (!classpaths.isEmpty()) { 126 ArrayList urls = new ArrayList(); 127 for (Iterator iter = classpaths.iterator(); iter.hasNext();) { 128 File dir = (File) iter.next(); 129 if (dir.isDirectory()) { 130 File[] files = dir.listFiles(); 131 if (files != null) { 132 // Sort the jars so that classpath built is 133 // consistently in the same order. Also allows us to 134 // use jar names to control classpath order. 135 Arrays.sort(files, new Comparator() { 136 public int compare(Object o1, Object o2) { 137 File f1 = (File) o1; 138 File f2 = (File) o2; 139 return f1.getName().compareTo(f2.getName()); 140 } 141 }); 142 for (int j = 0; j < files.length; j++) { 143 if (files[j].getName().endsWith(".zip") 144 || files[j].getName().endsWith(".jar")) { 145 urls.add(files[j].toURL()); 146 } 147 } 148 } 149 } 150 } 151 URL u[] = new URL[urls.size()]; 152 urls.toArray(u); 153 classLoader = new URLClassLoader(u, classLoader); 154 } 155 Thread.currentThread().setContextClassLoader(classLoader); 156 } 157 return classLoader; 158 } 159 160 public void setAppHome(File appHome) { 161 this.appHome = appHome; 162 } 163 164 public File getAppHome() { 165 if (appHome == null) { 166 if (System.getProperty("app.home") != null) { 167 appHome = new File(System.getProperty("app.home")); 168 } 169 if (appHome == null) { 170 // guess from the location of the jar 171 URL url = Main.class.getClassLoader().getResource("com/hs/mail/container/Main.class"); 172 if (url != null) { 173 try { 174 JarURLConnection jarConnection = (JarURLConnection) url.openConnection(); 175 url = jarConnection.getJarFileURL(); 176 URI baseURI = new URI(url.toString()).resolve(".."); 177 appHome = new File(baseURI).getCanonicalFile(); 178 System.setProperty("app.home", appHome.getAbsolutePath()); 179 } catch (Exception ignored) { 180 } 181 } 182 } 183 if (appHome == null) { 184 appHome = new File("../."); 185 System.setProperty("app.home", appHome.getAbsolutePath()); 186 } 187 } 188 return appHome; 189 } 190 191 }