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 }