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 try (Writer w = new BufferedWriter(new FileWriter(generateTo))) {
101 Bck2Brwsr.newCompiler().
102 extension(createExtension).
103 obfuscation(obfLevel).
104 addRootClasses(classes.toArray()).
105 resources(new LdrRsrcs(mainClassLoader)).
110 private static void collectClasses(
111 final StringArray dest,
112 final ClassLoader cl, final String relativePath)
113 throws IOException, URISyntaxException {
114 final Enumeration<URL> urls = cl.getResources(relativePath);
115 if (!urls.hasMoreElements()) {
116 dest.add(relativePath);
120 final URL url = urls.nextElement();
121 switch (url.getProtocol()) {
123 collectClasses(dest, relativePath,
124 new File(new URI(url.toString())));
127 final String fullPath = url.getPath();
128 final int sepIndex = fullPath.indexOf('!');
129 final String jarFilePath =
130 (sepIndex != -1) ? fullPath.substring(0, sepIndex)
133 final URI jarUri = new URI(jarFilePath);
134 if (jarUri.getScheme().equals("file")) {
135 try (JarFile jarFile = new JarFile(new File(jarUri))) {
136 collectClasses(dest, relativePath, jarFile);
143 dest.add(relativePath);
144 } while (urls.hasMoreElements());
147 private static void collectClasses(final StringArray dest,
148 final String relativePath,
150 if (file.isDirectory()) {
151 final File[] subFiles = file.listFiles();
152 for (final File subFile: subFiles) {
154 extendPath(relativePath, subFile.getName()),
161 final String filePath = file.getPath();
162 if (filePath.endsWith(".class")) {
163 validateAndAddClass(dest, relativePath);
167 private static void collectClasses(final StringArray dest,
168 final String relativePath,
169 final JarFile jarFile) {
170 if (relativePath.endsWith(".class")) {
171 if (jarFile.getJarEntry(relativePath) != null) {
172 validateAndAddClass(dest, relativePath);
178 final String expectedPrefix =
179 relativePath.endsWith("/") ? relativePath
180 : relativePath + '/';
181 final Enumeration<JarEntry> entries = jarFile.entries();
182 while (entries.hasMoreElements()) {
183 final JarEntry entry = entries.nextElement();
184 if (!entry.isDirectory()) {
185 final String entryName = entry.getName();
186 if (entryName.startsWith(expectedPrefix)
187 && entryName.endsWith(".class")) {
188 validateAndAddClass(dest, entryName);
194 private static String extendPath(final String relativePath,
195 final String fileName) {
196 return relativePath.endsWith("/") ? relativePath + fileName
197 : relativePath + '/' + fileName;
200 private static void validateAndAddClass(final StringArray dest,
201 final String relativePath) {
202 final String className =
203 relativePath.substring(0, relativePath.length() - 6);
204 if (!className.endsWith("package-info")) {