1 package org.unicode.cldr.tool;
2 
3 import java.io.FileNotFoundException;
4 import java.io.IOException;
5 import java.lang.reflect.Method;
6 
7 import org.unicode.cldr.util.CLDRFile;
8 import org.unicode.cldr.util.CLDRTool;
9 
10 /**
11  *
12  * Implement a 'main' for the CLDR jar.
13  */
14 @CLDRTool(alias = "main", description = "The 'main' class invoked when java -jar or doubleclicking the jar.", hidden = "Hidden so as not to list itself",
15     url = Main.TOOLSURL)
16 class Main {
17     private static final String CLASS_SUFFIX = ".class";
18     private static final String MAIN = "main";
19     public static final String TOOLSURL = "http://cldr.unicode.org/tools/";
20 
main(String args[])21     public static void main(String args[]) throws Throwable {
22         if (args.length == 0) {
23             System.out.println("Usage:  [ -l | [class|alias] args ...]");
24             System.out.println("Example usage:");
25             System.out.println(" (java -jar cldr.jar ) -l          -- prints a list of ALL tool/util/test classes with a 'main()' function.");
26             System.out.println(" (java -jar cldr.jar ) org.unicode.cldr.util.XMLValidator  somefile.xml ...");
27             System.out.println(" (java -jar cldr.jar ) validate  somefile.xml ...");
28             System.out.println("For more info: " + TOOLSURL);
29             System.out.println("CLDRFile.GEN_VERSION=" + CLDRFile.GEN_VERSION);
30             System.out.println("(Use the -l option to list hidden/undocumented tools)");
31             System.out.println();
32             listClasses(false, null);
33         } else if (args.length == 1 && args[0].equals("-l")) {
34             listClasses(true, null);
35         } else {
36             final String mainClass = args[0];
37             final String args2[] = new String[args.length - 1];
38             System.arraycopy(args, 1, args2, 0, args2.length);
39             Class<?> c = null;
40 
41             try {
42                 c = Class.forName(mainClass);
43             } catch (ClassNotFoundException e) {
44                 // not found
45             }
46             if (c == null) {
47                 c = listClasses(false, mainClass);
48             }
49             if (c == null) {
50                 throw new IllegalArgumentException("Class not found and not an alias: " + mainClass);
51             }
52 
53             if (c == Main.class) {
54                 throw new IllegalArgumentException("Cowardly refusing to invoke myself recursively. Stop.");
55             }
56 
57             final java.lang.reflect.Method main = getStaticMain(c);
58 
59             System.err.println(">> " + c.getName());
60 
61             main.invoke(null, (Object) args2);
62         }
63     }
64 
65     /**
66      * @param showAll if true, include even hidden classes
67      * @param match if non-null, will return the class instead of listing it
68      * @throws IOException
69      * @throws FileNotFoundException
70      */
listClasses(boolean showAll, final String match)71     public static Class<?> listClasses(boolean showAll, final String match) throws IOException, FileNotFoundException {
72         final java.util.jar.JarInputStream jis = getJarInputStream();
73         final ClassLoader classLoader = Main.class.getClassLoader();
74         if (jis == null) {
75             return null;
76         }
77         java.util.jar.JarEntry je;
78         while ((je = jis.getNextJarEntry()) != null) {
79             final String name = je.getName();
80             if (inOuterClass(name)) {
81                 final String className = filenameToClassName(name);
82                 try {
83                     final Class<?> c = java.lang.Class.forName(className, false, classLoader);
84 
85                     if ((match != null) && showAll == false && !c.isAnnotationPresent(CLDRTool.class))
86                         continue;
87 
88                     Method method = getStaticMain(c);
89 
90                     if (method != null) { // skip classes w/o static method - even if they have an annotatoin.
91                         CLDRTool annotation = c.getAnnotation(CLDRTool.class);
92 
93                         if (match == null) {
94                             // list mode
95                             if (showAll ||
96                                 (annotation != null && annotation.hidden().length() == 0)) {
97 
98                                 if (annotation != null) {
99                                     System.out.println("" + annotation.alias() + " - " + annotation.description());
100                                     if (annotation.url().length() > 0) {
101                                         System.out.println("   <" + annotation.url() + ">");
102                                     } else {
103                                         System.out.println("   <" + TOOLSURL + annotation.alias() + ">");
104                                     }
105                                     System.out.println(" = " + className);
106                                     if (annotation.hidden().length() > 0) {
107                                         System.out.println("   HIDDEN: " + annotation.hidden());
108                                     }
109                                     System.out.println();
110                                 } else {
111                                     System.out.print("   " + className);
112                                     System.out.println(" (no @CLDRTool annotation)");
113                                 }
114                             }
115                         } else {
116                             if (match.equalsIgnoreCase(className)) {
117                                 return c; // match the classname
118                             }
119                             if (annotation != null &&
120                                 annotation.alias().length() > 0 &&
121                                 match.equalsIgnoreCase(annotation.alias())) {
122                                 return c; // match the alias
123                             }
124                         }
125                     }
126                 } catch (Throwable t) {
127                     // ignore uninstantiable.
128                     //System.out.println(t);
129                 }
130             }
131         }
132         return null; // not found or not needed.
133     }
134 
135     /**
136      * @param c
137      * @return
138      * @throws NoSuchMethodException
139      */
getStaticMain(final Class<?> c)140     public static Method getStaticMain(final Class<?> c) throws NoSuchMethodException {
141         return c.getMethod(MAIN, String[].class);
142     }
143 
144     /**
145      * @param name
146      * @return
147      */
filenameToClassName(final String name)148     public static String filenameToClassName(final String name) {
149         return name.substring(0, name.length() - (CLASS_SUFFIX.length()))
150             .replaceAll("/", ".");
151     }
152 
153     /**
154      * @param name
155      * @return
156      */
inOuterClass(final String name)157     public static boolean inOuterClass(final String name) {
158         return name.endsWith(CLASS_SUFFIX) &&
159             !name.contains("$");
160     }
161 
162     /**
163      * @return
164      * @throws IOException
165      * @throws FileNotFoundException
166      */
getJarInputStream()167     public static java.util.jar.JarInputStream getJarInputStream() throws IOException, FileNotFoundException {
168         final java.net.URL url = Main.class.getProtectionDomain().getCodeSource().getLocation();
169         if (!url.getPath().endsWith(".jar")) {
170             System.out.println("(Not inside a .jar file - no listing available.)");
171             return null;
172         }
173         if (false) System.out.println("Classes in " + url.getPath());
174         final java.util.jar.JarInputStream jis = new java.util.jar.JarInputStream(new java.io.FileInputStream(url.getPath()));
175         java.util.jar.JarEntry je = null;
176         return jis;
177     }
178 }
179