# HG changeset patch # User Jaroslav Tulach # Date 1398631217 -7200 # Node ID 234fea368401c18d2b1a574e01289c337e4589ba # Parent e38025e9536a8699ca26c66ddcc5ee7f8d31b874 Initial infrastructure to export resources diff -r e38025e9536a -r 234fea368401 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java Sun Apr 27 08:33:38 2014 +0200 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java Sun Apr 27 22:40:17 2014 +0200 @@ -30,6 +30,7 @@ @Compare public String readResourceAsStream() throws Exception { InputStream is = getClass().getResourceAsStream("Resources.txt"); + assert is != null : "The stream for Resources.txt should be found"; byte[] b = new byte[30]; int len = is.read(b); StringBuilder sb = new StringBuilder(); diff -r e38025e9536a -r 234fea368401 rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Sun Apr 27 08:33:38 2014 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Sun Apr 27 22:40:17 2014 +0200 @@ -19,7 +19,6 @@ import java.io.IOException; import java.io.InputStream; -import java.net.URL; import org.apidesign.bck2brwsr.core.Exported; /** Build your own virtual machine! Use methods in this class to generate @@ -57,14 +56,16 @@ private final ObfuscationLevel level; private final StringArray rootcls; private final StringArray classes; + private final StringArray resources; private final Resources res; private final boolean extension; - private Bck2Brwsr(ObfuscationLevel level, StringArray rootcls, StringArray classes, Resources resources, boolean extension) { + private Bck2Brwsr(ObfuscationLevel level, StringArray rootcls, StringArray classes, StringArray resources, Resources res, boolean extension) { this.level = level; this.rootcls = rootcls; this.classes = classes; - this.res = resources; + this.resources = resources; + this.res = res; this.extension = extension; } @@ -102,7 +103,7 @@ * @since 0.5 */ public static Bck2Brwsr newCompiler() { - return new Bck2Brwsr(ObfuscationLevel.NONE, new StringArray(), new StringArray(), null, false); + return new Bck2Brwsr(ObfuscationLevel.NONE, new StringArray(), new StringArray(), new StringArray(), null, false); } /** Adds additional classes @@ -122,7 +123,7 @@ if (classes.length == 0) { return this; } else { - return new Bck2Brwsr(level, rootcls.addAndNew(classes), this.classes, res, + return new Bck2Brwsr(level, rootcls.addAndNew(classes), this.classes, resources, res, extension); } } @@ -142,11 +143,32 @@ if (classes.length == 0) { return this; } else { - return new Bck2Brwsr(level, rootcls, this.classes.addAndNew(classes), res, + return new Bck2Brwsr(level, rootcls, this.classes.addAndNew(classes), resources, res, extension); } } + /** These resources should be made available in the compiled file in + * binary form. These resources can then be loaded + * by {@link ClassLoader#getResource(java.lang.String)} and similar + * methods. + * + * @param resources names of the resources to be loaded by {@link Resources#get(java.lang.String)} + * @return new instance of the Bck2Brwsr compiler which inherits + * all values from this just adds few more resource names + * for processing + * @since 0.9 + */ + public Bck2Brwsr addResources(String... resources) { + if (resources.length == 0) { + return this; + } else { + return new Bck2Brwsr(level, rootcls, this.classes, + this.resources.addAndNew(resources), res, extension + ); + } + } + /** Changes the obfuscation level for the compiler by creating new instance * which inherits all values from this and adjust the level * of obfuscation. @@ -156,7 +178,7 @@ * @since 0.5 */ public Bck2Brwsr obfuscation(ObfuscationLevel level) { - return new Bck2Brwsr(level, rootcls, classes, res, extension); + return new Bck2Brwsr(level, rootcls, classes, resources, res, extension); } /** A way to change the provider of additional resources (classes) for the @@ -168,7 +190,7 @@ * @since 0.5 */ public Bck2Brwsr resources(Resources res) { - return new Bck2Brwsr(level, rootcls, classes, res, extension); + return new Bck2Brwsr(level, rootcls, classes, resources, res, extension); } /** Should one generate a library? By default the system generates @@ -183,7 +205,7 @@ * @since 0.9 */ public Bck2Brwsr library(boolean library) { - return new Bck2Brwsr(level, rootcls, classes, res, library); + return new Bck2Brwsr(level, rootcls, classes, resources, res, library); } /** A way to change the provider of additional resources (classes) for the @@ -205,10 +227,9 @@ * @since 0.5 */ public void generate(Appendable out) throws IOException { - Resources r = res != null ? res : new LdrRsrcs(Bck2Brwsr.class.getClassLoader()); if (level != ObfuscationLevel.NONE) { try { - ClosureWrapper.produceTo(out, level, r, rootcls, classes, extension); + ClosureWrapper.produceTo(out, level, this); return; } catch (IOException ex) { throw ex; @@ -218,7 +239,27 @@ } } - VM.compile(out, r, rootcls, classes, extension); + VM.compile(out, this); + } + + // + // Internal getters + // + + Resources getResources() { + return res != null ? res : new LdrRsrcs(Bck2Brwsr.class.getClassLoader()); + } + + String[] allClasses() { + return classes.addAndNew(rootcls.toArray()).toArray(); + } + + StringArray rootClasses() { + return rootcls; + } + + boolean isExtension() { + return extension; } /** Provider of resources (classes and other files). The diff -r e38025e9536a -r 234fea368401 rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java Sun Apr 27 08:33:38 2014 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java Sun Apr 27 22:40:17 2014 +0200 @@ -35,28 +35,18 @@ final class ClosureWrapper extends CommandLineRunner { private static final String[] ARGS = { "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--js", "bck2brwsr-raw.js" /*, "--debug", "--formatting", "PRETTY_PRINT" */ }; - private final Bck2Brwsr.Resources res; - private final StringArray classes; - private final boolean extension; - private final StringArray rootClasses; + private final Bck2Brwsr config; private String compiledCode; private String externsCode; - private ClosureWrapper(Appendable out, - String compilationLevel, - Bck2Brwsr.Resources res, - StringArray rootClasses, - StringArray classes, - boolean extension) { + private ClosureWrapper(Appendable out, + String compilationLevel, Bck2Brwsr config) { super( generateArguments(compilationLevel), new PrintStream(new APS(out)), System.err ); - this.res = res; - this.rootClasses = rootClasses; - this.classes = classes; - this.extension = extension; + this.config = config; } @Override @@ -99,7 +89,7 @@ if (compiledCode == null) { StringBuilder sb = new StringBuilder(); try { - VM.compile(sb, res, rootClasses, classes, extension); + VM.compile(sb, config); compiledCode = sb.toString(); } catch (IOException ex) { compiledCode = ex.getMessage(); @@ -142,17 +132,15 @@ } static int produceTo(Appendable output, - ObfuscationLevel obfuscationLevel, - Bck2Brwsr.Resources resources, - StringArray rootArr, - StringArray arr, - boolean extension) throws IOException { + ObfuscationLevel obfuscationLevel, + Bck2Brwsr config + ) throws IOException { final ClosureWrapper cw = new ClosureWrapper(output, (obfuscationLevel == ObfuscationLevel.FULL) ? "ADVANCED_OPTIMIZATIONS" : "SIMPLE_OPTIMIZATIONS", - resources, rootArr, arr, extension); + config); try { return cw.doRun(); } catch (FlagUsageException ex) { diff -r e38025e9536a -r 234fea368401 rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Sun Apr 27 08:33:38 2014 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Sun Apr 27 22:40:17 2014 +0200 @@ -64,15 +64,14 @@ } static void compile(Appendable out, - Bck2Brwsr.Resources l, - StringArray rootNames, - StringArray names, - boolean extension + Bck2Brwsr config ) throws IOException { - StringArray both = names.addAndNew(rootNames.toArray()); + String[] both = config.allClasses(); - VM vm = extension ? new Extension(out, l, both.toArray(), rootNames) - : new Standalone(out, l, rootNames); + VM vm = config.isExtension() ? + new Extension(out, config.getResources(), both, config.rootClasses()) + : + new Standalone(out, config.getResources(), config.rootClasses()); final StringArray fixedNames = new StringArray(); @@ -80,7 +79,7 @@ fixedNames.add(fixedClass.getName().replace('.', '/')); } - vm.doCompile(fixedNames.addAndNew(both.toArray())); + vm.doCompile(fixedNames.addAndNew(both)); } private void doCompile(StringArray names) throws IOException { diff -r e38025e9536a -r 234fea368401 rt/vm/src/test/java/org/apidesign/vm4brwsr/Resources.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Resources.java Sun Apr 27 22:40:17 2014 +0200 @@ -0,0 +1,40 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.vm4brwsr; + +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @author Jaroslav Tulach + */ +public class Resources { + public static String loadKO() throws IOException { + InputStream is = Resources.class.getResourceAsStream("ko.js"); + if (is == null) { + return "No resource found!"; + } + byte[] arr = new byte[4092]; + int len = is.read(arr); + if (len == -1) { + return "No data read!"; + } + return new String(arr, 0, len, "UTF-8"); + } +} diff -r e38025e9536a -r 234fea368401 rt/vm/src/test/java/org/apidesign/vm4brwsr/ResourcesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ResourcesTest.java Sun Apr 27 22:40:17 2014 +0200 @@ -0,0 +1,57 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.vm4brwsr; + +import static org.testng.Assert.*; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** Tests related to loading resources from the VM. + * + * @author Jaroslav Tulach + */ +public class ResourcesTest { + @Test public void checkNullCast() throws Exception { + String exp = Resources.loadKO(); + + assertExec("Loading a precompiled resource:", + Resources.class, "loadKO__Ljava_lang_String_2", + exp + ); + } + + private static TestVM code; + + @BeforeClass + public static void compileTheCode() throws Exception { + StringBuilder sb = new StringBuilder(); + code = TestVM.compileClassAndResources(sb, null, "org/apidesign/vm4brwsr/Resources", "org/apidesign/vm4brwsr/ko.js"); + } + @AfterClass + public static void releaseTheCode() { + code = null; + } + + private void assertExec( + String msg, Class clazz, String method, + Object ret, Object... args + ) throws Exception { + code.assertExec(msg, clazz, method, ret, args); + } +} diff -r e38025e9536a -r 234fea368401 rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Sun Apr 27 08:33:38 2014 +0200 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java Sun Apr 27 22:40:17 2014 +0200 @@ -152,6 +152,34 @@ return null; } } + + static TestVM compileClassAndResources(StringBuilder sb, ScriptEngine[] eng, String name, String... resources) throws ScriptException, IOException { + if (sb == null) { + sb = new StringBuilder(); + } + Bck2Brwsr b2b = Bck2Brwsr.newCompiler(). + resources(new EmulationResources()). + addRootClasses(name). + addResources(resources). + library(false); + b2b.generate(sb); + ScriptEngineManager sem = new ScriptEngineManager(); + ScriptEngine js = sem.getEngineByExtension("js"); + if (eng != null) { + eng[0] = js; + } + try { + Object res = js.eval(sb.toString()); + assertTrue(js instanceof Invocable, "It is invocable object: " + res); + return new TestVM((Invocable) js, sb); + } catch (Exception ex) { + if (sb.length() > 2000) { + sb = dumpJS(sb); + } + fail("Could not evaluate:" + ex.getClass() + ":" + ex.getMessage() + "\n" + sb, ex); + return null; + } + } Object loadClass(String loadClass, String name) throws ScriptException, NoSuchMethodException { return code.invokeMethod(bck2brwsr, "loadClass", Exceptions.class.getName());