View Javadoc

1   /*
2    * $Id: Main.java 454251 2006-10-09 02:10:57Z husted $
3    *
4    * Copyright 2006 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.struts2;
19  
20  import java.io.File;
21  import java.io.FilenameFilter;
22  import java.lang.reflect.Method;
23  import java.net.MalformedURLException;
24  import java.net.URL;
25  import java.net.URLClassLoader;
26  import java.util.ArrayList;
27  import java.util.Collections;
28  import java.util.List;
29  
30  /***
31   * <!-- START SNIPPET: javadoc -->
32   *
33   * Struts comes with various related tools included in the struts-core-VERSION.jar file. You can access these
34   * tools by simply unpacking the Struts distribution and running <b>java -jar struts-core-VERSION.jar</b>.
35   * Struts will automatically include all jars in the same directory as the struts-core-VERSION.jar file as well as all
36   * jars in the <i>lib</i> directory. This means you can invoke these tools either from within the standard directory
37   * structure found in the Struts distribution, or from within your WEB-INF/lib directory.
38   *
39   * <p/> You can access the help information for these tools by simply running the jar without any arguments.
40   *
41   * <!-- END SNIPPET: javadoc -->
42   */
43  public class Main {
44      public static void main(String[] args) {
45          if (args.length == 0) {
46              System.out.println("Usage:");
47              System.out.println("  java -jar struts-toolbox.jar [command] (optional command args)");
48              System.out.println("");
49              System.out.println("Where [command] is one of the following:");
50              System.out.println("  sitegraph");
51              System.out.println("  sitegraph:xxx");
52              System.out.println("");
53              System.out.println("Execute the commands for additional usage instructions.");
54              System.out.println("Note: the *:xxx commands are just shortcuts for ");
55              System.out.println("      running the command on a webapp in the apps dir.");
56              return;
57          }
58  
59          // check the JDK version
60          String version = System.getProperty("java.version");
61          boolean jdk15 = version.indexOf("1.5") != -1;
62  
63          String javaHome = System.getProperty("java.home");
64          ArrayList<URL> urls = new ArrayList<URL>();
65          try {
66              findJars(new File("lib"), urls);
67  
68              // use all the jars in the current that aren't the src jar
69              File wd = new File(".");
70              File[] jars = wd.listFiles(new FilenameFilter() {
71                  public boolean accept(File dir, String name) {
72                      return name.endsWith(".jar") && name.indexOf("-src.") == -1;
73                  }
74              });
75              for (int i = 0; i < jars.length; i++) {
76                  File jar = jars[i];
77                  urls.add(jar.toURL());
78              }
79  
80              // ... but there might not be any (ie: we're in development in IDEA), so use this as backup
81              urls.add(new File(System.getProperty("struts.classes", "build/java")).toURL());
82              urls.add(new File(System.getProperty("xwork.classes", "../xwork/build/java/")).toURL());
83  
84              // load tools.jar from JAVA_HOME
85              File tools = new File(javaHome, "lib/tools.jar");
86              if (!tools.exists()) {
87                  // hmm, not there, how about java.home?
88                  tools = new File(javaHome, "../lib/tools.jar");
89              }
90              if (!tools.exists()) {
91                  // try the OS X common path
92                  tools = new File(javaHome, "../Classes/classes.jar");
93              }
94              if (!tools.exists()) {
95                  // try the other OS X common path
96                  tools = new File(javaHome, "../Classes/classes.jar");
97              }
98              if (!tools.exists()) {
99                  // did the user specify it by hand?
100                 String prop = System.getProperty("tools");
101                 if (prop != null) {
102                     tools = new File(prop);
103                 }
104             }
105             if (!tools.exists()) {
106                 System.out.println("Error: Could not find tools.jar! Please do one of the following: ");
107                 System.out.println("");
108                 System.out.println("        - Use the JDK's JVM (ie: c://jdk1.5.0//bin//java)");
109                 System.out.println("        - Specify JAVA_HOME to point to your JDK 1.5 home");
110                 System.out.println("        - Specify a direct path to tools.jar via, as shown below:");
111                 System.out.println("");
112                 System.out.println("       java -Dtools=/path/to/tools.jar -jar struts.jar ...");
113                 return;
114             }
115 
116             // finally, add the verified tools.jar
117             urls.add(tools.toURL());
118         } catch (MalformedURLException e) {
119             e.printStackTrace();
120             System.out.println("Could not find URLs -- see stack trace.");
121         }
122 
123         String command = args[0];
124         String[] programArgs = new String[args.length - 1];
125         System.arraycopy(args, 1, programArgs, 0, programArgs.length);
126 
127         if (command.startsWith("sitegraph:")) {
128             command = "sitegraph";
129             String name = checkWebAppArgs(args);
130             programArgs = new String[]{"-config", "apps/" + name + "/src/webapp/WEB-INF/classes",
131                     "-views", "apps/" + name + "/src/webapp",
132                     "-output", "."};
133         }
134 
135         if ("sitegraph".equals(command)) {
136             launch("org.apache.struts2.sitegraph.SiteGraph", programArgs, urls);
137         }
138     }
139 
140     private static String checkWebAppArgs(String[] args) {
141         int colon = args[0].indexOf(':');
142         String name = null;
143         try {
144             name = args[0].substring(colon + 1);
145         } catch (Exception e) {
146             //this is OK to skip
147         }
148         if (name == null || name.equals("")) {
149             System.out.println("Error: you must specify the webapp you wish");
150             System.out.println("       to deploy. The webapp name must be the");
151             System.out.println("       name of the directory found in apps/.");
152             System.out.println("");
153             System.out.println("Example: java -jar struts-core-VERSION.jar quickstart:sandbox");
154             System.exit(1);
155         }
156 
157         return name;
158     }
159 
160     private static void launch(String program, String[] programArgs, List<URL> urls) {
161         Collections.reverse(urls);
162         URL[] urlArray = urls.toArray(new URL[urls.size()]);
163         URLClassLoader cl = new MainClassLoader(urlArray);
164         Thread.currentThread().setContextClassLoader(cl);
165         try {
166             Class clazz = cl.loadClass(program);
167             Method main = clazz.getDeclaredMethod("main", new Class[]{String[].class});
168             main.invoke(null, new Object[]{programArgs});
169         } catch (Exception e) {
170             e.printStackTrace();
171         }
172     }
173 
174     private static void findJars(File file, ArrayList<URL> urls) throws MalformedURLException {
175         File[] files = file.listFiles();
176         if (files == null) {
177             return;
178         }
179 
180         for (int i = 0; i < files.length; i++) {
181             File f = files[i];
182             if (f.isDirectory()) {
183                 findJars(f, urls);
184             } else if (f.getName().endsWith(".jar")) {
185                 if (isValid(f.getName())) {
186                     urls.add(f.toURL());
187                 }
188             }
189         }
190     }
191 
192     private static boolean isValid(String name) {
193         return !"dom.jar".equals(name);
194     }
195 
196     /***
197      * Reverses the typical order of classloading to defer only to the parent if the current class loader can't be
198      * found. This is required to allow for the launcher to be embedded within struts.jar (otherwise the dependencies
199      * wouldn't be found by the system ClassLoader when invoking using "java -jar struts-core-VERSION.jar ...").
200      */
201     public static class MainClassLoader extends URLClassLoader {
202         public MainClassLoader(URL[] urls) {
203             super(urls);
204         }
205 
206         public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
207             if (name.startsWith("org.xml.") || name.startsWith("org.w3c.")
208                     || name.startsWith("java.") || name.startsWith("javax.")
209                     || name.startsWith("sun.") || name.startsWith("com.sun.")) {
210                 return super.loadClass(name, resolve);
211             }
212 
213             ClassLoader parent = getParent();
214             // First, check if the class has already been loaded
215             Class c = findLoadedClass(name);
216             if (c == null) {
217                 try {
218                     c = findClass(name);
219                 } catch (Throwable t) {
220                     // If still not found, only then ask the parent
221                     c = parent.loadClass(name);
222                 }
223             }
224             if (resolve) {
225                 resolveClass(c);
226             }
227 
228             return c;
229         }
230     }
231 }