View Javadoc

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