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("  quickstart");
51              System.out.println("  quickstart: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              System.out.println("      For example, 'quickstart:sandbox' will start QuickStart");
57              System.out.println("      automatically for the webapp 'sandbox'.");
58              return;
59          }
60  
61          // check the JDK version
62          String version = System.getProperty("java.version");
63          boolean jdk15 = version.indexOf("1.5") != -1;
64  
65          String javaHome = System.getProperty("java.home");
66          ArrayList<URL> urls = new ArrayList<URL>();
67          try {
68              findJars(new File("lib"), urls);
69  
70              // use all the jars in the current that aren't the src jar
71              File wd = new File(".");
72              File[] jars = wd.listFiles(new FilenameFilter() {
73                  public boolean accept(File dir, String name) {
74                      return name.endsWith(".jar") && name.indexOf("-src.") == -1;
75                  }
76              });
77              for (int i = 0; i < jars.length; i++) {
78                  File jar = jars[i];
79                  urls.add(jar.toURL());
80              }
81  
82              // ... but there might not be any (ie: we're in development in IDEA), so use this as backup
83              urls.add(new File(System.getProperty("struts.classes", "build/java")).toURL());
84              urls.add(new File(System.getProperty("xwork.classes", "../xwork/build/java/")).toURL());
85  
86              // load tools.jar from JAVA_HOME
87              File tools = new File(javaHome, "lib/tools.jar");
88              if (!tools.exists()) {
89                  // hmm, not there, how about java.home?
90                  tools = new File(javaHome, "../lib/tools.jar");
91              }
92              if (!tools.exists()) {
93                  // try the OS X common path
94                  tools = new File(javaHome, "../Classes/classes.jar");
95              }
96              if (!tools.exists()) {
97                  // try the other OS X common path
98                  tools = new File(javaHome, "../Classes/classes.jar");
99              }
100             if (!tools.exists()) {
101                 // did the user specify it by hand?
102                 String prop = System.getProperty("tools");
103                 if (prop != null) {
104                     tools = new File(prop);
105                 }
106             }
107             if (!tools.exists()) {
108                 System.out.println("Error: Could not find tools.jar! Please do one of the following: ");
109                 System.out.println("");
110                 System.out.println("        - Use the JDK's JVM (ie: c://jdk1.5.0//bin//java)");
111                 System.out.println("        - Specify JAVA_HOME to point to your JDK 1.5 home");
112                 System.out.println("        - Specify a direct path to tools.jar via, as shown below:");
113                 System.out.println("");
114                 System.out.println("       java -Dtools=/path/to/tools.jar -jar struts.jar ...");
115                 return;
116             }
117 
118             // finally, add the verified tools.jar
119             urls.add(tools.toURL());
120         } catch (MalformedURLException e) {
121             e.printStackTrace();
122             System.out.println("Could not find URLs -- see stack trace.");
123         }
124 
125         String command = args[0];
126         String[] programArgs = new String[args.length - 1];
127         System.arraycopy(args, 1, programArgs, 0, programArgs.length);
128         if (command.startsWith("quickstart:")) {
129             command = "quickstart";
130             String name = checkWebAppArgs(args);
131             programArgs = new String[]{"/" + name,
132                     "apps/" + name + "/src/main/webapp",
133                     "apps/" + name + "/src/main/java",
134                     "apps/" + name + "/src/main/resources"};
135         }
136 
137         if (command.startsWith("sitegraph:")) {
138             command = "sitegraph";
139             String name = checkWebAppArgs(args);
140             programArgs = new String[]{"-config", "apps/" + name + "/src/webapp/WEB-INF/classes",
141                     "-views", "apps/" + name + "/src/webapp",
142                     "-output", "."};
143         }
144 
145         if ("sitegraph".equals(command)) {
146             launch("org.apache.struts2.sitegraph.SiteGraph", programArgs, urls);
147         }
148     }
149 
150     private static String checkWebAppArgs(String[] args) {
151         int colon = args[0].indexOf(':');
152         String name = null;
153         try {
154             name = args[0].substring(colon + 1);
155         } catch (Exception e) {
156             //this is OK to skip
157         }
158         if (name == null || name.equals("")) {
159             System.out.println("Error: you must specify the webapp you wish");
160             System.out.println("       to deploy. The webapp name must be the");
161             System.out.println("       name of the directory found in apps/.");
162             System.out.println("");
163             System.out.println("Example: java -jar struts-core-VERSION.jar quickstart:sandbox");
164             System.exit(1);
165         }
166 
167         return name;
168     }
169 
170     private static void launch(String program, String[] programArgs, List<URL> urls) {
171         Collections.reverse(urls);
172         URL[] urlArray = urls.toArray(new URL[urls.size()]);
173         URLClassLoader cl = new MainClassLoader(urlArray);
174         Thread.currentThread().setContextClassLoader(cl);
175         try {
176             Class clazz = cl.loadClass(program);
177             Method main = clazz.getDeclaredMethod("main", new Class[]{String[].class});
178             main.invoke(null, new Object[]{programArgs});
179         } catch (Exception e) {
180             e.printStackTrace();
181         }
182     }
183 
184     private static void findJars(File file, ArrayList<URL> urls) throws MalformedURLException {
185         File[] files = file.listFiles();
186         if (files == null) {
187             return;
188         }
189 
190         for (int i = 0; i < files.length; i++) {
191             File f = files[i];
192             if (f.isDirectory()) {
193                 findJars(f, urls);
194             } else if (f.getName().endsWith(".jar")) {
195                 if (isValid(f.getName())) {
196                     urls.add(f.toURL());
197                 }
198             }
199         }
200     }
201 
202     private static boolean isValid(String name) {
203         return !"dom.jar".equals(name);
204     }
205 
206     /***
207      * Reverses the typical order of classloading to defer only to the parent if the current class loader can't be
208      * found. This is required to allow for the launcher to be embedded within struts.jar (otherwise the dependencies
209      * wouldn't be found by the system ClassLoader when invoking using "java -jar struts-core-VERSION.jar ...").
210      */
211     public static class MainClassLoader extends URLClassLoader {
212         public MainClassLoader(URL[] urls) {
213             super(urls);
214         }
215 
216         public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
217             if (name.startsWith("org.xml.") || name.startsWith("org.w3c.")
218                     || name.startsWith("java.") || name.startsWith("javax.")
219                     || name.startsWith("sun.") || name.startsWith("com.sun.")) {
220                 return super.loadClass(name, resolve);
221             }
222 
223             ClassLoader parent = getParent();
224             // First, check if the class has already been loaded
225             Class c = findLoadedClass(name);
226             if (c == null) {
227                 try {
228                     c = findClass(name);
229                 } catch (Throwable t) {
230                     // If still not found, only then ask the parent
231                     c = parent.loadClass(name);
232                 }
233             }
234             if (resolve) {
235                 resolveClass(c);
236             }
237 
238             return c;
239         }
240     }
241 }