View Javadoc

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