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]);
101 File gt = new File(generateTo);
102 if (Boolean.getBoolean("skip.if.exists") && gt.isFile()) {
103 System.err.println("Skipping as " + gt + " exists.");
107 try (Writer w = new BufferedWriter(new FileWriter(gt))) {
108 Bck2Brwsr.newCompiler().
109 extension(createExtension).
110 obfuscation(obfLevel).
111 addRootClasses(classes.toArray()).
112 resources(new LdrRsrcs(mainClassLoader)).
117 private static void collectClasses(
118 final StringArray dest,
119 final ClassLoader cl, final String relativePath)
120 throws IOException, URISyntaxException {
121 final Enumeration<URL> urls = cl.getResources(relativePath);
122 if (!urls.hasMoreElements()) {
123 dest.add(relativePath);
127 final URL url = urls.nextElement();
128 switch (url.getProtocol()) {
130 collectClasses(dest, relativePath,
131 new File(new URI(url.toString())));
134 final String fullPath = url.getPath();
135 final int sepIndex = fullPath.indexOf('!');
136 final String jarFilePath =
137 (sepIndex != -1) ? fullPath.substring(0, sepIndex)
140 final URI jarUri = new URI(jarFilePath);
141 if (jarUri.getScheme().equals("file")) {
142 try (JarFile jarFile = new JarFile(new File(jarUri))) {
143 collectClasses(dest, relativePath, jarFile);
150 dest.add(relativePath);
151 } while (urls.hasMoreElements());
154 private static void collectClasses(final StringArray dest,
155 final String relativePath,
157 if (file.isDirectory()) {
158 final File[] subFiles = file.listFiles();
159 for (final File subFile: subFiles) {
161 extendPath(relativePath, subFile.getName()),
168 final String filePath = file.getPath();
169 if (filePath.endsWith(".class")) {
170 validateAndAddClass(dest, relativePath);
174 private static void collectClasses(final StringArray dest,
175 final String relativePath,
176 final JarFile jarFile) {
177 if (relativePath.endsWith(".class")) {
178 if (jarFile.getJarEntry(relativePath) != null) {
179 validateAndAddClass(dest, relativePath);
185 final String expectedPrefix =
186 relativePath.endsWith("/") ? relativePath
187 : relativePath + '/';
188 final Enumeration<JarEntry> entries = jarFile.entries();
189 while (entries.hasMoreElements()) {
190 final JarEntry entry = entries.nextElement();
191 if (!entry.isDirectory()) {
192 final String entryName = entry.getName();
193 if (entryName.startsWith(expectedPrefix)
194 && entryName.endsWith(".class")) {
195 validateAndAddClass(dest, entryName);
201 private static String extendPath(final String relativePath,
202 final String fileName) {
203 return relativePath.endsWith("/") ? relativePath + fileName
204 : relativePath + '/' + fileName;
207 private static void validateAndAddClass(final StringArray dest,
208 final String relativePath) {
209 final String className =
210 relativePath.substring(0, relativePath.length() - 6);
211 if (!className.endsWith("package-info")) {