2 * Back 2 Browser Bytecode Translator
3 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. Look for COPYING file in the top folder.
16 * If not, see http://opensource.org/licenses/GPL-2.0.
18 package org.apidesign.vm4brwsr;
20 import java.io.BufferedWriter;
22 import java.io.FileWriter;
23 import java.io.IOException;
24 import java.io.Writer;
26 import java.net.URISyntaxException;
28 import java.util.Enumeration;
29 import java.util.jar.JarEntry;
30 import java.util.jar.JarFile;
32 /** Generator of JavaScript from bytecode of classes on classpath of the VM
35 * @author Jaroslav Tulach <jtulach@netbeans.org>
40 public static void main(String... args) throws IOException, URISyntaxException {
41 final String obfuscate = "--obfuscatelevel";
42 final String extension = "--createextension";
44 if (args.length < 2) {
45 System.err.println("Bck2Brwsr Translator from Java(tm) to JavaScript, (c) Jaroslav Tulach 2012");
46 System.err.print("Usage: java -cp ... -jar ... [");
47 System.err.print(obfuscate);
48 System.err.print(" [");
50 for (ObfuscationLevel l : ObfuscationLevel.values()) {
52 System.err.print('|');
54 System.err.print(l.name());
57 System.err.print("]] [");
58 System.err.print(extension);
59 System.err.println("] <file_to_generate_js_code_to> java/lang/Class org/your/App ...");
63 final ClassLoader mainClassLoader = Main.class.getClassLoader();
65 ObfuscationLevel obfLevel = ObfuscationLevel.NONE;
66 boolean createExtension = false;
67 StringArray classes = new StringArray();
68 String generateTo = null;
69 for (int i = 0; i < args.length; i++) {
70 if (obfuscate.equals(args[i])) { // NOI18N
73 obfLevel = ObfuscationLevel.valueOf(args[i]);
74 } catch (Exception e) {
75 System.err.print(obfuscate);
76 System.err.print(" parameter needs to be followed by one of ");
78 for (ObfuscationLevel l : ObfuscationLevel.values()) {
80 System.err.print(", ");
82 System.err.print(l.name());
90 if (extension.equals(args[i])) { // NOI18N
91 createExtension = true;
94 if (generateTo == null) {
97 collectClasses(classes, mainClassLoader, args[i]);
100 final File outputFile = new File(generateTo);
101 String moduleName = null;
102 if (createExtension) {
103 moduleName = outputFile.getName();
104 if (moduleName.endsWith(".js")) {
105 moduleName = moduleName.substring(0, moduleName.length() - 3);
108 try (Writer w = new BufferedWriter(new FileWriter(outputFile))) {
109 Bck2Brwsr.newCompiler().
110 extension(createExtension).
111 obfuscation(obfLevel).
112 addRootClasses(classes.toArray()).
113 resources(new LdrRsrcs(moduleName, mainClassLoader)).
118 private static void collectClasses(
119 final StringArray dest,
120 final ClassLoader cl, final String relativePath)
121 throws IOException, URISyntaxException {
122 final Enumeration<URL> urls = cl.getResources(relativePath);
123 if (!urls.hasMoreElements()) {
124 dest.add(relativePath);
128 final URL url = urls.nextElement();
129 switch (url.getProtocol()) {
131 collectClasses(dest, relativePath,
132 new File(new URI(url.toString())));
135 final String fullPath = url.getPath();
136 final int sepIndex = fullPath.indexOf('!');
137 final String jarFilePath =
138 (sepIndex != -1) ? fullPath.substring(0, sepIndex)
141 final URI jarUri = new URI(jarFilePath);
142 if (jarUri.getScheme().equals("file")) {
143 try (JarFile jarFile = new JarFile(new File(jarUri))) {
144 collectClasses(dest, relativePath, jarFile);
151 dest.add(relativePath);
152 } while (urls.hasMoreElements());
155 private static void collectClasses(final StringArray dest,
156 final String relativePath,
158 if (file.isDirectory()) {
159 final File[] subFiles = file.listFiles();
160 for (final File subFile: subFiles) {
162 extendPath(relativePath, subFile.getName()),
169 final String filePath = file.getPath();
170 if (filePath.endsWith(".class")) {
171 validateAndAddClass(dest, relativePath);
175 private static void collectClasses(final StringArray dest,
176 final String relativePath,
177 final JarFile jarFile) {
178 if (relativePath.endsWith(".class")) {
179 if (jarFile.getJarEntry(relativePath) != null) {
180 validateAndAddClass(dest, relativePath);
186 final String expectedPrefix =
187 relativePath.endsWith("/") ? relativePath
188 : relativePath + '/';
189 final Enumeration<JarEntry> entries = jarFile.entries();
190 while (entries.hasMoreElements()) {
191 final JarEntry entry = entries.nextElement();
192 if (!entry.isDirectory()) {
193 final String entryName = entry.getName();
194 if (entryName.startsWith(expectedPrefix)
195 && entryName.endsWith(".class")) {
196 validateAndAddClass(dest, entryName);
202 private static String extendPath(final String relativePath,
203 final String fileName) {
204 return relativePath.endsWith("/") ? relativePath + fileName
205 : relativePath + '/' + fileName;
208 private static void validateAndAddClass(final StringArray dest,
209 final String relativePath) {
210 final String className =
211 relativePath.substring(0, relativePath.length() - 6);
212 if (!className.endsWith("package-info")) {