# HG changeset patch # User Jaroslav Tulach # Date 1358968608 -3600 # Node ID 388e48c0a37aff48e7dd17e93611f5151c09541d # Parent 029e6eed60e91b10b133a921f30cda5cec704348# Parent 38696181ea53318f867b4329bb2c02fe395c1c8e Merging default branch into emul to continue experiments with the emulation project layout diff -r 029e6eed60e9 -r 388e48c0a37a .hgignore --- a/.hgignore Thu Oct 11 06:15:22 2012 -0700 +++ b/.hgignore Wed Jan 23 20:16:48 2013 +0100 @@ -1,4 +1,4 @@ ^target/.* .*/target/.* .*orig$ - +.*~ diff -r 029e6eed60e9 -r 388e48c0a37a COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,15 @@ +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. diff -r 029e6eed60e9 -r 388e48c0a37a benchmarks/matrix-multiplication/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/benchmarks/matrix-multiplication/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,56 @@ + + + 4.0.0 + + org.apidesign.bck2brwsr + matrix.multiplication + 0.3-SNAPSHOT + jar + + Matrix multiplication + + + UTF-8 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + + + org.apidesign.bck2brwsr + emul + 0.3-SNAPSHOT + + + org.testng + testng + 6.5.2 + test + + + junit + junit + + + + + org.apidesign.bck2brwsr + vmtest + 0.3-SNAPSHOT + test + + + diff -r 029e6eed60e9 -r 388e48c0a37a benchmarks/matrix-multiplication/src/main/java/org/apidesign/benchmark/matrixmul/Matrix.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/benchmarks/matrix-multiplication/src/main/java/org/apidesign/benchmark/matrixmul/Matrix.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,108 @@ +/** + * 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.benchmark.matrixmul; + +import java.io.IOException; +import java.util.Arrays; + +public class Matrix { + private final int rank; + private final float data[][]; + + public Matrix(int r) { + this(r, new float[r][r]); + } + + private Matrix(int r, float[][] data) { + this.rank = r; + this.data = data; + } + + public void setElement(int i, int j, float value) { + data[i][j] = value; + } + public float getElement(int i, int j) { + return data[i][j]; + } + + public void generateData() { + //final Random rand = new Random(); + //final int x = 10; + for (int i = 0; i < rank; i++) { + for (int j = 0; j < rank; j++) { + data[i][j] = 1 / (1 + i + j); + } + } + } + + public Matrix multiply(Matrix m) { + if (rank != m.rank) { + throw new IllegalArgumentException("Rank doesn't match"); + } + + final float res[][] = new float[rank][rank]; + for (int i = 0; i < rank; i++) { + for (int j = 0; j < rank; j++) { + float ij = 0; + for (int q = 0; q < rank; q++) { + ij += data[i][q] * m.data[q][j]; + } + res[i][j] = ij; + } + } + return new Matrix(rank, res); + } + + public void printOn(Appendable s) throws IOException { + for (int i = 0; i < rank; i++) { + String sep = ""; + for (int j = 0; j < rank; j++) { + s.append(sep + data[i][j]); + sep = " "; + } + s.append("\n"); + } + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Matrix) { + Matrix snd = (Matrix)obj; + if (snd.rank != rank) { + return false; + } + for (int i = 0; i < rank; i++) { + for (int j = 0; j < rank; j++) { + if (data[i][j] != snd.data[i][j]) { + return false; + } + } + } + return true; + } + return false; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 97 * hash + this.rank; + hash = 97 * hash + Arrays.deepHashCode(this.data); + return hash; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a benchmarks/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/benchmarks/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -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.benchmark.matrixmul; + +import java.io.IOException; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class MatrixTest { + public MatrixTest() { + } + + @Compare(scripting = false) + public String tenThousandIterations() throws IOException { + + Matrix m1 = new Matrix(5); + Matrix m2 = new Matrix(5); + + m1.generateData(); + m2.generateData(); + + Matrix res = null; + for (int i = 0; i < 10000; i++) { + res = m1.multiply(m2); + m1 = res; + } + + StringBuilder sb = new StringBuilder(); + res.printOn(sb); + return sb.toString(); + } + + @Factory + public static Object[] create() { + return VMTest.create(MatrixTest.class); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a benchmarks/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/benchmarks/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,17 @@ + + + 4.0.0 + + bck2brwsr + org.apidesign + 0.3-SNAPSHOT + + org.apidesign.bck2brwsr + benchmarks + 0.3-SNAPSHOT + pom + Performance benchmarks + + matrix-multiplication + + diff -r 029e6eed60e9 -r 388e48c0a37a core/pom.xml --- a/core/pom.xml Thu Oct 11 06:15:22 2012 -0700 +++ b/core/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -5,14 +5,27 @@ org.apidesign bck2brwsr - 1.0-SNAPSHOT + 0.3-SNAPSHOT org.apidesign.bck2brwsr core - 1.0-SNAPSHOT - core + 0.3-SNAPSHOT + Core JS Annotations http://maven.apache.org - + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + UTF-8 @@ -22,5 +35,11 @@ 3.8.1 test + + org.netbeans.api + org-openide-util-lookup + + Contains esential annotations for associating JavaScript code with +methods and classes. diff -r 029e6eed60e9 -r 388e48c0a37a core/src/main/java/org/apidesign/bck2brwsr/core/ExtraJavaScript.java --- a/core/src/main/java/org/apidesign/bck2brwsr/core/ExtraJavaScript.java Thu Oct 11 06:15:22 2012 -0700 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/ExtraJavaScript.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,3 +1,20 @@ +/** + * 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.bck2brwsr.core; import java.lang.annotation.ElementType; diff -r 029e6eed60e9 -r 388e48c0a37a core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java --- a/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java Thu Oct 11 06:15:22 2012 -0700 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,6 +1,19 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. +/** + * 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.bck2brwsr.core; diff -r 029e6eed60e9 -r 388e48c0a37a core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptOnly.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptOnly.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,37 @@ +/** + * 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.bck2brwsr.core; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Don't include given field or method in generated JavaScript. Rather + * generate completely independent JavaScript code. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.CLASS) +@Target({ ElementType.METHOD, ElementType.FIELD }) +public @interface JavaScriptOnly { + /** name of the variable to assign given value to */ + String name() default ""; + /** value to assign to given field */ + String value() default ""; +} diff -r 029e6eed60e9 -r 388e48c0a37a core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptPrototype.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptPrototype.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,44 @@ +/** + * 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.bck2brwsr.core; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Controls how JavaScript inheritance should be handled. + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.CLASS) +@Target({ ElementType.TYPE }) +public @interface JavaScriptPrototype { + /** Expression that identifies the function where all methods + * should be added into. If this attribute is unspecified + * all methods are added to the same object specified by + * {@link #prototype()}. + * + * @return name of function to contain methods found in given class + */ + String container() default ""; + /** Expression that defines the way to construct prototype for this + * class. + * @return expression to construct prototype + */ + String prototype(); +} diff -r 029e6eed60e9 -r 388e48c0a37a core/src/main/java/org/apidesign/bck2brwsr/core/NoJavaScript.java --- a/core/src/main/java/org/apidesign/bck2brwsr/core/NoJavaScript.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -package org.apidesign.bck2brwsr.core; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** Don't include given field or method in generated JavaScript. - * - * @author Jaroslav Tulach - */ -@Retention(RetentionPolicy.CLASS) -@Target({ ElementType.METHOD, ElementType.FIELD }) -public @interface NoJavaScript { - -} diff -r 029e6eed60e9 -r 388e48c0a37a core/src/main/java/org/apidesign/bck2brwsr/core/impl/JavaScriptProcesor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/impl/JavaScriptProcesor.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,92 @@ +/** + * 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.bck2brwsr.core.impl; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Completion; +import javax.annotation.processing.Completions; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.tools.Diagnostic; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author Jaroslav Tulach + */ +@ServiceProvider(service = Processor.class) +public final class JavaScriptProcesor extends AbstractProcessor { + @Override + public Set getSupportedAnnotationTypes() { + Set set = new HashSet<>(); + set.add(JavaScriptBody.class.getName()); + return set; + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) { + if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) { + continue; + } + ExecutableElement ee = (ExecutableElement)e; + List params = ee.getParameters(); + + JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class); + String[] arr = jsb.args(); + if (params.size() != arr.length) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e); + } + } + return true; + } + + @Override + public Iterable getCompletions(Element e, + AnnotationMirror annotation, ExecutableElement member, String userText + ) { + StringBuilder sb = new StringBuilder(); + if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) { + ExecutableElement ee = (ExecutableElement) e; + String sep = ""; + sb.append("{ "); + for (VariableElement ve : ee.getParameters()) { + sb.append(sep).append('"').append(ve.getSimpleName()) + .append('"'); + sep = ", "; + } + sb.append(" }"); + return Collections.nCopies(1, Completions.of(sb.toString())); + } + return null; + } + + +} diff -r 029e6eed60e9 -r 388e48c0a37a dew/nbactions.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/nbactions.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,56 @@ + + + + + run + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + -classpath %classpath org.apidesign.bck2brwsr.dew.Dew + java + + + + debug + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + -Xdebug -Xrunjdwp:transport=dt_socket,server=n,address=${jpda.address} -classpath %classpath org.apidesign.bck2brwsr.dew.Dew + java + true + + + + profile + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + ${profiler.args} -classpath %classpath org.apidesign.bck2brwsr.dew.Dew + ${profiler.java} + + + diff -r 029e6eed60e9 -r 388e48c0a37a dew/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,64 @@ + + + 4.0.0 + + org.apidesign + bck2brwsr + 0.3-SNAPSHOT + + org.apidesign.bck2brwsr + dew + 0.3-SNAPSHOT + Development Environment for Web + http://maven.apache.org + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + UTF-8 + + + + org.glassfish.grizzly + grizzly-http-server + 2.2.19 + + + ${project.groupId} + vm4brwsr + ${project.version} + + + org.json + json + 20090211 + + + org.testng + testng + test + + + junit + junit + + + + + ${project.groupId} + javaquery.api + ${project.version} + + + diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/Compile.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,196 @@ +/** + * 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.bck2brwsr.dew; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +/** + * + * @author Jaroslav Tulach + */ +final class Compile implements DiagnosticListener { + private final List> errors = new ArrayList<>(); + private final Map classes; + private final String pkg; + private final String cls; + + private Compile(String html, String code) throws IOException { + this.pkg = findPkg(code); + this.cls = findCls(code); + classes = compile(html, code); + } + + /** Performs compilation of given HTML page and associated Java code + */ + public static Compile create(String html, String code) throws IOException { + return new Compile(html, code); + } + + /** Checks for given class among compiled resources */ + public byte[] get(String res) { + return classes.get(res); + } + + /** Obtains errors created during compilation. + */ + public List> getErrors() { + List> err = new ArrayList<>(); + for (Diagnostic diagnostic : errors) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + err.add(diagnostic); + } + } + return err; + } + + private Map compile(final String html, final String code) throws IOException { + StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null); + + final Map class2BAOS = new HashMap<>(); + + JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) { + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return code; + } + }; + final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) { + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return html; + } + + @Override + public InputStream openInputStream() throws IOException { + return new ByteArrayInputStream(html.getBytes()); + } + }; + + final URI scratch; + try { + scratch = new URI("mem://mem3"); + } catch (URISyntaxException ex) { + throw new IOException(ex); + } + + JavaFileManager jfm = new ForwardingJavaFileManager(sjfm) { + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { + if (kind == Kind.CLASS) { + final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + class2BAOS.put(className.replace('.', '/') + ".class", buffer); + return new SimpleJavaFileObject(sibling.toUri(), kind) { + @Override + public OutputStream openOutputStream() throws IOException { + return buffer; + } + }; + } + + if (kind == Kind.SOURCE) { + return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) { + private final ByteArrayOutputStream data = new ByteArrayOutputStream(); + @Override + public OutputStream openOutputStream() throws IOException { + return data; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + data.close(); + return new String(data.toByteArray()); + } + }; + } + + throw new IllegalStateException(); + } + + @Override + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { + if (location == StandardLocation.SOURCE_PATH) { + if (packageName.equals(pkg)) { + return htmlFile; + } + } + + return null; + } + + }; + + ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call(); + + Map result = new HashMap<>(); + + for (Map.Entry e : class2BAOS.entrySet()) { + result.put(e.getKey(), e.getValue().toByteArray()); + } + + return result; + } + + + @Override + public void report(Diagnostic diagnostic) { + errors.add(diagnostic); + } + private static String findPkg(String java) throws IOException { + Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE); + Matcher m = p.matcher(java); + if (!m.find()) { + throw new IOException("Can't find package declaration in the java file"); + } + String pkg = m.group(1); + return pkg; + } + private static String findCls(String java) throws IOException { + Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE); + Matcher m = p.matcher(java); + if (!m.find()) { + throw new IOException("Can't find package declaration in the java file"); + } + String cls = m.group(1); + return cls; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/Dew.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,138 @@ +/** + * 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.bck2brwsr.dew; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.List; +import java.util.Locale; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import org.apidesign.vm4brwsr.Bck2Brwsr; +import org.glassfish.grizzly.http.Method; +import org.glassfish.grizzly.http.server.HttpHandler; +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.grizzly.http.server.Request; +import org.glassfish.grizzly.http.server.Response; +import org.glassfish.grizzly.http.util.HttpStatus; +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONTokener; + +/** + * + * @author phrebejk + */ +final class Dew extends HttpHandler implements Bck2Brwsr.Resources { + private String html = ""; + private Compile data; + + public static void main(String... args) throws Exception { + DewLauncher l = new DewLauncher(null); + l.addClassLoader(DewLauncher.class.getClassLoader()); + final Dew dew = new Dew(); + HttpServer s = l.initServer(dew); + s.getServerConfiguration().addHttpHandler(dew, "/dew/"); + l.launchServerAndBrwsr(s, "/dew/"); + System.in.read(); + } + + @Override + public void service(Request request, Response response) throws Exception { + + if ( request.getMethod() == Method.POST ) { + InputStream is = request.getInputStream(); + JSONTokener tok = new JSONTokener(new InputStreamReader(is)); + JSONObject obj = new JSONObject(tok); + String tmpHtml = obj.getString("html"); + String tmpJava = obj.getString("java"); + + Compile res = Compile.create(tmpHtml, tmpJava); + List> err = res.getErrors(); + if (err.isEmpty()) { + data = res; + html = tmpHtml; + response.getOutputStream().write("[]".getBytes()); + response.setStatus(HttpStatus.OK_200); + } else { + + JSONArray errors = new JSONArray(); + + for (Diagnostic d : err) { + JSONObject e = new JSONObject(); + e.put("col", d.getColumnNumber()); + e.put("line", d.getLineNumber()); + e.put("kind", d.getKind().toString()); + e.put("msg", d.getMessage(Locale.ENGLISH)); + errors.put(e); + } + + errors.write(response.getWriter()); + response.setStatus(HttpStatus.PRECONDITION_FAILED_412); + } + + return; + } + + String r = request.getHttpHandlerPath(); + if (r == null || r.equals("/")) { + r = "index.html"; + } + if (r.equals("/result.html")) { + response.setContentType("text/html"); + response.getOutputBuffer().write(html); + response.setStatus(HttpStatus.OK_200); + return; + } + + if (r.startsWith("/")) { + r = r.substring(1); + } + + if (r.endsWith(".html") || r.endsWith(".xhtml")) { + response.setContentType("text/html"); + } + OutputStream os = response.getOutputStream(); + try (InputStream is = Dew.class.getResourceAsStream(r) ) { + copyStream(is, os, request.getRequestURL().toString() ); + } catch (IOException ex) { + response.setDetailMessage(ex.getLocalizedMessage()); + response.setError(); + response.setStatus(404); + } + } + + static void copyStream(InputStream is, OutputStream os, String baseURL) throws IOException { + for (;;) { + int ch = is.read(); + if (ch == -1) { + break; + } + os.write(ch); + } + } + + @Override + public InputStream get(String r) throws IOException { + byte[] arr = data == null ? null : data.get(r); + return arr == null ? null : new ByteArrayInputStream(arr); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/java/org/apidesign/bck2brwsr/dew/DewLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/java/org/apidesign/bck2brwsr/dew/DewLauncher.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,201 @@ +/** + * 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.bck2brwsr.dew; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apidesign.vm4brwsr.Bck2Brwsr; +import org.glassfish.grizzly.PortRange; +import org.glassfish.grizzly.http.server.HttpHandler; +import org.glassfish.grizzly.http.server.HttpServer; +import org.glassfish.grizzly.http.server.NetworkListener; +import org.glassfish.grizzly.http.server.Request; +import org.glassfish.grizzly.http.server.Response; +import org.glassfish.grizzly.http.server.ServerConfiguration; + +/** + * Lightweight server to launch dew - the Development Environment for Web. + */ +final class DewLauncher { + private static final Logger LOG = Logger.getLogger(DewLauncher.class.getName()); + private Set loaders = new LinkedHashSet<>(); + private Set xRes = new LinkedHashSet<>(); + private final Res resources = new Res(); + private final String cmd; + + public DewLauncher(String cmd) { + this.cmd = cmd; + } + + public void addClassLoader(ClassLoader url) { + this.loaders.add(url); + } + + final HttpServer initServer(Bck2Brwsr.Resources... extraResources) { + xRes.addAll(Arrays.asList(extraResources)); + + HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535)); + + final ServerConfiguration conf = s.getServerConfiguration(); + conf.addHttpHandler(new VM(resources), "/bck2brwsr.js"); + conf.addHttpHandler(new VMInit(), "/vm.js"); + conf.addHttpHandler(new Classes(resources), "/classes/"); + return s; + } + + final Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException { + server.start(); + NetworkListener listener = server.getListeners().iterator().next(); + int port = listener.getPort(); + + URI uri = new URI("http://localhost:" + port + page); + LOG.log(Level.INFO, "Showing {0}", uri); + if (cmd == null) { + try { + LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] { + System.getProperty("java.vm.name"), + System.getProperty("java.vm.vendor"), + System.getProperty("java.vm.version"), + }); + java.awt.Desktop.getDesktop().browse(uri); + LOG.log(Level.INFO, "Desktop.browse successfully finished"); + return null; + } catch (UnsupportedOperationException ex) { + LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage()); + LOG.log(Level.FINE, null, ex); + } + } + { + String cmdName = cmd == null ? "xdg-open" : cmd; + String[] cmdArr = { + cmdName, uri.toString() + }; + LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr)); + final Process process = Runtime.getRuntime().exec(cmdArr); + return new Object[] { process, null }; + } + } + + private class Res implements Bck2Brwsr.Resources { + @Override + public InputStream get(String resource) throws IOException { + for (ClassLoader l : loaders) { + URL u = null; + Enumeration en = l.getResources(resource); + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u != null) { + return u.openStream(); + } + } + for (Bck2Brwsr.Resources r : xRes) { + InputStream is = r.get(resource); + if (is != null) { + return is; + } + } + throw new IOException("Can't find " + resource); + } + } + + private static class VM extends HttpHandler { + private final Res loader; + + public VM(Res loader) { + this.loader = loader; + } + + @Override + public void service(Request request, Response response) throws Exception { + response.setCharacterEncoding("UTF-8"); + response.setContentType("text/javascript"); + Bck2Brwsr.generate(response.getWriter(), loader); + } + } + private static class VMInit extends HttpHandler { + public VMInit() { + } + + @Override + public void service(Request request, Response response) throws Exception { + response.setCharacterEncoding("UTF-8"); + response.setContentType("text/javascript"); + response.getWriter().append( + "function ldCls(res) {\n" + + " var request = new XMLHttpRequest();\n" + + " request.open('GET', '/classes/' + res, false);\n" + + " request.send();\n" + + " var arr = eval('(' + request.responseText + ')');\n" + + " return arr;\n" + + "}\n" + + "var vm = new bck2brwsr(ldCls);\n"); + } + } + + private static class Classes extends HttpHandler { + private final Res loader; + + public Classes(Res loader) { + this.loader = loader; + } + + @Override + public void service(Request request, Response response) throws Exception { + String res = request.getHttpHandlerPath(); + if (res.startsWith("/")) { + res = res.substring(1); + } + try (InputStream is = loader.get(res)) { + response.setContentType("text/javascript"); + Writer w = response.getWriter(); + w.append("["); + for (int i = 0;; i++) { + int b = is.read(); + if (b == -1) { + break; + } + if (i > 0) { + w.append(", "); + } + if (i % 20 == 0) { + w.write("\n"); + } + if (b > 127) { + b = b - 256; + } + w.append(Integer.toString(b)); + } + w.append("\n]"); + } catch (IOException ex) { + response.setError(); + response.setDetailMessage(ex.getMessage()); + } + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/css/app.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/css/app.css Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,54 @@ +/* app css stylesheet */ +.code-editor, .mono-font, .CodeMirror { + font-family: "Inconsolata","Monaco","Consolas","Andale Mono","Bitstream Vera Sans Mono","Courier New",Courier,monospace; + font-size: 13px; + line-height: 15px; +} + +.CodeMirror { + border: 1px solid #d9edf7; + height: 300px; +} + +.CodeMirror-scroll { + overflow-y: auto; + overflow-x: auto; +} + +.error-hover:hover { + text-decoration: underline; + cursor: pointer; +} + +.ic-html5 { + display: inline-block; + height: 20px; + width: 20px; + vertical-align: text-bottom; + background-repeat: no-repeat; + background-image: url("../img/html5.png"); +} + +.ic-java { + display: inline-block; + height: 20px; + width: 20px; + vertical-align: text-bottom; + background-repeat: no-repeat; + background-image: url("../img/java.png"); + +} + +.issues { + width: 16px; +} + +.issue { + height: 16px; + width: 16px; + vertical-align: middle; + background-repeat: no-repeat; + background-image: url("../img/error.png"); + /* color: #822; */ +} + diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/css/bootstrap-combined.min.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/css/bootstrap-combined.min.css Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,18 @@ +/*! + * Bootstrap v2.2.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover{color:#808080}.text-warning{color:#c09853}a.text-warning:hover{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover{color:#2d6987}.text-success{color:#468847}a.text-success:hover{color:#356635}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:25px}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{margin-bottom:5px;font-size:0;white-space:nowrap}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success td{background-color:#dff0d8}.table tbody tr.error td{background-color:#f2dede}.table tbody tr.warning td{background-color:#fcf8e3}.table tbody tr.info td{background-color:#d9edf7}.table-hover tbody tr.success:hover td{background-color:#d0e9c6}.table-hover tbody tr.error:hover td{background-color:#ebcccc}.table-hover tbody tr.warning:hover td{background-color:#faf2cc}.table-hover tbody tr.info:hover td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .disabled>a,.dropdown-menu .disabled>a:hover{color:#999}.dropdown-menu .disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #bbb;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#a2a2a2;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#c5c5c5;border-color:rgba(0,0,0,0.15) rgba(0,0,0,0.15) rgba(0,0,0,0.25)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret{border-top-color:#555;border-bottom-color:#555}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-3px}.tooltip.right{margin-left:3px}.tooltip.bottom{margin-top:3px}.tooltip.left{margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;width:236px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media .pull-left{margin-right:10px}.media .pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} +/*! + * Bootstrap Responsive v2.2.2 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */@-ms-viewport{width:device-width}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/error.png Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/error.png has changed diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/glyphicons-halflings-white.png Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/glyphicons-halflings-white.png has changed diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/glyphicons-halflings.png Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/glyphicons-halflings.png has changed diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/html5.png Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/html5.png has changed diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/java.png Binary file dew/src/main/resources/org/apidesign/bck2brwsr/dew/img/java.png has changed diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/index.html Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,98 @@ + + + + + Back2Browser - DEW + + + + + + + + + + + +
+ +
 
+ +
+
+ + +
HTML5
+
+ +
+ {{doc.modelError.toString()}} +
+
+
+ +
+ + +
Java
+
+ +
+ {{doc.modelError.toString()}} +
+
+
+ +
+ + + + + + + + +
{{e.line}}:{{e.col}}{{e.msg}}
+ + +
 
+ + + + + + + +
+ + + + + + + + diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/angular/angular.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/angular/angular.min.js Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,159 @@ +/* + AngularJS v1.0.3 + (c) 2010-2012 Google, Inc. http://angularjs.org + License: MIT +*/ +(function(U,ca,p){'use strict';function m(b,a,c){var d;if(b)if(N(b))for(d in b)d!="prototype"&&d!="length"&&d!="name"&&b.hasOwnProperty(d)&&a.call(c,b[d],d);else if(b.forEach&&b.forEach!==m)b.forEach(a,c);else if(L(b)&&wa(b.length))for(d=0;d=0&&b.splice(c,1);return a}function V(b,a){if(oa(b)||b&&b.$evalAsync&&b.$watch)throw B("Can't copy Window or Scope");if(a){if(b=== +a)throw B("Can't copy equivalent objects or arrays");if(J(b)){for(;a.length;)a.pop();for(var c=0;c2?ia.call(arguments,2):[];return N(a)&&!(a instanceof RegExp)?c.length? +function(){return arguments.length?a.apply(b,c.concat(ia.call(arguments,0))):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}:a}function ic(b,a){var c=a;/^\$+/.test(b)?c=p:oa(a)?c="$WINDOW":a&&ca===a?c="$DOCUMENT":a&&a.$evalAsync&&a.$watch&&(c="$SCOPE");return c}function da(b,a){return JSON.stringify(b,ic,a?" ":null)}function nb(b){return F(b)?JSON.parse(b):b}function Wa(b){b&&b.length!==0?(b=E(""+b),b=!(b=="f"||b=="0"||b=="false"||b=="no"||b=="n"||b=="[]")):b=!1; +return b}function pa(b){b=u(b).clone();try{b.html("")}catch(a){}return u("
").append(b).html().match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+E(b)})}function Xa(b){var a={},c,d;m((b||"").split("&"),function(b){b&&(c=b.split("="),d=decodeURIComponent(c[0]),a[d]=v(c[1])?decodeURIComponent(c[1]):!0)});return a}function ob(b){var a=[];m(b,function(b,d){a.push(Ya(d,!0)+(b===!0?"":"="+Ya(b,!0)))});return a.length?a.join("&"):""}function Za(b){return Ya(b,!0).replace(/%26/gi,"&").replace(/%3D/gi, +"=").replace(/%2B/gi,"+")}function Ya(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(a?null:/%20/g,"+")}function jc(b,a){function c(a){a&&d.push(a)}var d=[b],e,g,i=["ng:app","ng-app","x-ng-app","data-ng-app"],f=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;m(i,function(a){i[a]=!0;c(ca.getElementById(a));a=a.replace(":","\\:");b.querySelectorAll&&(m(b.querySelectorAll("."+a),c),m(b.querySelectorAll("."+a+"\\:"),c),m(b.querySelectorAll("["+ +a+"]"),c))});m(d,function(a){if(!e){var b=f.exec(" "+a.className+" ");b?(e=a,g=(b[2]||"").replace(/\s+/g,",")):m(a.attributes,function(b){if(!e&&i[b.name])e=a,g=b.value})}});e&&a(e,g?[g]:[])}function pb(b,a){b=u(b);a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");var c=qb(a);c.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,i){a.$apply(function(){b.data("$injector",i);c(b)(a)})}]);return c}function $a(b,a){a=a||"_";return b.replace(kc, +function(b,d){return(d?a:"")+b.toLowerCase()})}function qa(b,a,c){if(!b)throw new B("Argument '"+(a||"?")+"' is "+(c||"required"));return b}function ra(b,a,c){c&&J(b)&&(b=b[b.length-1]);qa(N(b),a,"not a function, got "+(b&&typeof b=="object"?b.constructor.name||"Object":typeof b));return b}function lc(b){function a(a,b,e){return a[b]||(a[b]=e())}return a(a(b,"angular",Object),"module",function(){var b={};return function(d,e,g){e&&b.hasOwnProperty(d)&&(b[d]=null);return a(b,d,function(){function a(c, +d,e){return function(){b[e||"push"]([c,d,arguments]);return j}}if(!e)throw B("No module: "+d);var b=[],c=[],k=a("$injector","invoke"),j={_invokeQueue:b,_runBlocks:c,requires:e,name:d,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:k,run:function(a){c.push(a); +return this}};g&&k(g);return j})}})}function rb(b){return b.replace(mc,function(a,b,d,e){return e?d.toUpperCase():d}).replace(nc,"Moz$1")}function ab(b,a){function c(){var e;for(var b=[this],c=a,i,f,h,k,j,l;b.length;){i=b.shift();f=0;for(h=i.length;f 
"+b;a.removeChild(a.firstChild);bb(this,a.childNodes);this.remove()}else bb(this,b)}function cb(b){return b.cloneNode(!0)}function sa(b){sb(b);for(var a=0,b=b.childNodes||[];a-1}function vb(b,a){a&&m(a.split(" "),function(a){b.className= +R((" "+b.className+" ").replace(/[\n\t]/g," ").replace(" "+R(a)+" "," "))})}function wb(b,a){a&&m(a.split(" "),function(a){if(!Ca(b,a))b.className=R(b.className+" "+R(a))})}function bb(b,a){if(a)for(var a=!a.nodeName&&v(a.length)&&!oa(a)?a:[a],c=0;c4096&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!"),W.length>20&&c.warn("Cookie '"+a+"' possibly not set or overflowed because too many cookies were already set ("+W.length+ +" > 20 )")}else{if(h.cookie!==y){y=h.cookie;d=y.split("; ");W={};for(f=0;f0&&(W[unescape(e.substring(0,k))]=unescape(e.substring(k+1)))}return W}};f.defer=function(a,b){var c;n++;c=l(function(){delete r[c];e(a)},b||0);r[c]=!0;return c};f.defer.cancel=function(a){return r[a]?(delete r[a],o(a),e(D),!0):!1}}function wc(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new vc(b,d,a,c)}]}function xc(){this.$get=function(){function b(b, +d){function e(a){if(a!=l){if(o){if(o==a)o=a.n}else o=a;g(a.n,a.p);g(a,l);l=a;l.n=null}}function g(a,b){if(a!=b){if(a)a.p=b;if(b)b.n=a}}if(b in a)throw B("cacheId "+b+" taken");var i=0,f=x({},d,{id:b}),h={},k=d&&d.capacity||Number.MAX_VALUE,j={},l=null,o=null;return a[b]={put:function(a,b){var c=j[a]||(j[a]={key:a});e(c);t(b)||(a in h||i++,h[a]=b,i>k&&this.remove(o.key))},get:function(a){var b=j[a];if(b)return e(b),h[a]},remove:function(a){var b=j[a];if(b){if(b==l)l=b.p;if(b==o)o=b.n;g(b.n,b.p);delete j[a]; +delete h[a];i--}},removeAll:function(){h={};i=0;j={};l=o=null},destroy:function(){j=f=h=null;delete a[b]},info:function(){return x({},f,{size:i})}}}var a={};b.info=function(){var b={};m(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function yc(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Bb(b){var a={},c="Directive",d=/^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,e=/(([\d\w\-_]+)(?:\:([^;]+))?;?)/,g="Template must have exactly one root element. was: "; +this.directive=function f(d,e){F(d)?(qa(e,"directive"),a.hasOwnProperty(d)||(a[d]=[],b.factory(d+c,["$injector","$exceptionHandler",function(b,c){var e=[];m(a[d],function(a){try{var f=b.invoke(a);if(N(f))f={compile:I(f)};else if(!f.compile&&f.link)f.compile=I(f.link);f.priority=f.priority||0;f.name=f.name||d;f.require=f.require||f.controller&&f.name;f.restrict=f.restrict||"A";e.push(f)}catch(k){c(k)}});return e}])),a[d].push(e)):m(d,mb(f));return this};this.$get=["$injector","$interpolate","$exceptionHandler", +"$http","$templateCache","$parse","$controller","$rootScope",function(b,h,k,j,l,o,r,n){function w(a,b,c){a instanceof u||(a=u(a));m(a,function(b,c){b.nodeType==3&&(a[c]=u(b).wrap("").parent()[0])});var d=s(a,b,a,c);return function(b,c){qa(b,"scope");var e=c?ua.clone.call(a):a;e.data("$scope",b);q(e,"ng-scope");c&&c(e,b);d&&d(b,e,e);return e}}function q(a,b){try{a.addClass(b)}catch(c){}}function s(a,b,c,d){function e(a,c,d,k){for(var g,h,j,n,o,l=0,r=0,q=f.length;lz.priority)break;if(Y=z.scope)M("isolated scope",C,z,y),L(Y)&&(q(y,"ng-isolate-scope"),C=z),q(y,"ng-scope"),s=s||z;H=z.name;if(Y=z.controller)t=t||{},M("'"+H+"' controller",t[H],z,y),t[H]=z;if(Y=z.transclude)M("transclusion",D,z,y),D=z,n=z.priority,Y=="element"?(X=u(b),y=c.$$element=u("<\!-- "+H+": "+c[H]+" --\>"),b=y[0],Ga(e,u(X[0]),b),v=w(X,d,n)):(X=u(cb(b)).contents(),y.html(""),v=w(X,d));if(Y=z.template)if(M("template",A,z,y),A=z,Y=Ha(Y),z.replace){X=u("
"+R(Y)+"
").contents(); +b=X[0];if(X.length!=1||b.nodeType!==1)throw new B(g+Y);Ga(e,y,b);H={$attr:{}};a=a.concat(O(b,a.splice(E+1,a.length-(E+1)),H));K(c,H);G=a.length}else y.html(Y);if(z.templateUrl)M("template",A,z,y),A=z,j=W(a.splice(E,a.length-E),j,y,c,e,z.replace,v),G=a.length;else if(z.compile)try{x=z.compile(y,c,v),N(x)?f(null,x):x&&f(x.pre,x.post)}catch(I){k(I,pa(y))}if(z.terminal)j.terminal=!0,n=Math.max(n,z.priority)}j.scope=s&&s.scope;j.transclude=D&&v;return j}function A(d,e,g,h){var j=!1;if(a.hasOwnProperty(e))for(var n, +e=b.get(e+c),o=0,l=e.length;on.priority)&&n.restrict.indexOf(g)!=-1)d.push(n),j=!0}catch(r){k(r)}return j}function K(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;m(a,function(d,e){e.charAt(0)!="$"&&(b[e]&&(d+=(e==="style"?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});m(b,function(b,f){f=="class"?(q(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):f=="style"?e.attr("style",e.attr("style")+";"+b):f.charAt(0)!="$"&&!a.hasOwnProperty(f)&&(a[f]=b,d[f]=c[f])})}function W(a,b,c,d,e, +f,k){var h=[],n,o,r=c[0],q=a.shift(),w=x({},q,{controller:null,templateUrl:null,transclude:null,scope:null});c.html("");j.get(q.templateUrl,{cache:l}).success(function(j){var l,q,j=Ha(j);if(f){q=u("
"+R(j)+"
").contents();l=q[0];if(q.length!=1||l.nodeType!==1)throw new B(g+j);j={$attr:{}};Ga(e,c,l);O(l,a,j);K(d,j)}else l=r,c.html(j);a.unshift(w);n=C(a,c,d,k);for(o=s(c.contents(),k);h.length;){var ba=h.pop(),j=h.pop();q=h.pop();var y=h.pop(),m=l;q!==r&&(m=cb(l),Ga(j,u(q),m));n(function(){b(o, +y,m,e,ba)},y,m,e,ba)}h=null}).error(function(a,b,c,d){throw B("Failed to load template: "+d.url);});return function(a,c,d,e,f){h?(h.push(c),h.push(d),h.push(e),h.push(f)):n(function(){b(o,c,d,e,f)},c,d,e,f)}}function y(a,b){return b.priority-a.priority}function M(a,b,c,d){if(b)throw B("Multiple directives ["+b.name+", "+c.name+"] asking for "+a+" on: "+pa(d));}function H(a,b){var c=h(b,!0);c&&a.push({priority:0,compile:I(function(a,b){var d=b.parent(),e=d.data("$binding")||[];e.push(c);q(d.data("$binding", +e),"ng-binding");a.$watch(c,function(a){b[0].nodeValue=a})})})}function X(a,b,c,d){var e=h(c,!0);e&&b.push({priority:100,compile:I(function(a,b,c){b=c.$$observers||(c.$$observers={});d==="class"&&(e=h(c[d],!0));c[d]=p;(b[d]||(b[d]=[])).$$inter=!0;(c.$$observers&&c.$$observers[d].$$scope||a).$watch(e,function(a){c.$set(d,a)})})})}function Ga(a,b,c){var d=b[0],e=d.parentNode,f,g;if(a){f=0;for(g=a.length;f0){var e=M[0],f=e.text;if(f==a||f==b||f==c||f==d||!a&&!b&&!c&&!d)return e}return!1}function f(b,c,d,f){return(b=i(b,c,d,f))?(a&&!b.json&&e("is not valid json",b),M.shift(),b):!1}function h(a){f(a)||e("is unexpected, expecting ["+a+"]",i())}function k(a,b){return function(c,d){return a(c,d,b)}}function j(a,b,c){return function(d,e){return b(d,e,a,c)}}function l(){for(var a=[];;)if(M.length>0&&!i("}",")",";","]")&&a.push(v()),!f(";"))return a.length==1?a[0]:function(b,c){for(var d, +e=0;e","<=",">="))a=j(a,b.fn,q());return a}function s(){for(var a=m(),b;b=f("*","/","%");)a=j(a,b.fn,m());return a}function m(){var a;return f("+")?C():(a=f("-"))?j(W,a.fn,m()):(a=f("!"))?k(a.fn,m()):C()}function C(){var a;if(f("("))a=v(),h(")");else if(f("["))a=A();else if(f("{"))a=K();else{var b=f();(a=b.fn)||e("not a primary expression",b)}for(var c;b=f("(","[",".");)b.text==="("?(a=u(a,c),c=null):b.text==="["?(c=a,a=ea(a)):b.text==="."?(c=a,a=t(a)):e("IMPOSSIBLE"); +return a}function A(){var a=[];if(g().text!="]"){do a.push(H());while(f(","))}h("]");return function(b,c){for(var d=[],e=0;e1;d++){var e=a.shift(),g= +b[e];g||(g={},b[e]=g);b=g}return b[a.shift()]=c}function fb(b,a,c){if(!a)return b;for(var a=a.split("."),d,e=b,g=a.length,i=0;i7),hasEvent:function(c){if(c=="input"&&aa==9)return!1;if(t(a[c])){var e=b.document.createElement("div");a[c]="on"+c in e}return a[c]},csp:!1}}]}function Uc(){this.$get=I(U)}function Mb(b){var a={},c,d,e;if(!b)return a;m(b.split("\n"),function(b){e=b.indexOf(":");c=E(R(b.substr(0, +e)));d=R(b.substr(e+1));c&&(a[c]?a[c]+=", "+d:a[c]=d)});return a}function Nb(b){var a=L(b)?b:p;return function(c){a||(a=Mb(b));return c?a[E(c)]||null:a}}function Ob(b,a,c){if(N(c))return c(b,a);m(c,function(c){b=c(b,a)});return b}function Vc(){var b=/^\s*(\[|\{[^\{])/,a=/[\}\]]\s*$/,c=/^\)\]\}',?\n/,d=this.defaults={transformResponse:[function(d){F(d)&&(d=d.replace(c,""),b.test(d)&&a.test(d)&&(d=nb(d,!0)));return d}],transformRequest:[function(a){return L(a)&&Sa.apply(a)!=="[object File]"?da(a):a}], +headers:{common:{Accept:"application/json, text/plain, */*","X-Requested-With":"XMLHttpRequest"},post:{"Content-Type":"application/json;charset=utf-8"},put:{"Content-Type":"application/json;charset=utf-8"}}},e=this.responseInterceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(a,b,c,h,k,j){function l(a){function c(a){var b=x({},a,{data:Ob(a.data,a.headers,f)});return 200<=a.status&&a.status<300?b:k.reject(b)}a.method=la(a.method);var e=a.transformRequest|| +d.transformRequest,f=a.transformResponse||d.transformResponse,h=d.headers,h=x({"X-XSRF-TOKEN":b.cookies()["XSRF-TOKEN"]},h.common,h[E(a.method)],a.headers),e=Ob(a.data,Nb(h),e),g;t(a.data)&&delete h["Content-Type"];g=o(a,e,h);g=g.then(c,c);m(w,function(a){g=a(g)});g.success=function(b){g.then(function(c){b(c.data,c.status,c.headers,a)});return g};g.error=function(b){g.then(null,function(c){b(c.data,c.status,c.headers,a)});return g};return g}function o(b,c,d){function e(a,b,c){m&&(200<=a&&a<300?m.put(w, +[a,b,Mb(c)]):m.remove(w));f(b,a,c);h.$apply()}function f(a,c,d){c=Math.max(c,0);(200<=c&&c<300?j.resolve:j.reject)({data:a,status:c,headers:Nb(d),config:b})}function i(){var a=za(l.pendingRequests,b);a!==-1&&l.pendingRequests.splice(a,1)}var j=k.defer(),o=j.promise,m,p,w=r(b.url,b.params);l.pendingRequests.push(b);o.then(i,i);b.cache&&b.method=="GET"&&(m=L(b.cache)?b.cache:n);if(m)if(p=m.get(w))if(p.then)return p.then(i,i),p;else J(p)?f(p[1],p[0],V(p[2])):f(p,200,{});else m.put(w,o);p||a(b.method, +w,c,e,d,b.timeout,b.withCredentials);return o}function r(a,b){if(!b)return a;var c=[];ec(b,function(a,b){a==null||a==p||(L(a)&&(a=da(a)),c.push(encodeURIComponent(b)+"="+encodeURIComponent(a)))});return a+(a.indexOf("?")==-1?"?":"&")+c.join("&")}var n=c("$http"),w=[];m(e,function(a){w.push(F(a)?j.get(a):j.invoke(a))});l.pendingRequests=[];(function(a){m(arguments,function(a){l[a]=function(b,c){return l(x(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){m(arguments,function(a){l[a]= +function(b,c,d){return l(x(d||{},{method:a,url:b,data:c}))}})})("post","put");l.defaults=d;return l}]}function Wc(){this.$get=["$browser","$window","$document",function(b,a,c){return Xc(b,Yc,b.defer,a.angular.callbacks,c[0],a.location.protocol.replace(":",""))}]}function Xc(b,a,c,d,e,g){function i(a,b){var c=e.createElement("script"),d=function(){e.body.removeChild(c);b&&b()};c.type="text/javascript";c.src=a;aa?c.onreadystatechange=function(){/loaded|complete/.test(c.readyState)&&d()}:c.onload=c.onerror= +d;e.body.appendChild(c)}return function(e,h,k,j,l,o,r){function n(a,c,d,e){c=(h.match(Fb)||["",g])[1]=="file"?d?200:404:c;a(c==1223?204:c,d,e);b.$$completeOutstandingRequest(D)}b.$$incOutstandingRequestCount();h=h||b.url();if(E(e)=="jsonp"){var p="_"+(d.counter++).toString(36);d[p]=function(a){d[p].data=a};i(h.replace("JSON_CALLBACK","angular.callbacks."+p),function(){d[p].data?n(j,200,d[p].data):n(j,-2);delete d[p]})}else{var q=new a;q.open(e,h,!0);m(l,function(a,b){a&&q.setRequestHeader(b,a)}); +var s;q.onreadystatechange=function(){q.readyState==4&&n(j,s||q.status,q.responseText,q.getAllResponseHeaders())};if(r)q.withCredentials=!0;q.send(k||"");o>0&&c(function(){s=-1;q.abort()},o)}}}function Zc(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"}, +DATETIME_FORMATS:{MONTH:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),SHORTMONTH:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),DAY:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),SHORTDAY:"Sun,Mon,Tue,Wed,Thu,Fri,Sat".split(","),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a", +shortTime:"h:mm a"},pluralCat:function(b){return b===1?"one":"other"}}}}function $c(){this.$get=["$rootScope","$browser","$q","$exceptionHandler",function(b,a,c,d){function e(e,f,h){var k=c.defer(),j=k.promise,l=v(h)&&!h,f=a.defer(function(){try{k.resolve(e())}catch(a){k.reject(a),d(a)}l||b.$apply()},f),h=function(){delete g[j.$$timeoutId]};j.$$timeoutId=f;g[f]=k;j.then(h,h);return j}var g={};e.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),a.defer.cancel(b.$$timeoutId)): +!1};return e}]}function Pb(b){function a(a,e){return b.factory(a+c,e)}var c="Filter";this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+c)}}];a("currency",Qb);a("date",Rb);a("filter",ad);a("json",bd);a("limitTo",cd);a("lowercase",dd);a("number",Sb);a("orderBy",Tb);a("uppercase",ed)}function ad(){return function(b,a){if(!(b instanceof Array))return b;var c=[];c.check=function(a){for(var b=0;b-1;case "object":for(var c in a)if(c.charAt(0)!=="$"&&d(a[c],b))return!0;return!1;case "array":for(c=0;ce+1?i="0":(f=i,k=!0)}if(!k){i=(i.split(Vb)[1]||"").length;t(e)&&(e=Math.min(Math.max(a.minFrac,i),a.maxFrac));var i=Math.pow(10,e),b=Math.round(b*i)/i,b=(""+b).split(Vb),i=b[0],b=b[1]||"",k=0,j=a.lgSize,l=a.gSize;if(i.length>=j+l)for(var k=i.length-j,o=0;o0||e>-c)e+=c;e===0&&c==-12&&(e=12);return ib(e,a,d)}}function La(b,a){return function(c,d){var e=c["get"+b](),g=la(a?"SHORT"+b:b);return d[g][e]}}function Rb(b){function a(a){var b; +if(b=a.match(c)){var a=new Date(0),g=0,i=0;b[9]&&(g=G(b[9]+b[10]),i=G(b[9]+b[11]));a.setUTCFullYear(G(b[1]),G(b[2])-1,G(b[3]));a.setUTCHours(G(b[4]||0)-g,G(b[5]||0)-i,G(b[6]||0),G(b[7]||0))}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var g="",i=[],f,h,e=e||"mediumDate",e=b.DATETIME_FORMATS[e]||e;F(c)&&(c=fd.test(c)?G(c):a(c));wa(c)&&(c=new Date(c));if(!na(c))return c;for(;e;)(h=gd.exec(e))?(i=i.concat(ia.call(h, +1)),e=i.pop()):(i.push(e),e=null);m(i,function(a){f=hd[a];g+=f?f(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function bd(){return function(b){return da(b,!0)}}function cd(){return function(b,a){if(!(b instanceof Array))return b;var a=G(a),c=[],d,e;if(!b||!(b instanceof Array))return c;a>b.length?a=b.length:a<-b.length&&(a=-b.length);a>0?(d=0,e=a):(d=b.length+a,e=b.length);for(;dl?(d.$setValidity("maxlength", +!1),p):(d.$setValidity("maxlength",!0),a)};d.$parsers.push(c);d.$formatters.push(c)}}function jb(b,a){b="ngClass"+b;return S(function(c,d,e){function g(b,d){if(a===!0||c.$index%2===a)d&&b!==d&&i(d),f(b)}function i(a){L(a)&&!J(a)&&(a=Ta(a,function(a,b){if(a)return b}));d.removeClass(J(a)?a.join(" "):a)}function f(a){L(a)&&!J(a)&&(a=Ta(a,function(a,b){if(a)return b}));a&&d.addClass(J(a)?a.join(" "):a)}c.$watch(e[b],g,!0);e.$observe("class",function(){var a=c.$eval(e[b]);g(a,a)});b!=="ngClass"&&c.$watch("$index", +function(d,g){var j=d%2;j!==g%2&&(j==a?f(c.$eval(e[b])):i(c.$eval(e[b])))})})}var E=function(b){return F(b)?b.toLowerCase():b},la=function(b){return F(b)?b.toUpperCase():b},B=U.Error,aa=G((/msie (\d+)/.exec(E(navigator.userAgent))||[])[1]),u,ja,ia=[].slice,Ra=[].push,Sa=Object.prototype.toString,Yb=U.angular||(U.angular={}),ta,Cb,Z=["0","0","0"];D.$inject=[];ma.$inject=[];Cb=aa<9?function(b){b=b.nodeName?b:b[0];return b.scopeName&&b.scopeName!="HTML"?la(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName? +b.nodeName:b[0].nodeName};var kc=/[A-Z]/g,id={full:"1.0.3",major:1,minor:0,dot:3,codeName:"bouncy-thunder"},Ba=Q.cache={},Aa=Q.expando="ng-"+(new Date).getTime(),oc=1,Zb=U.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},db=U.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)},mc=/([\:\-\_]+(.))/g,nc=/^moz([A-Z])/,ua=Q.prototype={ready:function(b){function a(){c||(c=!0,b())} +var c=!1;this.bind("DOMContentLoaded",a);Q(U).bind("load",a)},toString:function(){var b=[];m(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return b>=0?u(this[b]):u(this[this.length+b])},length:0,push:Ra,sort:[].sort,splice:[].splice},Ea={};m("multiple,selected,checked,disabled,readOnly,required".split(","),function(b){Ea[E(b)]=b});var zb={};m("input,select,option,textarea,button,form".split(","),function(b){zb[la(b)]=!0});m({data:ub,inheritedData:Da,scope:function(b){return Da(b, +"$scope")},controller:xb,injector:function(b){return Da(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Ca,css:function(b,a,c){a=rb(a);if(v(c))b.style[a]=c;else{var d;aa<=8&&(d=b.currentStyle&&b.currentStyle[a],d===""&&(d="auto"));d=d||b.style[a];aa<=8&&(d=d===""?p:d);return d}},attr:function(b,a,c){var d=E(a);if(Ea[d])if(v(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||D).specified?d:p;else if(v(c))b.setAttribute(a, +c);else if(b.getAttribute)return b=b.getAttribute(a,2),b===null?p:b},prop:function(b,a,c){if(v(c))b[a]=c;else return b[a]},text:x(aa<9?function(b,a){if(b.nodeType==1){if(t(a))return b.innerText;b.innerText=a}else{if(t(a))return b.nodeValue;b.nodeValue=a}}:function(b,a){if(t(a))return b.textContent;b.textContent=a},{$dv:""}),val:function(b,a){if(t(a))return b.value;b.value=a},html:function(b,a){if(t(a))return b.innerHTML;for(var c=0,d=b.childNodes;c":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a, +c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Lc={n:"\n",f:"\u000c",r:"\r",t:"\t",v:"\u000b","'":"'",'"':'"'},hb={},Yc=U.XMLHttpRequest||function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(a){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(c){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(d){}throw new B("This browser does not support XMLHttpRequest."); +};Pb.$inject=["$provide"];Qb.$inject=["$locale"];Sb.$inject=["$locale"];var Vb=".",hd={yyyy:P("FullYear",4),yy:P("FullYear",2,0,!0),y:P("FullYear",1),MMMM:La("Month"),MMM:La("Month",!0),MM:P("Month",2,1),M:P("Month",1,1),dd:P("Date",2),d:P("Date",1),HH:P("Hours",2),H:P("Hours",1),hh:P("Hours",2,-12),h:P("Hours",1,-12),mm:P("Minutes",2),m:P("Minutes",1),ss:P("Seconds",2),s:P("Seconds",1),EEEE:La("Day"),EEE:La("Day",!0),a:function(a,c){return a.getHours()<12?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=a.getTimezoneOffset(); +return ib(a/60,2)+ib(Math.abs(a%60),2)}},gd=/((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,fd=/^\d+$/;Rb.$inject=["$locale"];var dd=I(E),ed=I(la);Tb.$inject=["$parse"];var jd=I({restrict:"E",compile:function(a,c){c.href||c.$set("href","");return function(a,c){c.bind("click",function(a){if(!c.attr("href"))return a.preventDefault(),!1})}}}),kb={};m(Ea,function(a,c){var d=fa("ng-"+c);kb[d]=function(){return{priority:100,compile:function(){return function(a,g,i){a.$watch(i[d], +function(a){i.$set(c,!!a)})}}}}});m(["src","href"],function(a){var c=fa("ng-"+a);kb[c]=function(){return{priority:99,link:function(d,e,g){g.$observe(c,function(c){c&&(g.$set(a,c),aa&&e.prop(a,c))})}}}});var Oa={$addControl:D,$removeControl:D,$setValidity:D,$setDirty:D};Wb.$inject=["$element","$attrs","$scope"];var Ra=function(a){return["$timeout",function(c){var d={name:"form",restrict:"E",controller:Wb,compile:function(){return{pre:function(a,d,i,f){if(!i.action){var h=function(a){a.preventDefault? +a.preventDefault():a.returnValue=!1};Zb(d[0],"submit",h);d.bind("$destroy",function(){c(function(){db(d[0],"submit",h)},0,!1)})}var k=d.parent().controller("form"),j=i.name||i.ngForm;j&&(a[j]=f);k&&d.bind("$destroy",function(){k.$removeControl(f);j&&(a[j]=p);x(f,Oa)})}}}};return a?x(V(d),{restrict:"EAC"}):d}]},kd=Ra(),ld=Ra(!0),md=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,nd=/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/,od=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/, +ac={text:Qa,number:function(a,c,d,e,g,i){Qa(a,c,d,e,g,i);e.$parsers.push(function(a){var c=T(a);return c||od.test(a)?(e.$setValidity("number",!0),a===""?null:c?a:parseFloat(a)):(e.$setValidity("number",!1),p)});e.$formatters.push(function(a){return T(a)?"":""+a});if(d.min){var f=parseFloat(d.min),a=function(a){return!T(a)&&ah?(e.$setValidity("max", +!1),p):(e.$setValidity("max",!0),a)};e.$parsers.push(d);e.$formatters.push(d)}e.$formatters.push(function(a){return T(a)||wa(a)?(e.$setValidity("number",!0),a):(e.$setValidity("number",!1),p)})},url:function(a,c,d,e,g,i){Qa(a,c,d,e,g,i);a=function(a){return T(a)||md.test(a)?(e.$setValidity("url",!0),a):(e.$setValidity("url",!1),p)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,g,i){Qa(a,c,d,e,g,i);a=function(a){return T(a)||nd.test(a)?(e.$setValidity("email",!0),a):(e.$setValidity("email", +!1),p)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){t(d.name)&&c.attr("name",xa());c.bind("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var g=d.ngTrueValue,i=d.ngFalseValue;F(g)||(g=!0);F(i)||(i=!1);c.bind("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$formatters.push(function(a){return a=== +g});e.$parsers.push(function(a){return a?g:i})},hidden:D,button:D,submit:D,reset:D},bc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel",link:function(d,e,g,i){i&&(ac[E(g.type)]||ac.text)(d,e,g,i,c,a)}}}],Na="ng-valid",Ma="ng-invalid",Pa="ng-pristine",Xb="ng-dirty",pd=["$scope","$exceptionHandler","$attrs","$element","$parse",function(a,c,d,e,g){function i(a,c){c=c?"-"+$a(c,"-"):"";e.removeClass((a?Ma:Na)+c).addClass((a?Na:Ma)+c)}this.$modelValue=this.$viewValue=Number.NaN; +this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var f=g(d.ngModel),h=f.assign;if(!h)throw B(Db+d.ngModel+" ("+pa(e)+")");this.$render=D;var k=e.inheritedData("$formController")||Oa,j=0,l=this.$error={};e.addClass(Pa);i(!0);this.$setValidity=function(a,c){if(l[a]!==!c){if(c){if(l[a]&&j--,!j)i(!0),this.$valid=!0,this.$invalid=!1}else i(!1),this.$invalid=!0,this.$valid=!1,j++;l[a]=!c;i(c,a);k.$setValidity(a, +c,this)}};this.$setViewValue=function(d){this.$viewValue=d;if(this.$pristine)this.$dirty=!0,this.$pristine=!1,e.removeClass(Pa).addClass(Xb),k.$setDirty();m(this.$parsers,function(a){d=a(d)});if(this.$modelValue!==d)this.$modelValue=d,h(a,d),m(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};var o=this;a.$watch(function(){var c=f(a);if(o.$modelValue!==c){var d=o.$formatters,e=d.length;for(o.$modelValue=c;e--;)c=d[e](c);if(o.$viewValue!==c)o.$viewValue=c,o.$render()}})}],qd=function(){return{require:["ngModel", +"^?form"],controller:pd,link:function(a,c,d,e){var g=e[0],i=e[1]||Oa;i.$addControl(g);c.bind("$destroy",function(){i.$removeControl(g)})}}},rd=I({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),cc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var g=function(a){if(d.required&&(T(a)||a===!1))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(g);e.$parsers.unshift(g); +d.$observe("required",function(){g(e.$viewValue)})}}}},sd=function(){return{require:"ngModel",link:function(a,c,d,e){var g=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){var c=[];a&&m(a.split(g),function(a){a&&c.push(R(a))});return c});e.$formatters.push(function(a){return J(a)?a.join(", "):p})}}},td=/^(true|false|\d+)$/,ud=function(){return{priority:100,compile:function(a,c){return td.test(c.ngValue)?function(a,c,g){g.$set("value",a.$eval(g.ngValue))}:function(a, +c,g){a.$watch(g.ngValue,function(a){g.$set("value",a,!1)})}}}},vd=S(function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==p?"":a)})}),wd=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],xd=[function(){return function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBindHtmlUnsafe);a.$watch(d.ngBindHtmlUnsafe, +function(a){c.html(a||"")})}}],yd=jb("",!0),zd=jb("Odd",0),Ad=jb("Even",1),Bd=S({compile:function(a,c){c.$set("ngCloak",p);a.removeClass("ng-cloak")}}),Cd=[function(){return{scope:!0,controller:"@"}}],Dd=["$sniffer",function(a){return{priority:1E3,compile:function(){a.csp=!0}}}],dc={};m("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave".split(" "),function(a){var c=fa("ng-"+a);dc[c]=["$parse",function(d){return function(e,g,i){var f=d(i[c]);g.bind(E(a),function(a){e.$apply(function(){f(e, +{$event:a})})})}}]});var Ed=S(function(a,c,d){c.bind("submit",function(){a.$apply(d.ngSubmit)})}),Fd=["$http","$templateCache","$anchorScroll","$compile",function(a,c,d,e){return{restrict:"ECA",terminal:!0,compile:function(g,i){var f=i.ngInclude||i.src,h=i.onload||"",k=i.autoscroll;return function(g,i){var o=0,m,n=function(){m&&(m.$destroy(),m=null);i.html("")};g.$watch(f,function(f){var p=++o;f?a.get(f,{cache:c}).success(function(a){p===o&&(m&&m.$destroy(),m=g.$new(),i.html(a),e(i.contents())(m), +v(k)&&(!k||g.$eval(k))&&d(),m.$emit("$includeContentLoaded"),g.$eval(h))}).error(function(){p===o&&n()}):n()})}}}}],Gd=S({compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Hd=S({terminal:!0,priority:1E3}),Id=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,g,i){var f=i.count,h=g.attr(i.$attr.when),k=i.offset||0,j=e.$eval(h),l={},o=c.startSymbol(),r=c.endSymbol();m(j,function(a,e){l[e]=c(a.replace(d,o+f+"-"+k+r))});e.$watch(function(){var c= +parseFloat(e.$eval(f));return isNaN(c)?"":(j[c]||(c=a.pluralCat(c-k)),l[c](e,g,!0))},function(a){g.text(a)})}}}],Jd=S({transclude:"element",priority:1E3,terminal:!0,compile:function(a,c,d){return function(a,c,i){var f=i.ngRepeat,i=f.match(/^\s*(.+)\s+in\s+(.*)\s*$/),h,k,j;if(!i)throw B("Expected ngRepeat in form of '_item_ in _collection_' but got '"+f+"'.");f=i[1];h=i[2];i=f.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!i)throw B("'item' in 'item in collection' should be identifier or (key, value) but got '"+ +f+"'.");k=i[3]||i[1];j=i[2];var l=new eb;a.$watch(function(a){var e,f,i=a.$eval(h),m=gc(i,!0),p,u=new eb,C,A,v,t,y=c;if(J(i))v=i||[];else{v=[];for(C in i)i.hasOwnProperty(C)&&C.charAt(0)!="$"&&v.push(C);v.sort()}e=0;for(f=v.length;ex;)t.pop().element.remove()}for(;v.length>w;)v.pop()[0].element.remove()}var i;if(!(i=w.match(d)))throw B("Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '"+w+"'.");var j=c(i[2]||i[1]),k=i[4]|| +i[6],l=i[5],m=c(i[3]||""),o=c(i[2]?i[1]:k),r=c(i[7]),v=[[{element:f,label:""}]];q&&(a(q)(e),q.removeClass("ng-scope"),q.remove());f.html("");f.bind("change",function(){e.$apply(function(){var a,c=r(e)||[],d={},h,i,j,m,q,s;if(n){i=[];m=0;for(s=v.length;m@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\:form{display:block;}'); diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/app.js Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,224 @@ +// 'use strict'; + +// Declare app level module which depends on filters, and services +angular.module('bck2brwsr', []). + directive('uiCodemirror', ['$timeout', function($timeout) { + 'use strict'; + + var events = ["cursorActivity", "viewportChange", "gutterClick", "focus", "blur", "scroll", "update"]; + return { + restrict: 'A', + require: 'ngModel', + link: function(scope, elm, attrs, ngModel) { + var options, opts, onChange, deferCodeMirror, codeMirror, timeoutId, val; + + if (elm[0].type !== 'textarea') { + throw new Error('uiCodemirror3 can only be applied to a textarea element'); + } + + options = /* uiConfig.codemirror || */ {}; + opts = angular.extend({}, options, scope.$eval(attrs.uiCodemirror)); + + onChange = function(instance, changeObj) { + val = instance.getValue(); + $timeout.cancel(timeoutId); + timeoutId = $timeout(function() { + ngModel.$setViewValue(val); + }, 500); + }; + + deferCodeMirror = function() { + codeMirror = CodeMirror.fromTextArea(elm[0], opts); + elm[0].codeMirror = codeMirror; + // codeMirror.on("change", onChange(opts.onChange)); + codeMirror.on("change", onChange); + + for (var i = 0, n = events.length, aEvent; i < n; ++i) { + aEvent = opts["on" + events[i].charAt(0).toUpperCase() + events[i].slice(1)]; + if (aEvent === void 0) + continue; + if (typeof aEvent !== "function") + continue; + + var bound = _.bind( aEvent, scope ); + + codeMirror.on(events[i], bound); + } + + // CodeMirror expects a string, so make sure it gets one. + // This does not change the model. + ngModel.$formatters.push(function(value) { + if (angular.isUndefined(value) || value === null) { + return ''; + } + else if (angular.isObject(value) || angular.isArray(value)) { + throw new Error('ui-codemirror cannot use an object or an array as a model'); + } + return value; + }); + + // Override the ngModelController $render method, which is what gets called when the model is updated. + // This takes care of the synchronizing the codeMirror element with the underlying model, in the case that it is changed by something else. + ngModel.$render = function() { + codeMirror.setValue(ngModel.$viewValue); + }; + + }; + + $timeout(deferCodeMirror); + + } + }; +}]); + +function DevCtrl( $scope, $http ) { + var templateHtml = +"\n" + +" \n" + +" \n" + +" * 0 \n" + +" = 0\n" + +"
\n" + +" \n" + +" " + +"
\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +"\n" + +" \n" + +" \n" + +""; + var templateJava = +"package bck2brwsr.demo;\n" + +"import org.apidesign.bck2brwsr.htmlpage.api.*;\n" + +"import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;\n" + +"\n" + +"@Page(xhtml=\"index.html\", className=\"Index\", properties={\n" + +" @Property(name=\"value\", type=int.class)\n" + +"})\n" + +"class YourFirstHTML5PageInRealLanguage {\n" + +" static { new Index().applyBindings(); }\n" + +" @On(event=CLICK, id=\"dupl\") static void duplicateValue(Index m) {\n" + +" m.setValue(m.getValue() * 2);\n" + +" }\n" + +" @On(event=CLICK, id=\"clear\") static void zeroTheValue(Index m) {\n" + +" m.setValue(0);;\n" + +" }\n" + +" @ComputedProperty static int powerValue(int value) {\n" + +" return value * value;\n" + +" }\n" + +"}"; + + + $scope.makeMarker = function( editor, line ) { + var marker = document.createElement("div"); + marker.innerHTML = " "; + marker.className = "issue"; + + var info = editor.lineInfo(line); + editor.setGutterMarker(line, "issues", info.markers ? null : marker); + + return marker; + }; + + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + $scope.debounce = function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) result = func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) result = func.apply(context, args); + return result; + }; + }; + + $scope.reload = function() { + $scope.errors = null; + var frame = document.getElementById("result"); + frame.src = "result.html"; + frame.contentDocument.location.reload(true); + frame.contentWindow.location.reload(); + document.getElementById("editorJava").codeMirror.clearGutter("issues"); + }; + + $scope.fail = function( data ) { + $scope.errors = eval( data ); + var editor = document.getElementById("editorJava").codeMirror; + editor.clearGutter( "issues" ); + + for( var i = 0; i < $scope.errors.length; i ++ ) { + $scope.makeMarker( editor, $scope.errors[i].line - 1 ); + } + + }; + + $scope.post = function() { + return $http({url: ".", + method: "POST", + //headers: this.headers, + data: { html : $scope.html, java : $scope.java} + }).success( $scope.reload ).error( $scope.fail ); + }; + + $scope.errorClass = function( kind ) { + switch( kind ) { + case "ERROR" : + return "error"; + default : + return "warning"; + } + }; + + $scope.gotoError = function( line, col ) { + var editor = document.getElementById("editorJava").codeMirror; + editor.setCursor({ line: line - 1, ch : col - 1 }); + editor.focus(); + }; + + $scope.tab = "html"; + $scope.html= templateHtml; + $scope.java = templateJava; + + $scope.$watch( "html", $scope.debounce( $scope.post, 2000 ) ); + $scope.$watch( "java", $scope.debounce( $scope.post, 2000 ) ); + $scope.post(); + +} diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.css Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,239 @@ +/* BASICS */ + +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; + height: 300px; +} +.CodeMirror-scroll { + /* Set scrolling behaviour here */ + overflow: auto; +} + +/* PADDING */ + +.CodeMirror-lines { + padding: 4px 0; /* Vertical padding around content */ +} +.CodeMirror pre { + padding: 0 4px; /* Horizontal padding of content */ +} + +.CodeMirror-scrollbar-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; +} +.CodeMirror-linenumbers {} +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; +} + +/* CURSOR */ + +.CodeMirror pre.CodeMirror-cursor { + border-left: 1px solid black; +} +/* Shown when moving in bi-directional text */ +.CodeMirror pre.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} +.cm-keymap-fat-cursor pre.CodeMirror-cursor { + width: auto; + border: 0; + background: transparent; + background: rgba(0, 200, 0, .4); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800); +} +/* Kludge to turn off filter in ie9+, which also accepts rgba */ +.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) { + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} +/* Can style cursor different in overwrite (non-insert) mode */ +.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {} + +/* DEFAULT THEME */ + +.cm-s-default .cm-keyword {color: #708;} +.cm-s-default .cm-atom {color: #219;} +.cm-s-default .cm-number {color: #164;} +.cm-s-default .cm-def {color: #00f;} +.cm-s-default .cm-variable {color: black;} +.cm-s-default .cm-variable-2 {color: #05a;} +.cm-s-default .cm-variable-3 {color: #085;} +.cm-s-default .cm-property {color: black;} +.cm-s-default .cm-operator {color: black;} +.cm-s-default .cm-comment {color: #a50;} +.cm-s-default .cm-string {color: #a11;} +.cm-s-default .cm-string-2 {color: #f50;} +.cm-s-default .cm-meta {color: #555;} +.cm-s-default .cm-error {color: #f00;} +.cm-s-default .cm-qualifier {color: #555;} +.cm-s-default .cm-builtin {color: #30a;} +.cm-s-default .cm-bracket {color: #997;} +.cm-s-default .cm-tag {color: #170;} +.cm-s-default .cm-attribute {color: #00c;} +.cm-s-default .cm-header {color: blue;} +.cm-s-default .cm-quote {color: #090;} +.cm-s-default .cm-hr {color: #999;} +.cm-s-default .cm-link {color: #00c;} + +.cm-negative {color: #d44;} +.cm-positive {color: #292;} +.cm-header, .cm-strong {font-weight: bold;} +.cm-em {font-style: italic;} +.cm-emstrong {font-style: italic; font-weight: bold;} +.cm-link {text-decoration: underline;} + +.cm-invalidchar {color: #f00;} + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror { + line-height: 1; + position: relative; + overflow: hidden; +} + +.CodeMirror-scroll { + /* 30px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */ + margin-bottom: -30px; margin-right: -30px; + padding-bottom: 30px; padding-right: 30px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; +} +.CodeMirror-sizer { + position: relative; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actuall scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler { + position: absolute; + z-index: 6; + display: none; +} +.CodeMirror-vscrollbar { + right: 0; top: 0; + overflow-x: hidden; + overflow-y: scroll; +} +.CodeMirror-hscrollbar { + bottom: 0; left: 0; + overflow-y: hidden; + overflow-x: scroll; +} +.CodeMirror-scrollbar-filler { + right: 0; bottom: 0; + z-index: 6; +} + +.CodeMirror-gutters { + position: absolute; left: 0; top: 0; + height: 100%; + z-index: 3; +} +.CodeMirror-gutter { + height: 100%; + display: inline-block; + /* Hack to make IE7 behave */ + *zoom:1; + *display:inline; +} +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} + +.CodeMirror-lines { + cursor: text; +} +.CodeMirror pre { + /* Reset some styles that the rest of the page might have set */ + -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0; + border-width: 0; + background: transparent; + font-family: inherit; + font-size: inherit; + margin: 0; + white-space: pre; + word-wrap: normal; + line-height: inherit; + color: inherit; + z-index: 2; + position: relative; + overflow: visible; +} +.CodeMirror-wrap pre { + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; +} +.CodeMirror-linebackground { + position: absolute; + left: 0; right: 0; top: 0; bottom: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; +} + +.CodeMirror-wrap .CodeMirror-scroll { + overflow-x: hidden; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; height: 0px; + overflow: hidden; + visibility: hidden; +} +.CodeMirror-measure pre { position: static; } + +.CodeMirror pre.CodeMirror-cursor { + position: absolute; + visibility: hidden; + border-right: none; + width: 0; +} +.CodeMirror-focused pre.CodeMirror-cursor { + visibility: visible; +} + +.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } + +.CodeMirror-searching { + background: #ffa; + background: rgba(255, 255, 0, .4); +} + +/* IE7 hack to prevent it from returning funny offsetTops on the spans */ +.CodeMirror span { *vertical-align: text-bottom; } + +@media print { + /* Hide the cursor when printing */ + .CodeMirror pre.CodeMirror-cursor { + visibility: hidden; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/codemirror.js Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,4553 @@ +// CodeMirror version 3.0 +// +// CodeMirror is the only global var we claim +window.CodeMirror = (function() { + "use strict"; + + // BROWSER SNIFFING + + // Crude, but necessary to handle a number of hard-to-feature-detect + // bugs and behavior differences. + var gecko = /gecko\/\d/i.test(navigator.userAgent); + var ie = /MSIE \d/.test(navigator.userAgent); + var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent); + var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent); + var webkit = /WebKit\//.test(navigator.userAgent); + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent); + var chrome = /Chrome\//.test(navigator.userAgent); + var opera = /Opera\//.test(navigator.userAgent); + var safari = /Apple Computer/.test(navigator.vendor); + var khtml = /KHTML\//.test(navigator.userAgent); + var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent); + var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent); + var phantom = /PhantomJS/.test(navigator.userAgent); + + var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent); + // This is woefully incomplete. Suggestions for alternative methods welcome. + var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|IEMobile/i.test(navigator.userAgent); + var mac = ios || /Mac/.test(navigator.platform); + + // Optimize some code when these features are not used + var sawReadOnlySpans = false, sawCollapsedSpans = false; + + // CONSTRUCTOR + + function CodeMirror(place, options) { + if (!(this instanceof CodeMirror)) return new CodeMirror(place, options); + + this.options = options = options || {}; + // Determine effective options based on given values and defaults. + for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt)) + options[opt] = defaults[opt]; + setGuttersForLineNumbers(options); + + var display = this.display = makeDisplay(place); + display.wrapper.CodeMirror = this; + updateGutters(this); + if (options.autofocus && !mobile) focusInput(this); + + this.view = makeView(new BranchChunk([new LeafChunk([makeLine("", null, textHeight(display))])])); + this.nextOpId = 0; + loadMode(this); + themeChanged(this); + if (options.lineWrapping) + this.display.wrapper.className += " CodeMirror-wrap"; + + // Initialize the content. + this.setValue(options.value || ""); + // Override magic textarea content restore that IE sometimes does + // on our hidden textarea on reload + if (ie) setTimeout(bind(resetInput, this, true), 20); + this.view.history = makeHistory(); + + registerEventHandlers(this); + // IE throws unspecified error in certain cases, when + // trying to access activeElement before onload + var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { } + if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20); + else onBlur(this); + + operation(this, function() { + for (var opt in optionHandlers) + if (optionHandlers.propertyIsEnumerable(opt)) + optionHandlers[opt](this, options[opt], Init); + for (var i = 0; i < initHooks.length; ++i) initHooks[i](this); + })(); + } + + // DISPLAY CONSTRUCTOR + + function makeDisplay(place) { + var d = {}; + var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none;"); + input.setAttribute("wrap", "off"); input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); + // Wraps and hides input textarea + d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); + // The actual fake scrollbars. + d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar"); + d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar"); + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); + // DIVs containing the selection and the actual code + d.lineDiv = elt("div"); + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); + // Blinky cursor, and element used to ensure cursor fits at the end of a line + d.cursor = elt("pre", "\u00a0", "CodeMirror-cursor"); + // Secondary cursor, shown when on a 'jump' in bi-directional text + d.otherCursor = elt("pre", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"); + // Used to measure text size + d.measure = elt("div", null, "CodeMirror-measure"); + // Wraps everything that needs to exist inside the vertically-padded coordinate system + d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor], + null, "position: relative; outline: none"); + // Moved around its parent to cover visible view + d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative"); + // Set to the height of the text, causes scrolling + d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); + // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers + d.heightForcer = elt("div", "\u00a0", null, "position: absolute; height: " + scrollerCutOff + "px"); + // Will contain the gutters, if any + d.gutters = elt("div", null, "CodeMirror-gutters"); + d.lineGutter = null; + // Helper element to properly size the gutter backgrounds + var scrollerInner = elt("div", [d.sizer, d.heightForcer, d.gutters], null, "position: relative; min-height: 100%"); + // Provides scrolling + d.scroller = elt("div", [scrollerInner], "CodeMirror-scroll"); + d.scroller.setAttribute("tabIndex", "-1"); + // The element in which the editor lives. + d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV, + d.scrollbarFiller, d.scroller], "CodeMirror"); + // Work around IE7 z-index bug + if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } + if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper); + + // Needed to hide big blue blinking cursor on Mobile Safari + if (ios) input.style.width = "0px"; + if (!webkit) d.scroller.draggable = true; + // Needed to handle Tab key in KHTML + if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; } + // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px"; + + // Current visible range (may be bigger than the view window). + d.viewOffset = d.showingFrom = d.showingTo = d.lastSizeC = 0; + + // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; + // See readInput and resetInput + d.prevInput = ""; + // Set to true when a non-horizontal-scrolling widget is added. As + // an optimization, widget aligning is skipped when d is false. + d.alignWidgets = false; + // Flag that indicates whether we currently expect input to appear + // (after some event like 'keypress' or 'input') and are polling + // intensively. + d.pollingFast = false; + // Self-resetting timeout for the poller + d.poll = new Delayed(); + // True when a drag from the editor is active + d.draggingText = false; + + d.cachedCharWidth = d.cachedTextHeight = null; + d.measureLineCache = []; + d.measureLineCachePos = 0; + + // Tracks when resetInput has punted to just putting a short + // string instead of the (large) selection. + d.inaccurateSelection = false; + + // Used to adjust overwrite behaviour when a paste has been + // detected + d.pasteIncoming = false; + + return d; + } + + // VIEW CONSTRUCTOR + + function makeView(doc) { + var selPos = {line: 0, ch: 0}; + return { + doc: doc, + // frontier is the point up to which the content has been parsed, + frontier: 0, highlight: new Delayed(), + sel: {from: selPos, to: selPos, head: selPos, anchor: selPos, shift: false, extend: false}, + scrollTop: 0, scrollLeft: 0, + overwrite: false, focused: false, + // Tracks the maximum line length so that + // the horizontal scrollbar can be kept + // static when scrolling. + maxLine: getLine(doc, 0), + maxLineLength: 0, + maxLineChanged: false, + suppressEdits: false, + goalColumn: null, + cantEdit: false, + keyMaps: [] + }; + } + + // STATE UPDATES + + // Used to get the editor into a consistent state again when options change. + + function loadMode(cm) { + var doc = cm.view.doc; + cm.view.mode = CodeMirror.getMode(cm.options, cm.options.mode); + doc.iter(0, doc.size, function(line) { line.stateAfter = null; }); + cm.view.frontier = 0; + startWorker(cm, 100); + } + + function wrappingChanged(cm) { + var doc = cm.view.doc, th = textHeight(cm.display); + if (cm.options.lineWrapping) { + cm.display.wrapper.className += " CodeMirror-wrap"; + var perLine = cm.display.scroller.clientWidth / charWidth(cm.display) - 3; + doc.iter(0, doc.size, function(line) { + if (line.height == 0) return; + var guess = Math.ceil(line.text.length / perLine) || 1; + if (guess != 1) updateLineHeight(line, guess * th); + }); + cm.display.sizer.style.minWidth = ""; + } else { + cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", ""); + computeMaxLength(cm.view); + doc.iter(0, doc.size, function(line) { + if (line.height != 0) updateLineHeight(line, th); + }); + } + regChange(cm, 0, doc.size); + clearCaches(cm); + setTimeout(function(){updateScrollbars(cm.display, cm.view.doc.height);}, 100); + } + + function keyMapChanged(cm) { + var style = keyMap[cm.options.keyMap].style; + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") + + (style ? " cm-keymap-" + style : ""); + } + + function themeChanged(cm) { + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + clearCaches(cm); + } + + function guttersChanged(cm) { + updateGutters(cm); + updateDisplay(cm, true); + } + + function updateGutters(cm) { + var gutters = cm.display.gutters, specs = cm.options.gutters; + removeChildren(gutters); + for (var i = 0; i < specs.length; ++i) { + var gutterClass = specs[i]; + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)); + if (gutterClass == "CodeMirror-linenumbers") { + cm.display.lineGutter = gElt; + gElt.style.width = (cm.display.lineNumWidth || 1) + "px"; + } + } + gutters.style.display = i ? "" : "none"; + } + + function lineLength(doc, line) { + if (line.height == 0) return 0; + var len = line.text.length, merged, cur = line; + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(); + cur = getLine(doc, found.from.line); + len += found.from.ch - found.to.ch; + } + cur = line; + while (merged = collapsedSpanAtEnd(cur)) { + var found = merged.find(); + len -= cur.text.length - found.from.ch; + cur = getLine(doc, found.to.line); + len += cur.text.length - found.to.ch; + } + return len; + } + + function computeMaxLength(view) { + view.maxLine = getLine(view.doc, 0); + view.maxLineLength = lineLength(view.doc, view.maxLine); + view.maxLineChanged = true; + view.doc.iter(1, view.doc.size, function(line) { + var len = lineLength(view.doc, line); + if (len > view.maxLineLength) { + view.maxLineLength = len; + view.maxLine = line; + } + }); + } + + // Make sure the gutters options contains the element + // "CodeMirror-linenumbers" when the lineNumbers option is true. + function setGuttersForLineNumbers(options) { + var found = false; + for (var i = 0; i < options.gutters.length; ++i) { + if (options.gutters[i] == "CodeMirror-linenumbers") { + if (options.lineNumbers) found = true; + else options.gutters.splice(i--, 1); + } + } + if (!found && options.lineNumbers) + options.gutters.push("CodeMirror-linenumbers"); + } + + // SCROLLBARS + + // Re-synchronize the fake scrollbars with the actual size of the + // content. Optionally force a scrollTop. + function updateScrollbars(d /* display */, docHeight) { + var totalHeight = docHeight + 2 * paddingTop(d); + d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px"; + var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight); + var needsH = d.scroller.scrollWidth > d.scroller.clientWidth; + var needsV = scrollHeight > d.scroller.clientHeight; + if (needsV) { + d.scrollbarV.style.display = "block"; + d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0"; + d.scrollbarV.firstChild.style.height = + (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px"; + } else d.scrollbarV.style.display = ""; + if (needsH) { + d.scrollbarH.style.display = "block"; + d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0"; + d.scrollbarH.firstChild.style.width = + (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px"; + } else d.scrollbarH.style.display = ""; + if (needsH && needsV) { + d.scrollbarFiller.style.display = "block"; + d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px"; + } else d.scrollbarFiller.style.display = ""; + + if (mac_geLion && scrollbarWidth(d.measure) === 0) + d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px"; + } + + function visibleLines(display, doc, viewPort) { + var top = display.scroller.scrollTop, height = display.wrapper.clientHeight; + if (typeof viewPort == "number") top = viewPort; + else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;} + top = Math.floor(top - paddingTop(display)); + var bottom = Math.ceil(top + height); + return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)}; + } + + // LINE NUMBERS + + function alignHorizontally(cm) { + var display = cm.display; + if (!display.alignWidgets && !display.gutters.firstChild) return; + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.view.scrollLeft; + var gutterW = display.gutters.offsetWidth, l = comp + "px"; + for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) { + for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l; + } + display.gutters.style.left = (comp + gutterW) + "px"; + } + + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) return false; + var doc = cm.view.doc, last = lineNumberFor(cm.options, doc.size - 1), display = cm.display; + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], + "CodeMirror-linenumber CodeMirror-gutter-elt")); + var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; + display.lineGutter.style.width = ""; + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding); + display.lineNumWidth = display.lineNumInnerWidth + padding; + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; + display.lineGutter.style.width = display.lineNumWidth + "px"; + return true; + } + return false; + } + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)); + } + function compensateForHScroll(display) { + return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left; + } + + // DISPLAY DRAWING + + function updateDisplay(cm, changes, viewPort) { + var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo; + var updated = updateDisplayInner(cm, changes, viewPort); + if (updated) { + signalLater(cm, cm, "update", cm); + if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo) + signalLater(cm, cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo); + } + updateSelection(cm); + updateScrollbars(cm.display, cm.view.doc.height); + + return updated; + } + + // Uses a set of changes plus the current scroll position to + // determine which DOM updates have to be made, and makes the + // updates. + function updateDisplayInner(cm, changes, viewPort) { + var display = cm.display, doc = cm.view.doc; + if (!display.wrapper.clientWidth) { + display.showingFrom = display.showingTo = display.viewOffset = 0; + return; + } + + // Compute the new visible window + // If scrollTop is specified, use that to determine which lines + // to render instead of the current scrollbar position. + var visible = visibleLines(display, doc, viewPort); + // Bail out if the visible area is already rendered and nothing changed. + if (changes !== true && changes.length == 0 && + visible.from > display.showingFrom && visible.to < display.showingTo) + return; + + if (changes && maybeUpdateLineNumberWidth(cm)) + changes = true; + display.sizer.style.marginLeft = display.scrollbarH.style.left = display.gutters.offsetWidth + "px"; + + // When merged lines are present, the line that needs to be + // redrawn might not be the one that was changed. + if (changes !== true && sawCollapsedSpans) + for (var i = 0; i < changes.length; ++i) { + var ch = changes[i], merged; + while (merged = collapsedSpanAtStart(getLine(doc, ch.from))) { + var from = merged.find().from.line; + if (ch.diff) ch.diff -= ch.from - from; + ch.from = from; + } + } + + // Used to determine which lines need their line numbers updated + var positionsChangedFrom = changes === true ? 0 : Infinity; + if (cm.options.lineNumbers && changes && changes !== true) + for (var i = 0; i < changes.length; ++i) + if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; } + + var from = Math.max(visible.from - cm.options.viewportMargin, 0); + var to = Math.min(doc.size, visible.to + cm.options.viewportMargin); + if (display.showingFrom < from && from - display.showingFrom < 20) from = display.showingFrom; + if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(doc.size, display.showingTo); + if (sawCollapsedSpans) { + from = lineNo(visualLine(doc, getLine(doc, from))); + while (to < doc.size && lineIsHidden(getLine(doc, to))) ++to; + } + + // Create a range of theoretically intact lines, and punch holes + // in that using the change info. + var intact = changes === true ? [] : + computeIntact([{from: display.showingFrom, to: display.showingTo}], changes); + // Clip off the parts that won't be visible + var intactLines = 0; + for (var i = 0; i < intact.length; ++i) { + var range = intact[i]; + if (range.from < from) range.from = from; + if (range.to > to) range.to = to; + if (range.from >= range.to) intact.splice(i--, 1); + else intactLines += range.to - range.from; + } + if (intactLines == to - from && from == display.showingFrom && to == display.showingTo) + return; + intact.sort(function(a, b) {return a.from - b.from;}); + + if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none"; + patchDisplay(cm, from, to, intact, positionsChangedFrom); + display.lineDiv.style.display = ""; + + var different = from != display.showingFrom || to != display.showingTo || + display.lastSizeC != display.wrapper.clientHeight; + // This is just a bogus formula that detects when the editor is + // resized or the font size changes. + if (different) display.lastSizeC = display.wrapper.clientHeight; + display.showingFrom = from; display.showingTo = to; + startWorker(cm, 100); + + var prevBottom = display.lineDiv.offsetTop; + for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) { + if (ie_lt8) { + var bot = node.offsetTop + node.offsetHeight; + height = bot - prevBottom; + prevBottom = bot; + } else { + var box = node.getBoundingClientRect(); + height = box.bottom - box.top; + } + var diff = node.lineObj.height - height; + if (height < 2) height = textHeight(display); + if (diff > .001 || diff < -.001) + updateLineHeight(node.lineObj, height); + } + display.viewOffset = heightAtLine(cm, getLine(doc, from)); + // Position the mover div to align with the current virtual scroll position + display.mover.style.top = display.viewOffset + "px"; + return true; + } + + function computeIntact(intact, changes) { + for (var i = 0, l = changes.length || 0; i < l; ++i) { + var change = changes[i], intact2 = [], diff = change.diff || 0; + for (var j = 0, l2 = intact.length; j < l2; ++j) { + var range = intact[j]; + if (change.to <= range.from && change.diff) { + intact2.push({from: range.from + diff, to: range.to + diff}); + } else if (change.to <= range.from || change.from >= range.to) { + intact2.push(range); + } else { + if (change.from > range.from) + intact2.push({from: range.from, to: change.from}); + if (change.to < range.to) + intact2.push({from: change.to + diff, to: range.to + diff}); + } + } + intact = intact2; + } + return intact; + } + + function getDimensions(cm) { + var d = cm.display, left = {}, width = {}; + for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { + left[cm.options.gutters[i]] = n.offsetLeft; + width[cm.options.gutters[i]] = n.offsetWidth; + } + return {fixedPos: compensateForHScroll(d), + gutterTotalWidth: d.gutters.offsetWidth, + gutterLeft: left, + gutterWidth: width, + wrapperWidth: d.wrapper.clientWidth}; + } + + function patchDisplay(cm, from, to, intact, updateNumbersFrom) { + var dims = getDimensions(cm); + var display = cm.display, lineNumbers = cm.options.lineNumbers; + // IE does bad things to nodes when .innerHTML = "" is used on a parent + // we still need widgets and markers intact to add back to the new content later + if (!intact.length && !ie && (!webkit || !cm.display.currentWheelTarget)) + removeChildren(display.lineDiv); + var container = display.lineDiv, cur = container.firstChild; + + function rm(node) { + var next = node.nextSibling; + if (webkit && mac && cm.display.currentWheelTarget == node) { + node.style.display = "none"; + node.lineObj = null; + } else { + container.removeChild(node); + } + return next; + } + + var nextIntact = intact.shift(), lineNo = from; + cm.view.doc.iter(from, to, function(line) { + if (nextIntact && nextIntact.to == lineNo) nextIntact = intact.shift(); + if (lineIsHidden(line)) { + if (line.height != 0) updateLineHeight(line, 0); + } else if (nextIntact && nextIntact.from <= lineNo && nextIntact.to > lineNo) { + // This line is intact. Skip to the actual node. Update its + // line number if needed. + while (cur.lineObj != line) cur = rm(cur); + if (lineNumbers && updateNumbersFrom <= lineNo && cur.lineNumber) + setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineNo)); + cur = cur.nextSibling; + } else { + // This line needs to be generated. + var lineNode = buildLineElement(cm, line, lineNo, dims); + container.insertBefore(lineNode, cur); + lineNode.lineObj = line; + } + ++lineNo; + }); + while (cur) cur = rm(cur); + } + + function buildLineElement(cm, line, lineNo, dims) { + var lineElement = lineContent(cm, line); + var markers = line.gutterMarkers, display = cm.display; + + if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && + (!line.widgets || !line.widgets.length)) return lineElement; + + // Lines with gutter elements or a background class need + // to be wrapped again, and have the extra elements added + // to the wrapper div + + var wrap = elt("div", null, line.wrapClass, "position: relative"); + if (cm.options.lineNumbers || markers) { + var gutterWrap = wrap.appendChild(elt("div", null, null, "position: absolute; left: " + + dims.fixedPos + "px")); + wrap.alignable = [gutterWrap]; + if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) + wrap.lineNumber = gutterWrap.appendChild( + elt("div", lineNumberFor(cm.options, lineNo), + "CodeMirror-linenumber CodeMirror-gutter-elt", + "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: " + + display.lineNumInnerWidth + "px")); + if (markers) + for (var k = 0; k < cm.options.gutters.length; ++k) { + var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]; + if (found) + gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " + + dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px")); + } + } + // Kludge to make sure the styled element lies behind the selection (by z-index) + if (line.bgClass) + wrap.appendChild(elt("div", "\u00a0", line.bgClass + " CodeMirror-linebackground")); + wrap.appendChild(lineElement); + if (line.widgets) + for (var i = 0, ws = line.widgets; i < ws.length; ++i) { + var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); + node.widget = widget; + if (widget.noHScroll) { + (wrap.alignable || (wrap.alignable = [])).push(node); + var width = dims.wrapperWidth; + node.style.left = dims.fixedPos + "px"; + if (!widget.coverGutter) { + width -= dims.gutterTotalWidth; + node.style.paddingLeft = dims.gutterTotalWidth + "px"; + } + node.style.width = width + "px"; + } + if (widget.coverGutter) { + node.style.zIndex = 5; + node.style.position = "relative"; + if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px"; + } + if (widget.above) + wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement); + else + wrap.appendChild(node); + } + + if (ie_lt8) wrap.style.zIndex = 2; + return wrap; + } + + // SELECTION / CURSOR + + function updateSelection(cm) { + var display = cm.display; + var collapsed = posEq(cm.view.sel.from, cm.view.sel.to); + if (collapsed || cm.options.showCursorWhenSelecting) + updateSelectionCursor(cm); + else + display.cursor.style.display = display.otherCursor.style.display = "none"; + if (!collapsed) + updateSelectionRange(cm); + else + display.selectionDiv.style.display = "none"; + + // Move the hidden textarea near the cursor to prevent scrolling artifacts + var headPos = cursorCoords(cm, cm.view.sel.head, "div"); + var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); + display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10, + headPos.top + lineOff.top - wrapOff.top)) + "px"; + display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10, + headPos.left + lineOff.left - wrapOff.left)) + "px"; + } + + // No selection, plain cursor + function updateSelectionCursor(cm) { + var display = cm.display, pos = cursorCoords(cm, cm.view.sel.head, "div"); + display.cursor.style.left = pos.left + "px"; + display.cursor.style.top = pos.top + "px"; + display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; + display.cursor.style.display = ""; + + if (pos.other) { + display.otherCursor.style.display = ""; + display.otherCursor.style.left = pos.other.left + "px"; + display.otherCursor.style.top = pos.other.top + "px"; + display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; + } else { display.otherCursor.style.display = "none"; } + } + + // Highlight selection + function updateSelectionRange(cm) { + var display = cm.display, doc = cm.view.doc, sel = cm.view.sel; + var fragment = document.createDocumentFragment(); + var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display); + + function add(left, top, width, bottom) { + if (top < 0) top = 0; + fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + + "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) + + "px; height: " + (bottom - top) + "px")); + } + + function drawForLine(line, fromArg, toArg, retTop) { + var lineObj = getLine(doc, line); + var lineLen = lineObj.text.length, rVal = retTop ? Infinity : -Infinity; + function coords(ch) { + return charCoords(cm, {line: line, ch: ch}, "div", lineObj); + } + + iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) { + var leftPos = coords(dir == "rtl" ? to - 1 : from); + var rightPos = coords(dir == "rtl" ? from : to - 1); + var left = leftPos.left, right = rightPos.right; + if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part + add(left, leftPos.top, null, leftPos.bottom); + left = pl; + if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top); + } + if (toArg == null && to == lineLen) right = clientWidth; + if (fromArg == null && from == 0) left = pl; + rVal = retTop ? Math.min(rightPos.top, rVal) : Math.max(rightPos.bottom, rVal); + if (left < pl + 1) left = pl; + add(left, rightPos.top, right - left, rightPos.bottom); + }); + return rVal; + } + + if (sel.from.line == sel.to.line) { + drawForLine(sel.from.line, sel.from.ch, sel.to.ch); + } else { + var fromObj = getLine(doc, sel.from.line); + var cur = fromObj, merged, path = [sel.from.line, sel.from.ch], singleLine; + while (merged = collapsedSpanAtEnd(cur)) { + var found = merged.find(); + path.push(found.from.ch, found.to.line, found.to.ch); + if (found.to.line == sel.to.line) { + path.push(sel.to.ch); + singleLine = true; + break; + } + cur = getLine(doc, found.to.line); + } + + // This is a single, merged line + if (singleLine) { + for (var i = 0; i < path.length; i += 3) + drawForLine(path[i], path[i+1], path[i+2]); + } else { + var middleTop, middleBot, toObj = getLine(doc, sel.to.line); + if (sel.from.ch) + // Draw the first line of selection. + middleTop = drawForLine(sel.from.line, sel.from.ch, null, false); + else + // Simply include it in the middle block. + middleTop = heightAtLine(cm, fromObj) - display.viewOffset; + + if (!sel.to.ch) + middleBot = heightAtLine(cm, toObj) - display.viewOffset; + else + middleBot = drawForLine(sel.to.line, collapsedSpanAtStart(toObj) ? null : 0, sel.to.ch, true); + + if (middleTop < middleBot) add(pl, middleTop, null, middleBot); + } + } + + removeChildrenAndAdd(display.selectionDiv, fragment); + display.selectionDiv.style.display = ""; + } + + // Cursor-blinking + function restartBlink(cm) { + var display = cm.display; + clearInterval(display.blinker); + var on = true; + display.cursor.style.visibility = display.otherCursor.style.visibility = ""; + display.blinker = setInterval(function() { + if (!display.cursor.offsetHeight) return; + display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden"; + }, cm.options.cursorBlinkRate); + } + + // HIGHLIGHT WORKER + + function startWorker(cm, time) { + if (cm.view.frontier < cm.display.showingTo) + cm.view.highlight.set(time, bind(highlightWorker, cm)); + } + + function highlightWorker(cm) { + var view = cm.view, doc = view.doc; + if (view.frontier >= cm.display.showingTo) return; + var end = +new Date + cm.options.workTime; + var state = copyState(view.mode, getStateBefore(cm, view.frontier)); + var changed = [], prevChange; + doc.iter(view.frontier, Math.min(doc.size, cm.display.showingTo + 500), function(line) { + if (view.frontier >= cm.display.showingFrom) { // Visible + if (highlightLine(cm, line, state) && view.frontier >= cm.display.showingFrom) { + if (prevChange && prevChange.end == view.frontier) prevChange.end++; + else changed.push(prevChange = {start: view.frontier, end: view.frontier + 1}); + } + line.stateAfter = copyState(view.mode, state); + } else { + processLine(cm, line, state); + line.stateAfter = view.frontier % 5 == 0 ? copyState(view.mode, state) : null; + } + ++view.frontier; + if (+new Date > end) { + startWorker(cm, cm.options.workDelay); + return true; + } + }); + if (changed.length) + operation(cm, function() { + for (var i = 0; i < changed.length; ++i) + regChange(this, changed[i].start, changed[i].end); + })(); + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(cm, n) { + var minindent, minline, doc = cm.view.doc; + for (var search = n, lim = n - 100; search > lim; --search) { + if (search == 0) return 0; + var line = getLine(doc, search-1); + if (line.stateAfter) return search; + var indented = countColumn(line.text, null, cm.options.tabSize); + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + return minline; + } + + function getStateBefore(cm, n) { + var view = cm.view; + var pos = findStartLine(cm, n), state = pos && getLine(view.doc, pos-1).stateAfter; + if (!state) state = startState(view.mode); + else state = copyState(view.mode, state); + view.doc.iter(pos, n, function(line) { + processLine(cm, line, state); + var save = pos == n - 1 || pos % 5 == 0 || pos >= view.showingFrom && pos < view.showingTo; + line.stateAfter = save ? copyState(view.mode, state) : null; + ++pos; + }); + return state; + } + + // POSITION MEASUREMENT + + function paddingTop(display) {return display.lineSpace.offsetTop;} + function paddingLeft(display) { + var e = removeChildrenAndAdd(display.measure, elt("pre")).appendChild(elt("span", "x")); + return e.offsetLeft; + } + + function measureChar(cm, line, ch, data) { + var data = data || measureLine(cm, line), dir = -1; + for (var pos = ch;; pos += dir) { + var r = data[pos]; + if (r) break; + if (dir < 0 && pos == 0) dir = 1; + } + return {left: pos < ch ? r.right : r.left, + right: pos > ch ? r.left : r.right, + top: r.top, bottom: r.bottom}; + } + + function measureLine(cm, line) { + // First look in the cache + var display = cm.display, cache = cm.display.measureLineCache; + for (var i = 0; i < cache.length; ++i) { + var memo = cache[i]; + if (memo.text == line.text && memo.markedSpans == line.markedSpans && + display.scroller.clientWidth == memo.width) + return memo.measure; + } + + var measure = measureLineInner(cm, line); + // Store result in the cache + var memo = {text: line.text, width: display.scroller.clientWidth, + markedSpans: line.markedSpans, measure: measure}; + if (cache.length == 16) cache[++display.measureLineCachePos % 16] = memo; + else cache.push(memo); + return measure; + } + + function measureLineInner(cm, line) { + var display = cm.display, measure = emptyArray(line.text.length); + var pre = lineContent(cm, line, measure); + + // IE does not cache element positions of inline elements between + // calls to getBoundingClientRect. This makes the loop below, + // which gathers the positions of all the characters on the line, + // do an amount of layout work quadratic to the number of + // characters. When line wrapping is off, we try to improve things + // by first subdividing the line into a bunch of inline blocks, so + // that IE can reuse most of the layout information from caches + // for those blocks. This does interfere with line wrapping, so it + // doesn't work when wrapping is on, but in that case the + // situation is slightly better, since IE does cache line-wrapping + // information and only recomputes per-line. + if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) { + var fragment = document.createDocumentFragment(); + var chunk = 10, n = pre.childNodes.length; + for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) { + var wrap = elt("div", null, null, "display: inline-block"); + for (var j = 0; j < chunk && n; ++j) { + wrap.appendChild(pre.firstChild); + --n; + } + fragment.appendChild(wrap); + } + pre.appendChild(fragment); + } + + removeChildrenAndAdd(display.measure, pre); + + var outer = display.lineDiv.getBoundingClientRect(); + var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight; + for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) { + var size = cur.getBoundingClientRect(); + var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot); + for (var j = 0; j < vranges.length; j += 2) { + var rtop = vranges[j], rbot = vranges[j+1]; + if (rtop > bot || rbot < top) continue; + if (rtop <= top && rbot >= bot || + top <= rtop && bot >= rbot || + Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) { + vranges[j] = Math.min(top, rtop); + vranges[j+1] = Math.max(bot, rbot); + break; + } + } + if (j == vranges.length) vranges.push(top, bot); + data[i] = {left: size.left - outer.left, right: size.right - outer.left, top: j}; + } + for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) { + var vr = cur.top; + cur.top = vranges[vr]; cur.bottom = vranges[vr+1]; + } + return data; + } + + function clearCaches(cm) { + cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0; + cm.display.cachedCharWidth = cm.display.cachedTextHeight = null; + cm.view.maxLineChanged = true; + } + + // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page" + function intoCoordSystem(cm, lineObj, rect, context) { + if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) { + var size = lineObj.widgets[i].node.offsetHeight; + rect.top += size; rect.bottom += size; + } + if (context == "line") return rect; + if (!context) context = "local"; + var yOff = heightAtLine(cm, lineObj); + if (context != "local") yOff -= cm.display.viewOffset; + if (context == "page") { + var lOff = cm.display.lineSpace.getBoundingClientRect(); + yOff += lOff.top + (window.pageYOffset || (document.documentElement || document.body).scrollTop); + var xOff = lOff.left + (window.pageXOffset || (document.documentElement || document.body).scrollLeft); + rect.left += xOff; rect.right += xOff; + } + rect.top += yOff; rect.bottom += yOff; + return rect; + } + + function charCoords(cm, pos, context, lineObj) { + if (!lineObj) lineObj = getLine(cm.view.doc, pos.line); + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch), context); + } + + function cursorCoords(cm, pos, context, lineObj, measurement) { + lineObj = lineObj || getLine(cm.view.doc, pos.line); + if (!measurement) measurement = measureLine(cm, lineObj); + function get(ch, right) { + var m = measureChar(cm, lineObj, ch, measurement); + if (right) m.left = m.right; else m.right = m.left; + return intoCoordSystem(cm, lineObj, m, context); + } + var order = getOrder(lineObj), ch = pos.ch; + if (!order) return get(ch); + var main, other, linedir = order[0].level; + for (var i = 0; i < order.length; ++i) { + var part = order[i], rtl = part.level % 2, nb, here; + if (part.from < ch && part.to > ch) return get(ch, rtl); + var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to; + if (left == ch) { + // Opera and IE return bogus offsets and widths for edges + // where the direction flips, but only for the side with the + // lower level. So we try to use the side with the higher + // level. + if (i && part.level < (nb = order[i-1]).level) here = get(nb.level % 2 ? nb.from : nb.to - 1, true); + else here = get(rtl && part.from != part.to ? ch - 1 : ch); + if (rtl == linedir) main = here; else other = here; + } else if (right == ch) { + var nb = i < order.length - 1 && order[i+1]; + if (!rtl && nb && nb.from == nb.to) continue; + if (nb && part.level < nb.level) here = get(nb.level % 2 ? nb.to - 1 : nb.from); + else here = get(rtl ? ch : ch - 1, true); + if (rtl == linedir) main = here; else other = here; + } + } + if (linedir && !ch) other = get(order[0].to - 1); + if (!main) return other; + if (other) main.other = other; + return main; + } + + // Coords must be lineSpace-local + function coordsChar(cm, x, y) { + var doc = cm.view.doc; + y += cm.display.viewOffset; + if (y < 0) return {line: 0, ch: 0, outside: true}; + var lineNo = lineAtHeight(doc, y); + if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc, doc.size - 1).text.length}; + if (x < 0) x = 0; + + for (;;) { + var lineObj = getLine(doc, lineNo); + var found = coordsCharInner(cm, lineObj, lineNo, x, y); + var merged = collapsedSpanAtEnd(lineObj); + if (merged && found.ch == lineRight(lineObj)) + lineNo = merged.find().to.line; + else + return found; + } + } + + function coordsCharInner(cm, lineObj, lineNo, x, y) { + var innerOff = y - heightAtLine(cm, lineObj); + var wrongLine = false, cWidth = cm.display.wrapper.clientWidth; + var measurement = measureLine(cm, lineObj); + + function getX(ch) { + var sp = cursorCoords(cm, {line: lineNo, ch: ch}, "line", + lineObj, measurement); + wrongLine = true; + if (innerOff > sp.bottom) return Math.max(0, sp.left - cWidth); + else if (innerOff < sp.top) return sp.left + cWidth; + else wrongLine = false; + return sp.left; + } + + var bidi = getOrder(lineObj), dist = lineObj.text.length; + var from = lineLeft(lineObj), to = lineRight(lineObj); + var fromX = paddingLeft(cm.display), toX = getX(to); + + if (x > toX) return {line: lineNo, ch: to, outside: wrongLine}; + // Do a binary search between these bounds. + for (;;) { + if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { + var after = x - fromX < toX - x, ch = after ? from : to; + while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch; + return {line: lineNo, ch: ch, after: after, outside: wrongLine}; + } + var step = Math.ceil(dist / 2), middle = from + step; + if (bidi) { + middle = from; + for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1); + } + var middleX = getX(middle); + if (middleX > x) {to = middle; toX = middleX; if (wrongLine) toX += 1000; dist -= step;} + else {from = middle; fromX = middleX; dist = step;} + } + } + + var measureText; + function textHeight(display) { + if (display.cachedTextHeight != null) return display.cachedTextHeight; + if (measureText == null) { + measureText = elt("pre"); + // Measure a bunch of lines, for browsers that compute + // fractional heights. + for (var i = 0; i < 49; ++i) { + measureText.appendChild(document.createTextNode("x")); + measureText.appendChild(elt("br")); + } + measureText.appendChild(document.createTextNode("x")); + } + removeChildrenAndAdd(display.measure, measureText); + var height = measureText.offsetHeight / 50; + if (height > 3) display.cachedTextHeight = height; + removeChildren(display.measure); + return height || 1; + } + + function charWidth(display) { + if (display.cachedCharWidth != null) return display.cachedCharWidth; + var anchor = elt("span", "x"); + var pre = elt("pre", [anchor]); + removeChildrenAndAdd(display.measure, pre); + var width = anchor.offsetWidth; + if (width > 2) display.cachedCharWidth = width; + return width || 10; + } + + // OPERATIONS + + // Operations are used to wrap changes in such a way that each + // change won't have to update the cursor and display (which would + // be awkward, slow, and error-prone), but instead updates are + // batched and then all combined and executed at once. + + function startOperation(cm) { + if (cm.curOp) ++cm.curOp.depth; + else cm.curOp = { + // Nested operations delay update until the outermost one + // finishes. + depth: 1, + // An array of ranges of lines that have to be updated. See + // updateDisplay. + changes: [], + delayedCallbacks: [], + updateInput: null, + userSelChange: null, + textChanged: null, + selectionChanged: false, + updateMaxLine: false, + id: ++cm.nextOpId + }; + } + + function endOperation(cm) { + var op = cm.curOp; + if (--op.depth) return; + cm.curOp = null; + var view = cm.view, display = cm.display; + if (op.updateMaxLine) computeMaxLength(view); + if (view.maxLineChanged && !cm.options.lineWrapping) { + var width = measureChar(cm, view.maxLine, view.maxLine.text.length).right; + display.sizer.style.minWidth = (width + 3 + scrollerCutOff) + "px"; + view.maxLineChanged = false; + } + var newScrollPos, updated; + if (op.selectionChanged) { + var coords = cursorCoords(cm, view.sel.head); + newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom); + } + if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null) + updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop); + if (!updated && op.selectionChanged) updateSelection(cm); + if (newScrollPos) scrollCursorIntoView(cm); + if (op.selectionChanged) restartBlink(cm); + + if (view.focused && op.updateInput) + resetInput(cm, op.userSelChange); + + if (op.textChanged) + signal(cm, "change", cm, op.textChanged); + if (op.selectionChanged) signal(cm, "cursorActivity", cm); + for (var i = 0; i < op.delayedCallbacks.length; ++i) op.delayedCallbacks[i](cm); + } + + // Wraps a function in an operation. Returns the wrapped function. + function operation(cm1, f) { + return function() { + var cm = cm1 || this; + startOperation(cm); + try {var result = f.apply(cm, arguments);} + finally {endOperation(cm);} + return result; + }; + } + + function regChange(cm, from, to, lendiff) { + cm.curOp.changes.push({from: from, to: to, diff: lendiff}); + } + + // INPUT HANDLING + + function slowPoll(cm) { + if (cm.view.pollingFast) return; + cm.display.poll.set(cm.options.pollInterval, function() { + readInput(cm); + if (cm.view.focused) slowPoll(cm); + }); + } + + function fastPoll(cm) { + var missed = false; + cm.display.pollingFast = true; + function p() { + var changed = readInput(cm); + if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);} + else {cm.display.pollingFast = false; slowPoll(cm);} + } + cm.display.poll.set(20, p); + } + + // prevInput is a hack to work with IME. If we reset the textarea + // on every change, that breaks IME. So we look for changes + // compared to the previous content instead. (Modern browsers have + // events that indicate IME taking place, but these are not widely + // supported or compatible enough yet to rely on.) + function readInput(cm) { + var input = cm.display.input, prevInput = cm.display.prevInput, view = cm.view, sel = view.sel; + if (!view.focused || hasSelection(input) || isReadOnly(cm)) return false; + var text = input.value; + if (text == prevInput && posEq(sel.from, sel.to)) return false; + startOperation(cm); + view.sel.shift = false; + var same = 0, l = Math.min(prevInput.length, text.length); + while (same < l && prevInput[same] == text[same]) ++same; + var from = sel.from, to = sel.to; + if (same < prevInput.length) + from = {line: from.line, ch: from.ch - (prevInput.length - same)}; + else if (view.overwrite && posEq(from, to) && !cm.display.pasteIncoming) + to = {line: to.line, ch: Math.min(getLine(cm.view.doc, to.line).text.length, to.ch + (text.length - same))}; + var updateInput = cm.curOp.updateInput; + updateDoc(cm, from, to, splitLines(text.slice(same)), "end", + cm.display.pasteIncoming ? "paste" : "input", {from: from, to: to}); + cm.curOp.updateInput = updateInput; + if (text.length > 1000) input.value = cm.display.prevInput = ""; + else cm.display.prevInput = text; + endOperation(cm); + cm.display.pasteIncoming = false; + return true; + } + + function resetInput(cm, user) { + var view = cm.view, minimal, selected; + if (!posEq(view.sel.from, view.sel.to)) { + cm.display.prevInput = ""; + minimal = hasCopyEvent && + (view.sel.to.line - view.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000); + if (minimal) cm.display.input.value = "-"; + else cm.display.input.value = selected || cm.getSelection(); + if (view.focused) selectInput(cm.display.input); + } else if (user) cm.display.prevInput = cm.display.input.value = ""; + cm.display.inaccurateSelection = minimal; + } + + function focusInput(cm) { + if (cm.options.readOnly != "nocursor" && (ie || document.activeElement != cm.display.input)) + cm.display.input.focus(); + } + + function isReadOnly(cm) { + return cm.options.readOnly || cm.view.cantEdit; + } + + // EVENT HANDLERS + + function registerEventHandlers(cm) { + var d = cm.display; + on(d.scroller, "mousedown", operation(cm, onMouseDown)); + on(d.scroller, "dblclick", operation(cm, e_preventDefault)); + on(d.lineSpace, "selectstart", function(e) { + if (!mouseEventInWidget(d, e)) e_preventDefault(e); + }); + // Gecko browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for Gecko. + if (!gecko) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);}); + + on(d.scroller, "scroll", function() { + setScrollTop(cm, d.scroller.scrollTop); + setScrollLeft(cm, d.scroller.scrollLeft, true); + signal(cm, "scroll", cm); + }); + on(d.scrollbarV, "scroll", function() { + setScrollTop(cm, d.scrollbarV.scrollTop); + }); + on(d.scrollbarH, "scroll", function() { + setScrollLeft(cm, d.scrollbarH.scrollLeft); + }); + + on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);}); + on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);}); + + function reFocus() { if (cm.view.focused) setTimeout(bind(focusInput, cm), 0); } + on(d.scrollbarH, "mousedown", reFocus); + on(d.scrollbarV, "mousedown", reFocus); + // Prevent wrapper from ever scrolling + on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); + on(window, "resize", function resizeHandler() { + // Might be a text scaling operation, clear size caches. + d.cachedCharWidth = d.cachedTextHeight = null; + clearCaches(cm); + if (d.wrapper.parentNode) updateDisplay(cm, true); + else off(window, "resize", resizeHandler); + }); + + on(d.input, "keyup", operation(cm, function(e) { + if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + if (e_prop(e, "keyCode") == 16) cm.view.sel.shift = false; + })); + on(d.input, "input", bind(fastPoll, cm)); + on(d.input, "keydown", operation(cm, onKeyDown)); + on(d.input, "keypress", operation(cm, onKeyPress)); + on(d.input, "focus", bind(onFocus, cm)); + on(d.input, "blur", bind(onBlur, cm)); + + function drag_(e) { + if (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return; + e_stop(e); + } + if (cm.options.dragDrop) { + on(d.scroller, "dragstart", function(e){onDragStart(cm, e);}); + on(d.scroller, "dragenter", drag_); + on(d.scroller, "dragover", drag_); + on(d.scroller, "drop", operation(cm, onDrop)); + } + on(d.scroller, "paste", function(){focusInput(cm); fastPoll(cm);}); + on(d.input, "paste", function() { + d.pasteIncoming = true; + fastPoll(cm); + }); + + function prepareCopy() { + if (d.inaccurateSelection) { + d.prevInput = ""; + d.inaccurateSelection = false; + d.input.value = cm.getSelection(); + selectInput(d.input); + } + } + on(d.input, "cut", prepareCopy); + on(d.input, "copy", prepareCopy); + + // Needed to handle Tab key in KHTML + if (khtml) on(d.sizer, "mouseup", function() { + if (document.activeElement == d.input) d.input.blur(); + focusInput(cm); + }); + } + + function mouseEventInWidget(display, e) { + for (var n = e_target(e); n != display.wrapper; n = n.parentNode) + if (/\bCodeMirror-(?:line)?widget\b/.test(n.className) || + n.parentNode == display.sizer && n != display.mover) return true; + } + + function posFromMouse(cm, e, liberal) { + var display = cm.display; + if (!liberal) { + var target = e_target(e); + if (target == display.scrollbarH || target == display.scrollbarH.firstChild || + target == display.scrollbarV || target == display.scrollbarV.firstChild || + target == display.scrollbarFiller) return null; + } + var x, y, space = display.lineSpace.getBoundingClientRect(); + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX; y = e.clientY; } catch (e) { return null; } + return coordsChar(cm, x - space.left, y - space.top); + } + + var lastClick, lastDoubleClick; + function onMouseDown(e) { + var cm = this, display = cm.display, view = cm.view, sel = view.sel, doc = view.doc; + sel.shift = e_prop(e, "shiftKey"); + + if (mouseEventInWidget(display, e)) { + if (!webkit) { + display.scroller.draggable = false; + setTimeout(function(){display.scroller.draggable = true;}, 100); + } + return; + } + if (clickInGutter(cm, e)) return; + var start = posFromMouse(cm, e); + + switch (e_button(e)) { + case 3: + if (gecko) onContextMenu.call(cm, cm, e); + return; + case 2: + if (start) extendSelection(cm, start); + setTimeout(bind(focusInput, cm), 20); + e_preventDefault(e); + return; + } + // For button 1, if it was clicked inside the editor + // (posFromMouse returning non-null), we have to adjust the + // selection. + if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;} + + if (!view.focused) onFocus(cm); + + var now = +new Date, type = "single"; + if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) { + type = "triple"; + e_preventDefault(e); + setTimeout(bind(focusInput, cm), 20); + selectLine(cm, start.line); + } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) { + type = "double"; + lastDoubleClick = {time: now, pos: start}; + e_preventDefault(e); + var word = findWordAt(getLine(doc, start.line).text, start); + extendSelection(cm, word.from, word.to); + } else { lastClick = {time: now, pos: start}; } + + var last = start; + if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) && + !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") { + var dragEnd = operation(cm, function(e2) { + if (webkit) display.scroller.draggable = false; + view.draggingText = false; + off(document, "mouseup", dragEnd); + off(display.scroller, "drop", dragEnd); + if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { + e_preventDefault(e2); + extendSelection(cm, start); + focusInput(cm); + } + }); + // Let the drag handler handle this. + if (webkit) display.scroller.draggable = true; + view.draggingText = dragEnd; + // IE's approach to draggable + if (display.scroller.dragDrop) display.scroller.dragDrop(); + on(document, "mouseup", dragEnd); + on(display.scroller, "drop", dragEnd); + return; + } + e_preventDefault(e); + if (type == "single") extendSelection(cm, clipPos(doc, start)); + + var startstart = sel.from, startend = sel.to; + + function doSelect(cur) { + if (type == "single") { + extendSelection(cm, clipPos(doc, start), cur); + return; + } + + startstart = clipPos(doc, startstart); + startend = clipPos(doc, startend); + if (type == "double") { + var word = findWordAt(getLine(doc, cur.line).text, cur); + if (posLess(cur, startstart)) extendSelection(cm, word.from, startend); + else extendSelection(cm, startstart, word.to); + } else if (type == "triple") { + if (posLess(cur, startstart)) extendSelection(cm, startend, clipPos(doc, {line: cur.line, ch: 0})); + else extendSelection(cm, startstart, clipPos(doc, {line: cur.line + 1, ch: 0})); + } + } + + var editorSize = display.wrapper.getBoundingClientRect(); + // Used to ensure timeout re-tries don't fire when another extend + // happened in the meantime (clearTimeout isn't reliable -- at + // least on Chrome, the timeouts still happen even when cleared, + // if the clear happens after their scheduled firing time). + var counter = 0; + + function extend(e) { + var curCount = ++counter; + var cur = posFromMouse(cm, e, true); + if (!cur) return; + if (!posEq(cur, last)) { + if (!view.focused) onFocus(cm); + last = cur; + doSelect(cur); + var visible = visibleLines(display, doc); + if (cur.line >= visible.to || cur.line < visible.from) + setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150); + } else { + var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; + if (outside) setTimeout(operation(cm, function() { + if (counter != curCount) return; + display.scroller.scrollTop += outside; + extend(e); + }), 50); + } + } + + function done(e) { + counter = Infinity; + var cur = posFromMouse(cm, e); + if (cur) doSelect(cur); + e_preventDefault(e); + focusInput(cm); + off(document, "mousemove", move); + off(document, "mouseup", up); + } + + var move = operation(cm, function(e) { + if (!ie && !e_button(e)) done(e); + else extend(e); + }); + var up = operation(cm, done); + on(document, "mousemove", move); + on(document, "mouseup", up); + } + + function onDrop(e) { + var cm = this; + if (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return; + e_preventDefault(e); + var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; + if (!pos || isReadOnly(cm)) return; + if (files && files.length && window.FileReader && window.File) { + var n = files.length, text = Array(n), read = 0; + var loadFile = function(file, i) { + var reader = new FileReader; + reader.onload = function() { + text[i] = reader.result; + if (++read == n) { + pos = clipPos(cm.view.doc, pos); + operation(cm, function() { + var end = replaceRange(cm, text.join(""), pos, pos, "paste"); + setSelection(cm, pos, end); + })(); + } + }; + reader.readAsText(file); + }; + for (var i = 0; i < n; ++i) loadFile(files[i], i); + } else { + // Don't do a replace if the drop happened inside of the selected text. + if (cm.view.draggingText && !(posLess(pos, cm.view.sel.from) || posLess(cm.view.sel.to, pos))) { + cm.view.draggingText(e); + if (ie) setTimeout(bind(focusInput, cm), 50); + return; + } + try { + var text = e.dataTransfer.getData("Text"); + if (text) { + var curFrom = cm.view.sel.from, curTo = cm.view.sel.to; + setSelection(cm, pos, pos); + if (cm.view.draggingText) replaceRange(cm, "", curFrom, curTo, "paste"); + cm.replaceSelection(text, null, "paste"); + focusInput(cm); + onFocus(cm); + } + } + catch(e){} + } + } + + function clickInGutter(cm, e) { + var display = cm.display; + try { var mX = e.clientX, mY = e.clientY; } + catch(e) { return false; } + + if (mX >= Math.floor(display.gutters.getBoundingClientRect().right)) return false; + e_preventDefault(e); + if (!hasHandler(cm, "gutterClick")) return true; + + var lineBox = display.lineDiv.getBoundingClientRect(); + if (mY > lineBox.bottom) return true; + mY -= lineBox.top - display.viewOffset; + + for (var i = 0; i < cm.options.gutters.length; ++i) { + var g = display.gutters.childNodes[i]; + if (g && g.getBoundingClientRect().right >= mX) { + var line = lineAtHeight(cm.view.doc, mY); + var gutter = cm.options.gutters[i]; + signalLater(cm, cm, "gutterClick", cm, line, gutter, e); + break; + } + } + return true; + } + + function onDragStart(cm, e) { + var txt = cm.getSelection(); + e.dataTransfer.setData("Text", txt); + + // Use dummy image instead of default browsers image. + // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. + if (e.dataTransfer.setDragImage && !safari) + e.dataTransfer.setDragImage(elt('img'), 0, 0); + } + + function setScrollTop(cm, val) { + if (Math.abs(cm.view.scrollTop - val) < 2) return; + cm.view.scrollTop = val; + if (!gecko) updateDisplay(cm, [], val); + if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val; + if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val; + if (gecko) updateDisplay(cm, []); + } + function setScrollLeft(cm, val, isScroller) { + if (isScroller ? val == cm.view.scrollLeft : Math.abs(cm.view.scrollLeft - val) < 2) return; + cm.view.scrollLeft = val; + alignHorizontally(cm); + if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val; + if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val; + } + + // Since the delta values reported on mouse wheel events are + // unstandardized between browsers and even browser versions, and + // generally horribly unpredictable, this code starts by measuring + // the scroll effect that the first few mouse wheel events have, + // and, from that, detects the way it can convert deltas to pixel + // offsets afterwards. + // + // The reason we want to know the amount a wheel event will scroll + // is that it gives us a chance to update the display before the + // actual scrolling happens, reducing flickering. + + var wheelSamples = 0, wheelDX, wheelDY, wheelStartX, wheelStartY, wheelPixelsPerUnit = null; + // Fill in a browser-detected starting value on browsers where we + // know one. These don't have to be accurate -- the result of them + // being wrong would just be a slight flicker on the first wheel + // scroll (if it is large enough). + if (ie) wheelPixelsPerUnit = -.53; + else if (gecko) wheelPixelsPerUnit = 15; + else if (chrome) wheelPixelsPerUnit = -.7; + else if (safari) wheelPixelsPerUnit = -1/3; + + function onScrollWheel(cm, e) { + var dx = e.wheelDeltaX, dy = e.wheelDeltaY; + if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail; + if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail; + else if (dy == null) dy = e.wheelDelta; + + // Webkit browsers on OS X abort momentum scrolls when the target + // of the scroll event is removed from the scrollable element. + // This hack (see related code in patchDisplay) makes sure the + // element is kept around. + if (dy && mac && webkit) { + for (var cur = e.target; cur != scroll; cur = cur.parentNode) { + if (cur.lineObj) { + cm.display.currentWheelTarget = cur; + break; + } + } + } + + var scroll = cm.display.scroller; + // On some browsers, horizontal scrolling will cause redraws to + // happen before the gutter has been realigned, causing it to + // wriggle around in a most unseemly way. When we have an + // estimated pixels/delta value, we just handle horizontal + // scrolling entirely here. It'll be slightly off from native, but + // better than glitching out. + if (dx && !gecko && !opera && wheelPixelsPerUnit != null) { + if (dy) + setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))); + setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))); + e_preventDefault(e); + wheelStartX = null; // Abort measurement, if in progress + return; + } + + if (dy && wheelPixelsPerUnit != null) { + var pixels = dy * wheelPixelsPerUnit; + var top = cm.view.scrollTop, bot = top + cm.display.wrapper.clientHeight; + if (pixels < 0) top = Math.max(0, top + pixels - 50); + else bot = Math.min(cm.view.doc.height, bot + pixels + 50); + updateDisplay(cm, [], {top: top, bottom: bot}); + } + + if (wheelSamples < 20) { + if (wheelStartX == null) { + wheelStartX = scroll.scrollLeft; wheelStartY = scroll.scrollTop; + wheelDX = dx; wheelDY = dy; + setTimeout(function() { + if (wheelStartX == null) return; + var movedX = scroll.scrollLeft - wheelStartX; + var movedY = scroll.scrollTop - wheelStartY; + var sample = (movedY && wheelDY && movedY / wheelDY) || + (movedX && wheelDX && movedX / wheelDX); + wheelStartX = wheelStartY = null; + if (!sample) return; + wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); + ++wheelSamples; + }, 200); + } else { + wheelDX += dx; wheelDY += dy; + } + } + } + + function doHandleBinding(cm, bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound]; + if (!bound) return false; + } + // Ensure previous input has been read, so that the handler sees a + // consistent view of the document + if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false; + var view = cm.view, prevShift = view.sel.shift; + try { + if (isReadOnly(cm)) view.suppressEdits = true; + if (dropShift) view.sel.shift = false; + bound(cm); + } catch(e) { + if (e != Pass) throw e; + return false; + } finally { + view.sel.shift = prevShift; + view.suppressEdits = false; + } + return true; + } + + function allKeyMaps(cm) { + var maps = cm.view.keyMaps.slice(0); + maps.push(cm.options.keyMap); + if (cm.options.extraKeys) maps.unshift(cm.options.extraKeys); + return maps; + } + + var maybeTransition; + function handleKeyBinding(cm, e) { + // Handle auto keymap transitions + var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto; + clearTimeout(maybeTransition); + if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() { + if (getKeyMap(cm.options.keyMap) == startMap) + cm.options.keyMap = (next.call ? next.call(null, cm) : next); + }, 50); + + var name = keyNames[e_prop(e, "keyCode")], handled = false; + var flipCtrlCmd = mac && (opera || qtwebkit); + if (name == null || e.altGraphKey) return false; + if (e_prop(e, "altKey")) name = "Alt-" + name; + if (e_prop(e, flipCtrlCmd ? "metaKey" : "ctrlKey")) name = "Ctrl-" + name; + if (e_prop(e, flipCtrlCmd ? "ctrlKey" : "metaKey")) name = "Cmd-" + name; + + var stopped = false; + function stop() { stopped = true; } + var keymaps = allKeyMaps(cm); + + if (e_prop(e, "shiftKey")) { + handled = lookupKey("Shift-" + name, keymaps, + function(b) {return doHandleBinding(cm, b, true);}, stop) + || lookupKey(name, keymaps, function(b) { + if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(cm, b); + }, stop); + } else { + handled = lookupKey(name, keymaps, + function(b) { return doHandleBinding(cm, b); }, stop); + } + if (stopped) handled = false; + if (handled) { + e_preventDefault(e); + restartBlink(cm); + if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; } + } + return handled; + } + + function handleCharBinding(cm, e, ch) { + var handled = lookupKey("'" + ch + "'", allKeyMaps(cm), + function(b) { return doHandleBinding(cm, b, true); }); + if (handled) { + e_preventDefault(e); + restartBlink(cm); + } + return handled; + } + + var lastStoppedKey = null; + function onKeyDown(e) { + var cm = this; + if (!cm.view.focused) onFocus(cm); + if (ie && e.keyCode == 27) { e.returnValue = false; } + if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + var code = e_prop(e, "keyCode"); + // IE does strange things with escape. + cm.view.sel.shift = code == 16 || e_prop(e, "shiftKey"); + // First give onKeyEvent option a chance to handle this. + var handled = handleKeyBinding(cm, e); + if (opera) { + lastStoppedKey = handled ? code : null; + // Opera has no cut event... we try to at least catch the key combo + if (!handled && code == 88 && !hasCopyEvent && e_prop(e, mac ? "metaKey" : "ctrlKey")) + cm.replaceSelection(""); + } + } + + function onKeyPress(e) { + var cm = this; + if (cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return; + var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode"); + if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} + if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return; + var ch = String.fromCharCode(charCode == null ? keyCode : charCode); + if (this.options.electricChars && this.view.mode.electricChars && + this.options.smartIndent && !isReadOnly(this) && + this.view.mode.electricChars.indexOf(ch) > -1) + setTimeout(operation(cm, function() {indentLine(cm, cm.view.sel.to.line, "smart");}), 75); + if (handleCharBinding(cm, e, ch)) return; + fastPoll(cm); + } + + function onFocus(cm) { + if (cm.options.readOnly == "nocursor") return; + if (!cm.view.focused) { + signal(cm, "focus", cm); + cm.view.focused = true; + if (cm.display.scroller.className.search(/\bCodeMirror-focused\b/) == -1) + cm.display.scroller.className += " CodeMirror-focused"; + resetInput(cm, true); + } + slowPoll(cm); + restartBlink(cm); + } + function onBlur(cm) { + if (cm.view.focused) { + signal(cm, "blur", cm); + cm.view.focused = false; + cm.display.scroller.className = cm.display.scroller.className.replace(" CodeMirror-focused", ""); + } + clearInterval(cm.display.blinker); + setTimeout(function() {if (!cm.view.focused) cm.view.sel.shift = false;}, 150); + } + + var detectingSelectAll; + function onContextMenu(cm, e) { + var display = cm.display, sel = cm.view.sel; + var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; + if (!pos || opera) return; // Opera is difficult. + if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)) + operation(cm, setSelection)(cm, pos, pos); + + var oldCSS = display.input.style.cssText; + display.inputDiv.style.position = "absolute"; + display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + + "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" + + "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + focusInput(cm); + resetInput(cm, true); + // Adds "Select all" to context menu in FF + if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " "; + + function rehide() { + display.inputDiv.style.position = "relative"; + display.input.style.cssText = oldCSS; + if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos; + slowPoll(cm); + + // Try to detect the user choosing select-all + if (display.input.selectionStart != null) { + clearTimeout(detectingSelectAll); + var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0; + display.prevInput = " "; + display.input.selectionStart = 1; display.input.selectionEnd = extval.length; + detectingSelectAll = setTimeout(function poll(){ + if (display.prevInput == " " && display.input.selectionStart == 0) + operation(cm, commands.selectAll)(cm); + else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); + else resetInput(cm); + }, 200); + } + } + + if (gecko) { + e_stop(e); + on(window, "mouseup", function mouseup() { + off(window, "mouseup", mouseup); + setTimeout(rehide, 20); + }); + } else { + setTimeout(rehide, 50); + } + } + + // UPDATING + + // Replace the range from from to to by the strings in newText. + // Afterwards, set the selection to selFrom, selTo. + function updateDoc(cm, from, to, newText, selUpdate, origin) { + // Possibly split or suppress the update based on the presence + // of read-only spans in its range. + var split = sawReadOnlySpans && + removeReadOnlyRanges(cm.view.doc, from, to); + if (split) { + for (var i = split.length - 1; i >= 1; --i) + updateDocInner(cm, split[i].from, split[i].to, [""], origin); + if (split.length) + return updateDocInner(cm, split[0].from, split[0].to, newText, selUpdate, origin); + } else { + return updateDocInner(cm, from, to, newText, selUpdate, origin); + } + } + + function updateDocInner(cm, from, to, newText, selUpdate, origin) { + if (cm.view.suppressEdits) return; + + var view = cm.view, doc = view.doc, old = []; + doc.iter(from.line, to.line + 1, function(line) { + old.push(newHL(line.text, line.markedSpans)); + }); + var startSelFrom = view.sel.from, startSelTo = view.sel.to; + var lines = updateMarkedSpans(hlSpans(old[0]), hlSpans(lst(old)), from.ch, to.ch, newText); + var retval = updateDocNoUndo(cm, from, to, lines, selUpdate, origin); + if (view.history) addChange(cm, from.line, newText.length, old, origin, + startSelFrom, startSelTo, view.sel.from, view.sel.to); + return retval; + } + + function unredoHelper(cm, type) { + var doc = cm.view.doc, hist = cm.view.history; + var set = (type == "undo" ? hist.done : hist.undone).pop(); + if (!set) return; + var anti = {events: [], fromBefore: set.fromAfter, toBefore: set.toAfter, + fromAfter: set.fromBefore, toAfter: set.toBefore}; + for (var i = set.events.length - 1; i >= 0; i -= 1) { + hist.dirtyCounter += type == "undo" ? -1 : 1; + var change = set.events[i]; + var replaced = [], end = change.start + change.added; + doc.iter(change.start, end, function(line) { replaced.push(newHL(line.text, line.markedSpans)); }); + anti.events.push({start: change.start, added: change.old.length, old: replaced}); + var selPos = i ? null : {from: set.fromBefore, to: set.toBefore}; + updateDocNoUndo(cm, {line: change.start, ch: 0}, {line: end - 1, ch: getLine(doc, end-1).text.length}, + change.old, selPos, type); + } + (type == "undo" ? hist.undone : hist.done).push(anti); + } + + function updateDocNoUndo(cm, from, to, lines, selUpdate, origin) { + var view = cm.view, doc = view.doc, display = cm.display; + if (view.suppressEdits) return; + + var nlines = to.line - from.line, firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); + var recomputeMaxLength = false, checkWidthStart = from.line; + if (!cm.options.lineWrapping) { + checkWidthStart = lineNo(visualLine(doc, firstLine)); + doc.iter(checkWidthStart, to.line + 1, function(line) { + if (lineLength(doc, line) == view.maxLineLength) { + recomputeMaxLength = true; + return true; + } + }); + } + + var lastHL = lst(lines), th = textHeight(display); + + // First adjust the line structure + if (from.ch == 0 && to.ch == 0 && hlText(lastHL) == "") { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = []; + for (var i = 0, e = lines.length - 1; i < e; ++i) + added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th)); + updateLine(cm, lastLine, lastLine.text, hlSpans(lastHL)); + if (nlines) doc.remove(from.line, nlines, cm); + if (added.length) doc.insert(from.line, added); + } else if (firstLine == lastLine) { + if (lines.length == 1) { + updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]) + + firstLine.text.slice(to.ch), hlSpans(lines[0])); + } else { + for (var added = [], i = 1, e = lines.length - 1; i < e; ++i) + added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th)); + added.push(makeLine(hlText(lastHL) + firstLine.text.slice(to.ch), hlSpans(lastHL), th)); + updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0])); + doc.insert(from.line + 1, added); + } + } else if (lines.length == 1) { + updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]) + + lastLine.text.slice(to.ch), hlSpans(lines[0])); + doc.remove(from.line + 1, nlines, cm); + } else { + var added = []; + updateLine(cm, firstLine, firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0])); + updateLine(cm, lastLine, hlText(lastHL) + lastLine.text.slice(to.ch), hlSpans(lastHL)); + for (var i = 1, e = lines.length - 1; i < e; ++i) + added.push(makeLine(hlText(lines[i]), hlSpans(lines[i]), th)); + if (nlines > 1) doc.remove(from.line + 1, nlines - 1, cm); + doc.insert(from.line + 1, added); + } + + if (cm.options.lineWrapping) { + var perLine = Math.max(5, display.scroller.clientWidth / charWidth(display) - 3); + doc.iter(from.line, from.line + lines.length, function(line) { + if (line.height == 0) return; + var guess = (Math.ceil(line.text.length / perLine) || 1) * th; + if (guess != line.height) updateLineHeight(line, guess); + }); + } else { + doc.iter(checkWidthStart, from.line + lines.length, function(line) { + var len = lineLength(doc, line); + if (len > view.maxLineLength) { + view.maxLine = line; + view.maxLineLength = len; + view.maxLineChanged = true; + recomputeMaxLength = false; + } + }); + if (recomputeMaxLength) cm.curOp.updateMaxLine = true; + } + + // Adjust frontier, schedule worker + view.frontier = Math.min(view.frontier, from.line); + startWorker(cm, 400); + + var lendiff = lines.length - nlines - 1; + // Remember that these lines changed, for updating the display + regChange(cm, from.line, to.line + 1, lendiff); + if (hasHandler(cm, "change")) { + // Normalize lines to contain only strings, since that's what + // the change event handler expects + for (var i = 0; i < lines.length; ++i) + if (typeof lines[i] != "string") lines[i] = lines[i].text; + var changeObj = {from: from, to: to, text: lines, origin: origin}; + if (cm.curOp.textChanged) { + for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {} + cur.next = changeObj; + } else cm.curOp.textChanged = changeObj; + } + + // Update the selection + var newSelFrom, newSelTo, end = {line: from.line + lines.length - 1, + ch: hlText(lastHL).length + (lines.length == 1 ? from.ch : 0)}; + if (selUpdate && typeof selUpdate != "string") { + if (selUpdate.from) { newSelFrom = selUpdate.from; newSelTo = selUpdate.to; } + else newSelFrom = newSelTo = selUpdate; + } else if (selUpdate == "end") { + newSelFrom = newSelTo = end; + } else if (selUpdate == "start") { + newSelFrom = newSelTo = from; + } else if (selUpdate == "around") { + newSelFrom = from; newSelTo = end; + } else { + var adjustPos = function(pos) { + if (posLess(pos, from)) return pos; + if (!posLess(to, pos)) return end; + var line = pos.line + lendiff; + var ch = pos.ch; + if (pos.line == to.line) + ch += hlText(lastHL).length - (to.ch - (to.line == from.line ? from.ch : 0)); + return {line: line, ch: ch}; + }; + newSelFrom = adjustPos(view.sel.from); + newSelTo = adjustPos(view.sel.to); + } + setSelection(cm, newSelFrom, newSelTo, null, true); + return end; + } + + function replaceRange(cm, code, from, to, origin) { + if (!to) to = from; + if (posLess(to, from)) { var tmp = to; to = from; from = tmp; } + return updateDoc(cm, from, to, splitLines(code), null, origin); + } + + // SELECTION + + function posEq(a, b) {return a.line == b.line && a.ch == b.ch;} + function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);} + function copyPos(x) {return {line: x.line, ch: x.ch};} + + function clipLine(doc, n) {return Math.max(0, Math.min(n, doc.size-1));} + function clipPos(doc, pos) { + if (pos.line < 0) return {line: 0, ch: 0}; + if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc, doc.size-1).text.length}; + var ch = pos.ch, linelen = getLine(doc, pos.line).text.length; + if (ch == null || ch > linelen) return {line: pos.line, ch: linelen}; + else if (ch < 0) return {line: pos.line, ch: 0}; + else return pos; + } + function isLine(doc, l) {return l >= 0 && l < doc.size;} + + // If shift is held, this will move the selection anchor. Otherwise, + // it'll set the whole selection. + function extendSelection(cm, pos, other, bias) { + var sel = cm.view.sel; + if (sel.shift || sel.extend) { + var anchor = sel.anchor; + if (other) { + var posBefore = posLess(pos, anchor); + if (posBefore != posLess(other, anchor)) { + anchor = pos; + pos = other; + } else if (posBefore != posLess(pos, other)) { + pos = other; + } + } + setSelection(cm, anchor, pos, bias); + } else { + setSelection(cm, pos, other || pos, bias); + } + cm.curOp.userSelChange = true; + } + + // Update the selection. Last two args are only used by + // updateDoc, since they have to be expressed in the line + // numbers before the update. + function setSelection(cm, anchor, head, bias, checkAtomic) { + cm.view.goalColumn = null; + var sel = cm.view.sel; + // Skip over atomic spans. + if (checkAtomic || !posEq(anchor, sel.anchor)) + anchor = skipAtomic(cm, anchor, bias, checkAtomic != "push"); + if (checkAtomic || !posEq(head, sel.head)) + head = skipAtomic(cm, head, bias, checkAtomic != "push"); + + if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return; + + sel.anchor = anchor; sel.head = head; + var inv = posLess(head, anchor); + sel.from = inv ? head : anchor; + sel.to = inv ? anchor : head; + + cm.curOp.updateInput = true; + cm.curOp.selectionChanged = true; + } + + function reCheckSelection(cm) { + setSelection(cm, cm.view.sel.from, cm.view.sel.to, null, "push"); + } + + function skipAtomic(cm, pos, bias, mayClear) { + var doc = cm.view.doc, flipped = false, curPos = pos; + var dir = bias || 1; + cm.view.cantEdit = false; + search: for (;;) { + var line = getLine(doc, curPos.line), toClear; + if (line.markedSpans) { + for (var i = 0; i < line.markedSpans.length; ++i) { + var sp = line.markedSpans[i], m = sp.marker; + if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) && + (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) { + if (mayClear && m.clearOnEnter) { + (toClear || (toClear = [])).push(m); + continue; + } else if (!m.atomic) continue; + var newPos = m.find()[dir < 0 ? "from" : "to"]; + if (posEq(newPos, curPos)) { + newPos.ch += dir; + if (newPos.ch < 0) { + if (newPos.line) newPos = clipPos(doc, {line: newPos.line - 1}); + else newPos = null; + } else if (newPos.ch > line.text.length) { + if (newPos.line < doc.size - 1) newPos = {line: newPos.line + 1, ch: 0}; + else newPos = null; + } + if (!newPos) { + if (flipped) { + // Driven in a corner -- no valid cursor position found at all + // -- try again *with* clearing, if we didn't already + if (!mayClear) return skipAtomic(cm, pos, bias, true); + // Otherwise, turn off editing until further notice, and return the start of the doc + cm.view.cantEdit = true; + return {line: 0, ch: 0}; + } + flipped = true; newPos = pos; dir = -dir; + } + } + curPos = newPos; + continue search; + } + } + if (toClear) for (var i = 0; i < toClear.length; ++i) toClear[i].clear(); + } + return curPos; + } + } + + // SCROLLING + + function scrollCursorIntoView(cm) { + var view = cm.view; + var coords = scrollPosIntoView(cm, view.sel.head); + if (!view.focused) return; + var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; + if (coords.top + box.top < 0) doScroll = true; + else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; + if (doScroll != null && !phantom) { + var hidden = display.cursor.style.display == "none"; + if (hidden) { + display.cursor.style.display = ""; + display.cursor.style.left = coords.left + "px"; + display.cursor.style.top = (coords.top - display.viewOffset) + "px"; + } + display.cursor.scrollIntoView(doScroll); + if (hidden) display.cursor.style.display = "none"; + } + } + + function scrollPosIntoView(cm, pos) { + for (;;) { + var changed = false, coords = cursorCoords(cm, pos); + var scrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom); + var startTop = cm.view.scrollTop, startLeft = cm.view.scrollLeft; + if (scrollPos.scrollTop != null) { + setScrollTop(cm, scrollPos.scrollTop); + if (Math.abs(cm.view.scrollTop - startTop) > 1) changed = true; + } + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft); + if (Math.abs(cm.view.scrollLeft - startLeft) > 1) changed = true; + } + if (!changed) return coords; + } + } + + function scrollIntoView(cm, x1, y1, x2, y2) { + var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2); + if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop); + if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft); + } + + function calculateScrollPos(cm, x1, y1, x2, y2) { + var display = cm.display, pt = paddingTop(display); + y1 += pt; y2 += pt; + var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {}; + var docBottom = cm.view.doc.height + 2 * pt; + var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10; + if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1); + else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen; + + var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft; + x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth; + var gutterw = display.gutters.offsetWidth; + var atLeft = x1 < gutterw + 10; + if (x1 < screenleft + gutterw || atLeft) { + if (atLeft) x1 = 0; + result.scrollLeft = Math.max(0, x1 - 10 - gutterw); + } else if (x2 > screenw + screenleft - 3) { + result.scrollLeft = x2 + 10 - screenw; + } + return result; + } + + // API UTILITIES + + function indentLine(cm, n, how, aggressive) { + var doc = cm.view.doc; + if (!how) how = "add"; + if (how == "smart") { + if (!cm.view.mode.indent) how = "prev"; + else var state = getStateBefore(cm, n); + } + + var tabSize = cm.options.tabSize; + var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); + var curSpaceString = line.text.match(/^\s*/)[0], indentation; + if (how == "smart") { + indentation = cm.view.mode.indent(state, line.text.slice(curSpaceString.length), line.text); + if (indentation == Pass) { + if (!aggressive) return; + how = "prev"; + } + } + if (how == "prev") { + if (n) indentation = countColumn(getLine(doc, n-1).text, null, tabSize); + else indentation = 0; + } + else if (how == "add") indentation = curSpace + cm.options.indentUnit; + else if (how == "subtract") indentation = curSpace - cm.options.indentUnit; + indentation = Math.max(0, indentation); + + var indentString = "", pos = 0; + if (cm.options.indentWithTabs) + for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} + if (pos < indentation) indentString += spaceStr(indentation - pos); + + if (indentString != curSpaceString) + replaceRange(cm, indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length}, "input"); + line.stateAfter = null; + } + + function changeLine(cm, handle, op) { + var no = handle, line = handle, doc = cm.view.doc; + if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle)); + else no = lineNo(handle); + if (no == null) return null; + if (op(line, no)) regChange(cm, no, no + 1); + else return null; + return line; + } + + function findPosH(cm, dir, unit, visually) { + var doc = cm.view.doc, end = cm.view.sel.head, line = end.line, ch = end.ch; + var lineObj = getLine(doc, line); + function findNextLine() { + var l = line + dir; + if (l < 0 || l == doc.size) return false; + line = l; + return lineObj = getLine(doc, l); + } + function moveOnce(boundToLine) { + var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true); + if (next == null) { + if (!boundToLine && findNextLine()) { + if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj); + else ch = dir < 0 ? lineObj.text.length : 0; + } else return false; + } else ch = next; + return true; + } + if (unit == "char") moveOnce(); + else if (unit == "column") moveOnce(true); + else if (unit == "word") { + var sawWord = false; + for (;;) { + if (dir < 0) if (!moveOnce()) break; + if (isWordChar(lineObj.text.charAt(ch))) sawWord = true; + else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;} + if (dir > 0) if (!moveOnce()) break; + } + } + return skipAtomic(cm, {line: line, ch: ch}, dir, true); + } + + function findWordAt(line, pos) { + var start = pos.ch, end = pos.ch; + if (line) { + if (pos.after === false || end == line.length) --start; else ++end; + var startChar = line.charAt(start); + var check = isWordChar(startChar) ? isWordChar : + /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} : + function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; + while (start > 0 && check(line.charAt(start - 1))) --start; + while (end < line.length && check(line.charAt(end))) ++end; + } + return {from: {line: pos.line, ch: start}, to: {line: pos.line, ch: end}}; + } + + function selectLine(cm, line) { + extendSelection(cm, {line: line, ch: 0}, clipPos(cm.view.doc, {line: line + 1, ch: 0})); + } + + // PROTOTYPE + + // The publicly visible API. Note that operation(null, f) means + // 'wrap f in an operation, performed on its `this` parameter' + + CodeMirror.prototype = { + getValue: function(lineSep) { + var text = [], doc = this.view.doc; + doc.iter(0, doc.size, function(line) { text.push(line.text); }); + return text.join(lineSep || "\n"); + }, + + setValue: operation(null, function(code) { + var doc = this.view.doc, top = {line: 0, ch: 0}, lastLen = getLine(doc, doc.size-1).text.length; + updateDocInner(this, top, {line: doc.size - 1, ch: lastLen}, splitLines(code), top, top, "setValue"); + }), + + getSelection: function(lineSep) { return this.getRange(this.view.sel.from, this.view.sel.to, lineSep); }, + + replaceSelection: operation(null, function(code, collapse, origin) { + var sel = this.view.sel; + updateDoc(this, sel.from, sel.to, splitLines(code), collapse || "around", origin); + }), + + focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);}, + + setOption: function(option, value) { + var options = this.options, old = options[option]; + if (options[option] == value && option != "mode") return; + options[option] = value; + if (optionHandlers.hasOwnProperty(option)) + operation(this, optionHandlers[option])(this, value, old); + }, + + getOption: function(option) {return this.options[option];}, + + getMode: function() {return this.view.mode;}, + + addKeyMap: function(map) { + this.view.keyMaps.push(map); + }, + + removeKeyMap: function(map) { + var maps = this.view.keyMaps; + for (var i = 0; i < maps.length; ++i) + if ((typeof map == "string" ? maps[i].name : maps[i]) == map) { + maps.splice(i, 1); + return true; + } + }, + + undo: operation(null, function() {unredoHelper(this, "undo");}), + redo: operation(null, function() {unredoHelper(this, "redo");}), + + indentLine: operation(null, function(n, dir, aggressive) { + if (typeof dir != "string") { + if (dir == null) dir = this.options.smartIndent ? "smart" : "prev"; + else dir = dir ? "add" : "subtract"; + } + if (isLine(this.view.doc, n)) indentLine(this, n, dir, aggressive); + }), + + indentSelection: operation(null, function(how) { + var sel = this.view.sel; + if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how); + var e = sel.to.line - (sel.to.ch ? 0 : 1); + for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how); + }), + + historySize: function() { + var hist = this.view.history; + return {undo: hist.done.length, redo: hist.undone.length}; + }, + + clearHistory: function() {this.view.history = makeHistory();}, + + markClean: function() { + this.view.history.dirtyCounter = 0; + this.view.history.lastOp = this.view.history.lastOrigin = null; + }, + + isClean: function () {return this.view.history.dirtyCounter == 0;}, + + getHistory: function() { + var hist = this.view.history; + function cp(arr) { + for (var i = 0, nw = [], nwelt; i < arr.length; ++i) { + var set = arr[i]; + nw.push({events: nwelt = [], fromBefore: set.fromBefore, toBefore: set.toBefore, + fromAfter: set.fromAfter, toAfter: set.toAfter}); + for (var j = 0, elt = set.events; j < elt.length; ++j) { + var old = [], cur = elt[j]; + nwelt.push({start: cur.start, added: cur.added, old: old}); + for (var k = 0; k < cur.old.length; ++k) old.push(hlText(cur.old[k])); + } + } + return nw; + } + return {done: cp(hist.done), undone: cp(hist.undone)}; + }, + + setHistory: function(histData) { + var hist = this.view.history = makeHistory(); + hist.done = histData.done; + hist.undone = histData.undone; + }, + + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(pos) { + var doc = this.view.doc; + pos = clipPos(doc, pos); + var state = getStateBefore(this, pos.line), mode = this.view.mode; + var line = getLine(doc, pos.line); + var stream = new StringStream(line.text, this.options.tabSize); + while (stream.pos < pos.ch && !stream.eol()) { + stream.start = stream.pos; + var style = mode.token(stream, state); + } + return {start: stream.start, + end: stream.pos, + string: stream.current(), + className: style || null, // Deprecated, use 'type' instead + type: style || null, + state: state}; + }, + + getStateAfter: function(line) { + var doc = this.view.doc; + line = clipLine(doc, line == null ? doc.size - 1: line); + return getStateBefore(this, line + 1); + }, + + cursorCoords: function(start, mode) { + var pos, sel = this.view.sel; + if (start == null) pos = sel.head; + else if (typeof start == "object") pos = clipPos(this.view.doc, start); + else pos = start ? sel.from : sel.to; + return cursorCoords(this, pos, mode || "page"); + }, + + charCoords: function(pos, mode) { + return charCoords(this, clipPos(this.view.doc, pos), mode || "page"); + }, + + coordsChar: function(coords) { + var off = this.display.lineSpace.getBoundingClientRect(); + return coordsChar(this, coords.left - off.left, coords.top - off.top); + }, + + defaultTextHeight: function() { return textHeight(this.display); }, + + markText: operation(null, function(from, to, options) { + return markText(this, clipPos(this.view.doc, from), clipPos(this.view.doc, to), + options, "range"); + }), + + setBookmark: operation(null, function(pos, widget) { + pos = clipPos(this.view.doc, pos); + return markText(this, pos, pos, widget ? {replacedWith: widget} : {}, "bookmark"); + }), + + findMarksAt: function(pos) { + var doc = this.view.doc; + pos = clipPos(doc, pos); + var markers = [], spans = getLine(doc, pos.line).markedSpans; + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if ((span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch)) + markers.push(span.marker); + } + return markers; + }, + + setGutterMarker: operation(null, function(line, gutterID, value) { + return changeLine(this, line, function(line) { + var markers = line.gutterMarkers || (line.gutterMarkers = {}); + markers[gutterID] = value; + if (!value && isEmpty(markers)) line.gutterMarkers = null; + return true; + }); + }), + + clearGutter: operation(null, function(gutterID) { + var i = 0, cm = this, doc = cm.view.doc; + doc.iter(0, doc.size, function(line) { + if (line.gutterMarkers && line.gutterMarkers[gutterID]) { + line.gutterMarkers[gutterID] = null; + regChange(cm, i, i + 1); + if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null; + } + ++i; + }); + }), + + addLineClass: operation(null, function(handle, where, cls) { + return changeLine(this, handle, function(line) { + var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass"; + if (!line[prop]) line[prop] = cls; + else if (new RegExp("\\b" + cls + "\\b").test(line[prop])) return false; + else line[prop] += " " + cls; + return true; + }); + }), + + removeLineClass: operation(null, function(handle, where, cls) { + return changeLine(this, handle, function(line) { + var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass"; + var cur = line[prop]; + if (!cur) return false; + else if (cls == null) line[prop] = null; + else { + var upd = cur.replace(new RegExp("^" + cls + "\\b\\s*|\\s*\\b" + cls + "\\b"), ""); + if (upd == cur) return false; + line[prop] = upd || null; + } + return true; + }); + }), + + addLineWidget: operation(null, function(handle, node, options) { + var widget = options || {}; + widget.node = node; + if (widget.noHScroll) this.display.alignWidgets = true; + changeLine(this, handle, function(line) { + (line.widgets || (line.widgets = [])).push(widget); + widget.line = line; + return true; + }); + return widget; + }), + + removeLineWidget: operation(null, function(widget) { + var ws = widget.line.widgets, no = lineNo(widget.line); + if (no == null) return; + for (var i = 0; i < ws.length; ++i) if (ws[i] == widget) ws.splice(i--, 1); + regChange(this, no, no + 1); + }), + + lineInfo: function(line) { + if (typeof line == "number") { + if (!isLine(this.view.doc, line)) return null; + var n = line; + line = getLine(this.view.doc, line); + if (!line) return null; + } else { + var n = lineNo(line); + if (n == null) return null; + } + return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, + textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, + widgets: line.widgets}; + }, + + getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};}, + + addWidget: function(pos, node, scroll, vert, horiz) { + var display = this.display; + pos = cursorCoords(this, clipPos(this.view.doc, pos)); + var top = pos.top, left = pos.left; + node.style.position = "absolute"; + display.sizer.appendChild(node); + if (vert == "over") top = pos.top; + else if (vert == "near") { + var vspace = Math.max(display.wrapper.clientHeight, this.view.doc.height), + hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); + if (pos.bottom + node.offsetHeight > vspace && pos.top > node.offsetHeight) + top = pos.top - node.offsetHeight; + if (left + node.offsetWidth > hspace) + left = hspace - node.offsetWidth; + } + node.style.top = (top + paddingTop(display)) + "px"; + node.style.left = node.style.right = ""; + if (horiz == "right") { + left = display.sizer.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") left = 0; + else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2; + node.style.left = left + "px"; + } + if (scroll) + scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight); + }, + + lineCount: function() {return this.view.doc.size;}, + + clipPos: function(pos) {return clipPos(this.view.doc, pos);}, + + getCursor: function(start) { + var sel = this.view.sel, pos; + if (start == null || start == "head") pos = sel.head; + else if (start == "anchor") pos = sel.anchor; + else if (start == "end" || start === false) pos = sel.to; + else pos = sel.from; + return copyPos(pos); + }, + + somethingSelected: function() {return !posEq(this.view.sel.from, this.view.sel.to);}, + + setCursor: operation(null, function(line, ch, extend) { + var pos = clipPos(this.view.doc, typeof line == "number" ? {line: line, ch: ch || 0} : line); + if (extend) extendSelection(this, pos); + else setSelection(this, pos, pos); + }), + + setSelection: operation(null, function(anchor, head) { + var doc = this.view.doc; + setSelection(this, clipPos(doc, anchor), clipPos(doc, head || anchor)); + }), + + extendSelection: operation(null, function(from, to) { + var doc = this.view.doc; + extendSelection(this, clipPos(doc, from), to && clipPos(doc, to)); + }), + + setExtending: function(val) {this.view.sel.extend = val;}, + + getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;}, + + getLineHandle: function(line) { + var doc = this.view.doc; + if (isLine(doc, line)) return getLine(doc, line); + }, + + getLineNumber: function(line) {return lineNo(line);}, + + setLine: operation(null, function(line, text) { + if (isLine(this.view.doc, line)) + replaceRange(this, text, {line: line, ch: 0}, {line: line, ch: getLine(this.view.doc, line).text.length}); + }), + + removeLine: operation(null, function(line) { + if (isLine(this.view.doc, line)) + replaceRange(this, "", {line: line, ch: 0}, clipPos(this.view.doc, {line: line+1, ch: 0})); + }), + + replaceRange: operation(null, function(code, from, to) { + var doc = this.view.doc; + from = clipPos(doc, from); + to = to ? clipPos(doc, to) : from; + return replaceRange(this, code, from, to); + }), + + getRange: function(from, to, lineSep) { + var doc = this.view.doc; + from = clipPos(doc, from); to = clipPos(doc, to); + var l1 = from.line, l2 = to.line; + if (l1 == l2) return getLine(doc, l1).text.slice(from.ch, to.ch); + var code = [getLine(doc, l1).text.slice(from.ch)]; + doc.iter(l1 + 1, l2, function(line) { code.push(line.text); }); + code.push(getLine(doc, l2).text.slice(0, to.ch)); + return code.join(lineSep || "\n"); + }, + + triggerOnKeyDown: operation(null, onKeyDown), + + execCommand: function(cmd) {return commands[cmd](this);}, + + // Stuff used by commands, probably not much use to outside code. + moveH: operation(null, function(dir, unit) { + var sel = this.view.sel, pos = dir < 0 ? sel.from : sel.to; + if (sel.shift || sel.extend || posEq(sel.from, sel.to)) pos = findPosH(this, dir, unit, true); + extendSelection(this, pos, pos, dir); + }), + + deleteH: operation(null, function(dir, unit) { + var sel = this.view.sel; + if (!posEq(sel.from, sel.to)) replaceRange(this, "", sel.from, sel.to, "delete"); + else replaceRange(this, "", sel.from, findPosH(this, dir, unit, false), "delete"); + this.curOp.userSelChange = true; + }), + + moveV: operation(null, function(dir, unit) { + var view = this.view, doc = view.doc, display = this.display; + var cur = view.sel.head, pos = cursorCoords(this, cur, "div"); + var x = pos.left, y; + if (view.goalColumn != null) x = view.goalColumn; + if (unit == "page") { + var pageSize = Math.min(display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); + y = pos.top + dir * pageSize; + } else if (unit == "line") { + y = dir > 0 ? pos.bottom + 3 : pos.top - 3; + } + do { + var target = coordsChar(this, x, y); + y += dir * 5; + } while (target.outside && (dir < 0 ? y > 0 : y < doc.height)); + + if (unit == "page") display.scrollbarV.scrollTop += charCoords(this, target, "div").top - pos.top; + extendSelection(this, target, target, dir); + view.goalColumn = x; + }), + + toggleOverwrite: function() { + if (this.view.overwrite = !this.view.overwrite) + this.display.cursor.className += " CodeMirror-overwrite"; + else + this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", ""); + }, + + posFromIndex: function(off) { + var lineNo = 0, ch, doc = this.view.doc; + doc.iter(0, doc.size, function(line) { + var sz = line.text.length + 1; + if (sz > off) { ch = off; return true; } + off -= sz; + ++lineNo; + }); + return clipPos(doc, {line: lineNo, ch: ch}); + }, + indexFromPos: function (coords) { + if (coords.line < 0 || coords.ch < 0) return 0; + var index = coords.ch; + this.view.doc.iter(0, coords.line, function (line) { + index += line.text.length + 1; + }); + return index; + }, + + scrollTo: function(x, y) { + if (x != null) this.display.scrollbarH.scrollLeft = this.display.scroller.scrollLeft = x; + if (y != null) this.display.scrollbarV.scrollTop = this.display.scroller.scrollTop = y; + updateDisplay(this, []); + }, + getScrollInfo: function() { + var scroller = this.display.scroller, co = scrollerCutOff; + return {left: scroller.scrollLeft, top: scroller.scrollTop, + height: scroller.scrollHeight - co, width: scroller.scrollWidth - co, + clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co}; + }, + + scrollIntoView: function(pos) { + if (typeof pos == "number") pos = {line: pos, ch: 0}; + pos = pos ? clipPos(this.view.doc, pos) : this.view.sel.head; + scrollPosIntoView(this, pos); + }, + + setSize: function(width, height) { + function interpret(val) { + return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; + } + if (width != null) this.display.wrapper.style.width = interpret(width); + if (height != null) this.display.wrapper.style.height = interpret(height); + this.refresh(); + }, + + on: function(type, f) {on(this, type, f);}, + off: function(type, f) {off(this, type, f);}, + + operation: function(f){return operation(this, f)();}, + + refresh: function() { + clearCaches(this); + if (this.display.scroller.scrollHeight > this.view.scrollTop) + this.display.scrollbarV.scrollTop = this.display.scroller.scrollTop = this.view.scrollTop; + updateDisplay(this, true); + }, + + getInputField: function(){return this.display.input;}, + getWrapperElement: function(){return this.display.wrapper;}, + getScrollerElement: function(){return this.display.scroller;}, + getGutterElement: function(){return this.display.gutters;} + }; + + // OPTION DEFAULTS + + var optionHandlers = CodeMirror.optionHandlers = {}; + + // The default configuration options. + var defaults = CodeMirror.defaults = {}; + + function option(name, deflt, handle, notOnInit) { + CodeMirror.defaults[name] = deflt; + if (handle) optionHandlers[name] = + notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle; + } + + var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}}; + + // These two are, on init, called from the constructor because they + // have to be initialized before the editor can start at all. + option("value", "", function(cm, val) {cm.setValue(val);}, true); + option("mode", null, loadMode, true); + + option("indentUnit", 2, loadMode, true); + option("indentWithTabs", false); + option("smartIndent", true); + option("tabSize", 4, function(cm) { + loadMode(cm); + clearCaches(cm); + updateDisplay(cm, true); + }, true); + option("electricChars", true); + + option("theme", "default", function(cm) { + themeChanged(cm); + guttersChanged(cm); + }, true); + option("keyMap", "default", keyMapChanged); + option("extraKeys", null); + + option("onKeyEvent", null); + option("onDragEvent", null); + + option("lineWrapping", false, wrappingChanged, true); + option("gutters", [], function(cm) { + setGuttersForLineNumbers(cm.options); + guttersChanged(cm); + }, true); + option("lineNumbers", false, function(cm) { + setGuttersForLineNumbers(cm.options); + guttersChanged(cm); + }, true); + option("firstLineNumber", 1, guttersChanged, true); + option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true); + option("showCursorWhenSelecting", false, updateSelection, true); + + option("readOnly", false, function(cm, val) { + if (val == "nocursor") {onBlur(cm); cm.display.input.blur();} + else if (!val) resetInput(cm, true); + }); + option("dragDrop", true); + + option("cursorBlinkRate", 530); + option("cursorHeight", 1); + option("workTime", 100); + option("workDelay", 100); + option("flattenSpans", true); + option("pollInterval", 100); + option("undoDepth", 40); + option("viewportMargin", 10, function(cm){cm.refresh();}, true); + + option("tabindex", null, function(cm, val) { + cm.display.input.tabIndex = val || ""; + }); + option("autofocus", null); + + // MODE DEFINITION AND QUERYING + + // Known modes, by name and by MIME + var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; + + CodeMirror.defineMode = function(name, mode) { + if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; + if (arguments.length > 2) { + mode.dependencies = []; + for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]); + } + modes[name] = mode; + }; + + CodeMirror.defineMIME = function(mime, spec) { + mimeModes[mime] = spec; + }; + + CodeMirror.resolveMode = function(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) + spec = mimeModes[spec]; + else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) + return CodeMirror.resolveMode("application/xml"); + if (typeof spec == "string") return {name: spec}; + else return spec || {name: "null"}; + }; + + CodeMirror.getMode = function(options, spec) { + var spec = CodeMirror.resolveMode(spec); + var mfactory = modes[spec.name]; + if (!mfactory) return CodeMirror.getMode(options, "text/plain"); + var modeObj = mfactory(options, spec); + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name]; + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) continue; + if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; + modeObj[prop] = exts[prop]; + } + } + modeObj.name = spec.name; + return modeObj; + }; + + CodeMirror.defineMode("null", function() { + return {token: function(stream) {stream.skipToEnd();}}; + }); + CodeMirror.defineMIME("text/plain", "null"); + + var modeExtensions = CodeMirror.modeExtensions = {}; + CodeMirror.extendMode = function(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); + for (var prop in properties) if (properties.hasOwnProperty(prop)) + exts[prop] = properties[prop]; + }; + + // EXTENSIONS + + CodeMirror.defineExtension = function(name, func) { + CodeMirror.prototype[name] = func; + }; + + CodeMirror.defineOption = option; + + var initHooks = []; + CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; + + // MODE STATE HANDLING + + // Utility functions for working with state. Exported because modes + // sometimes need to do this. + function copyState(mode, state) { + if (state === true) return state; + if (mode.copyState) return mode.copyState(state); + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) val = val.concat([]); + nstate[n] = val; + } + return nstate; + } + CodeMirror.copyState = copyState; + + function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true; + } + CodeMirror.startState = startState; + + CodeMirror.innerMode = function(mode, state) { + while (mode.innerMode) { + var info = mode.innerMode(state); + state = info.state; + mode = info.mode; + } + return info || {mode: mode, state: state}; + }; + + // STANDARD COMMANDS + + var commands = CodeMirror.commands = { + selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});}, + killLine: function(cm) { + var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); + if (!sel && cm.getLine(from.line).length == from.ch) + cm.replaceRange("", from, {line: from.line + 1, ch: 0}, "delete"); + else cm.replaceRange("", from, sel ? to : {line: from.line}, "delete"); + }, + deleteLine: function(cm) { + var l = cm.getCursor().line; + cm.replaceRange("", {line: l, ch: 0}, {line: l}, "delete"); + }, + undo: function(cm) {cm.undo();}, + redo: function(cm) {cm.redo();}, + goDocStart: function(cm) {cm.extendSelection({line: 0, ch: 0});}, + goDocEnd: function(cm) {cm.extendSelection({line: cm.lineCount() - 1});}, + goLineStart: function(cm) { + cm.extendSelection(lineStart(cm, cm.getCursor().line)); + }, + goLineStartSmart: function(cm) { + var cur = cm.getCursor(), start = lineStart(cm, cur.line); + var line = cm.getLineHandle(start.line); + var order = getOrder(line); + if (!order || order[0].level == 0) { + var firstNonWS = Math.max(0, line.text.search(/\S/)); + var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch; + cm.extendSelection({line: start.line, ch: inWS ? 0 : firstNonWS}); + } else cm.extendSelection(start); + }, + goLineEnd: function(cm) { + cm.extendSelection(lineEnd(cm, cm.getCursor().line)); + }, + goLineUp: function(cm) {cm.moveV(-1, "line");}, + goLineDown: function(cm) {cm.moveV(1, "line");}, + goPageUp: function(cm) {cm.moveV(-1, "page");}, + goPageDown: function(cm) {cm.moveV(1, "page");}, + goCharLeft: function(cm) {cm.moveH(-1, "char");}, + goCharRight: function(cm) {cm.moveH(1, "char");}, + goColumnLeft: function(cm) {cm.moveH(-1, "column");}, + goColumnRight: function(cm) {cm.moveH(1, "column");}, + goWordLeft: function(cm) {cm.moveH(-1, "word");}, + goWordRight: function(cm) {cm.moveH(1, "word");}, + delCharBefore: function(cm) {cm.deleteH(-1, "char");}, + delCharAfter: function(cm) {cm.deleteH(1, "char");}, + delWordBefore: function(cm) {cm.deleteH(-1, "word");}, + delWordAfter: function(cm) {cm.deleteH(1, "word");}, + indentAuto: function(cm) {cm.indentSelection("smart");}, + indentMore: function(cm) {cm.indentSelection("add");}, + indentLess: function(cm) {cm.indentSelection("subtract");}, + insertTab: function(cm) {cm.replaceSelection("\t", "end", "input");}, + defaultTab: function(cm) { + if (cm.somethingSelected()) cm.indentSelection("add"); + else cm.replaceSelection("\t", "end", "input"); + }, + transposeChars: function(cm) { + var cur = cm.getCursor(), line = cm.getLine(cur.line); + if (cur.ch > 0 && cur.ch < line.length - 1) + cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1), + {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1}); + }, + newlineAndIndent: function(cm) { + operation(cm, function() { + cm.replaceSelection("\n", "end", "input"); + cm.indentLine(cm.getCursor().line, null, true); + })(); + }, + toggleOverwrite: function(cm) {cm.toggleOverwrite();} + }; + + // STANDARD KEYMAPS + + var keyMap = CodeMirror.keyMap = {}; + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite" + }; + // Note that the save and find-related commands aren't defined by + // default. Unknown commands are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd", + "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delWordBefore", "Ctrl-Delete": "delWordAfter", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", + fallthrough: "basic" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft", + "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordBefore", + "Ctrl-Alt-Backspace": "delWordAfter", "Alt-Delete": "delWordAfter", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", + fallthrough: ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", + "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" + }; + + // KEYMAP DISPATCH + + function getKeyMap(val) { + if (typeof val == "string") return keyMap[val]; + else return val; + } + + function lookupKey(name, maps, handle, stop) { + function lookup(map) { + map = getKeyMap(map); + var found = map[name]; + if (found === false) { + if (stop) stop(); + return true; + } + if (found != null && handle(found)) return true; + if (map.nofallthrough) { + if (stop) stop(); + return true; + } + var fallthrough = map.fallthrough; + if (fallthrough == null) return false; + if (Object.prototype.toString.call(fallthrough) != "[object Array]") + return lookup(fallthrough); + for (var i = 0, e = fallthrough.length; i < e; ++i) { + if (lookup(fallthrough[i])) return true; + } + return false; + } + + for (var i = 0; i < maps.length; ++i) + if (lookup(maps[i])) return true; + } + function isModifierKey(event) { + var name = keyNames[e_prop(event, "keyCode")]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; + } + CodeMirror.isModifierKey = isModifierKey; + + // FROMTEXTAREA + + CodeMirror.fromTextArea = function(textarea, options) { + if (!options) options = {}; + options.value = textarea.value; + if (!options.tabindex && textarea.tabindex) + options.tabindex = textarea.tabindex; + // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + if (options.autofocus == null) { + var hasFocus = document.body; + // doc.activeElement occasionally throws on IE + try { hasFocus = document.activeElement; } catch(e) {} + options.autofocus = hasFocus == textarea || + textarea.getAttribute("autofocus") != null && hasFocus == document.body; + } + + function save() {textarea.value = cm.getValue();} + if (textarea.form) { + // Deplorable hack to make the submit method do the right thing. + on(textarea.form, "submit", save); + var form = textarea.form, realSubmit = form.submit; + try { + form.submit = function wrappedSubmit() { + save(); + form.submit = realSubmit; + form.submit(); + form.submit = wrappedSubmit; + }; + } catch(e) {} + } + + textarea.style.display = "none"; + var cm = CodeMirror(function(node) { + textarea.parentNode.insertBefore(node, textarea.nextSibling); + }, options); + cm.save = save; + cm.getTextArea = function() { return textarea; }; + cm.toTextArea = function() { + save(); + textarea.parentNode.removeChild(cm.getWrapperElement()); + textarea.style.display = ""; + if (textarea.form) { + off(textarea.form, "submit", save); + if (typeof textarea.form.submit == "function") + textarea.form.submit = realSubmit; + } + }; + return cm; + }; + + // STRING STREAM + + // Fed to the mode parsers, provides helper functions to make + // parsers more succinct. + + // The character stream used by a mode's parser. + function StringStream(string, tabSize) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + } + + StringStream.prototype = { + eol: function() {return this.pos >= this.string.length;}, + sol: function() {return this.pos == 0;}, + peek: function() {return this.string.charAt(this.pos) || undefined;}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && (match.test ? match.test(ch) : match(ch)); + if (ok) {++this.pos; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start; + }, + eatSpace: function() { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > start; + }, + skipToEnd: function() {this.pos = this.string.length;}, + skipTo: function(ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true;} + }, + backUp: function(n) {this.pos -= n;}, + column: function() {return countColumn(this.string, this.start, this.tabSize);}, + indentation: function() {return countColumn(this.string, null, this.tabSize);}, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; + if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) { + if (consume !== false) this.pos += pattern.length; + return true; + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) return null; + if (match && consume !== false) this.pos += match[0].length; + return match; + } + }, + current: function(){return this.string.slice(this.start, this.pos);} + }; + CodeMirror.StringStream = StringStream; + + // TEXTMARKERS + + function TextMarker(cm, type) { + this.lines = []; + this.type = type; + this.cm = cm; + } + + TextMarker.prototype.clear = function() { + if (this.explicitlyCleared) return; + startOperation(this.cm); + var min = null, max = null; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.to != null) max = lineNo(line); + line.markedSpans = removeMarkedSpan(line.markedSpans, span); + if (span.from != null) + min = lineNo(line); + else if (this.collapsed && !lineIsHidden(line)) + updateLineHeight(line, textHeight(this.cm.display)); + } + if (min != null) regChange(this.cm, min, max + 1); + this.lines.length = 0; + this.explicitlyCleared = true; + if (this.collapsed && this.cm.view.cantEdit) { + this.cm.view.cantEdit = false; + reCheckSelection(this.cm); + } + endOperation(this.cm); + signalLater(this.cm, this, "clear"); + }; + + TextMarker.prototype.find = function() { + var from, to; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.from != null || span.to != null) { + var found = lineNo(line); + if (span.from != null) from = {line: found, ch: span.from}; + if (span.to != null) to = {line: found, ch: span.to}; + } + } + if (this.type == "bookmark") return from; + return from && {from: from, to: to}; + }; + + function markText(cm, from, to, options, type) { + var doc = cm.view.doc; + var marker = new TextMarker(cm, type); + if (type == "range" && !posLess(from, to)) return marker; + if (options) for (var opt in options) if (options.hasOwnProperty(opt)) + marker[opt] = options[opt]; + if (marker.replacedWith) { + marker.collapsed = true; + marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget"); + } + if (marker.collapsed) sawCollapsedSpans = true; + + var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd; + doc.iter(curLine, to.line + 1, function(line) { + var span = {from: null, to: null, marker: marker}; + size += line.text.length; + if (curLine == from.line) {span.from = from.ch; size -= from.ch;} + if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;} + if (marker.collapsed) { + if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch); + if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch); + else updateLineHeight(line, 0); + } + addMarkedSpan(line, span); + if (marker.collapsed && curLine == from.line && lineIsHidden(line)) + updateLineHeight(line, 0); + ++curLine; + }); + + if (marker.readOnly) { + sawReadOnlySpans = true; + if (cm.view.history.done.length || cm.view.history.undone.length) + cm.clearHistory(); + } + if (marker.collapsed) { + if (collapsedAtStart != collapsedAtEnd) + throw new Error("Inserting collapsed marker overlapping an existing one"); + marker.size = size; + marker.atomic = true; + } + if (marker.className || marker.startStyle || marker.endStyle || marker.collapsed) + regChange(cm, from.line, to.line + 1); + if (marker.atomic) reCheckSelection(cm); + return marker; + } + + // TEXTMARKER SPANS + + function getMarkedSpanFor(spans, marker) { + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.marker == marker) return span; + } + } + function removeMarkedSpan(spans, span) { + for (var r, i = 0; i < spans.length; ++i) + if (spans[i] != span) (r || (r = [])).push(spans[i]); + return r; + } + function addMarkedSpan(line, span) { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; + span.marker.lines.push(line); + } + + function markedSpansBefore(old, startCh) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + if (startsBefore || marker.type == "bookmark" && span.from == startCh) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); + (nw || (nw = [])).push({from: span.from, + to: endsAfter ? null : span.to, + marker: marker}); + } + } + return nw; + } + + function markedSpansAfter(old, startCh, endCh) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + if (endsAfter || marker.type == "bookmark" && span.from == endCh && span.from != startCh) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); + (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh, + to: span.to == null ? null : span.to - endCh, + marker: marker}); + } + } + return nw; + } + + function updateMarkedSpans(oldFirst, oldLast, startCh, endCh, newText) { + if (!oldFirst && !oldLast) return newText; + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh); + var last = markedSpansAfter(oldLast, startCh, endCh); + + // Next, merge those two ends + var sameLine = newText.length == 1, offset = lst(newText).length + (sameLine ? startCh : 0); + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + if (!found) span.to = startCh; + else if (sameLine) span.to = found.to == null ? null : found.to + offset; + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i = 0; i < last.length; ++i) { + var span = last[i]; + if (span.to != null) span.to += offset; + if (span.from == null) { + var found = getMarkedSpanFor(first, span.marker); + if (!found) { + span.from = offset; + if (sameLine) (first || (first = [])).push(span); + } + } else { + span.from += offset; + if (sameLine) (first || (first = [])).push(span); + } + } + } + + var newMarkers = [newHL(newText[0], first)]; + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = newText.length - 2, gapMarkers; + if (gap > 0 && first) + for (var i = 0; i < first.length; ++i) + if (first[i].to == null) + (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker}); + for (var i = 0; i < gap; ++i) + newMarkers.push(newHL(newText[i+1], gapMarkers)); + newMarkers.push(newHL(lst(newText), last)); + } + return newMarkers; + } + + function removeReadOnlyRanges(doc, from, to) { + var markers = null; + doc.iter(from.line, to.line + 1, function(line) { + if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker; + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) + (markers || (markers = [])).push(mark); + } + }); + if (!markers) return null; + var parts = [{from: from, to: to}]; + for (var i = 0; i < markers.length; ++i) { + var m = markers[i].find(); + for (var j = 0; j < parts.length; ++j) { + var p = parts[j]; + if (!posLess(m.from, p.to) || posLess(m.to, p.from)) continue; + var newParts = [j, 1]; + if (posLess(p.from, m.from)) newParts.push({from: p.from, to: m.from}); + if (posLess(m.to, p.to)) newParts.push({from: m.to, to: p.to}); + parts.splice.apply(parts, newParts); + j += newParts.length - 1; + } + } + return parts; + } + + function collapsedSpanAt(line, ch) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) for (var sp, i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) continue; + if ((sp.from == null || sp.from < ch) && + (sp.to == null || sp.to > ch) && + (!found || found.width < sp.marker.width)) + found = sp.marker; + } + return found; + } + function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); } + function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); } + + function visualLine(doc, line) { + var merged; + while (merged = collapsedSpanAtStart(line)) + line = getLine(doc, merged.find().from.line); + return line; + } + + function lineIsHidden(line) { + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) for (var sp, i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) continue; + if (sp.from == null) return true; + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(line, sp)) + return true; + } + } + window.lineIsHidden = lineIsHidden; + function lineIsHiddenInner(line, span) { + if (span.to == null || span.marker.inclusiveRight && span.to == line.text.length) + return true; + for (var sp, i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i]; + if (sp.marker.collapsed && sp.from == span.to && + (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && + lineIsHiddenInner(line, sp)) return true; + } + } + + // hl stands for history-line, a data structure that can be either a + // string (line without markers) or a {text, markedSpans} object. + function hlText(val) { return typeof val == "string" ? val : val.text; } + function hlSpans(val) { + if (typeof val == "string") return null; + var spans = val.markedSpans, out = null; + for (var i = 0; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); } + else if (out) out.push(spans[i]); + } + return !out ? spans : out.length ? out : null; + } + function newHL(text, spans) { return spans ? {text: text, markedSpans: spans} : text; } + + function detachMarkedSpans(line) { + var spans = line.markedSpans; + if (!spans) return; + for (var i = 0; i < spans.length; ++i) { + var lines = spans[i].marker.lines; + var ix = indexOf(lines, line); + lines.splice(ix, 1); + } + line.markedSpans = null; + } + + function attachMarkedSpans(line, spans) { + if (!spans) return; + for (var i = 0; i < spans.length; ++i) + spans[i].marker.lines.push(line); + line.markedSpans = spans; + } + + // LINE DATA STRUCTURE + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + function makeLine(text, markedSpans, height) { + var line = {text: text, height: height}; + attachMarkedSpans(line, markedSpans); + if (lineIsHidden(line)) line.height = 0; + return line; + } + + function updateLine(cm, line, text, markedSpans) { + line.text = text; + line.stateAfter = line.styles = null; + if (line.order != null) line.order = null; + detachMarkedSpans(line); + attachMarkedSpans(line, markedSpans); + if (lineIsHidden(line)) line.height = 0; + else if (!line.height) line.height = textHeight(cm.display); + signalLater(cm, line, "change"); + } + + function cleanUpLine(line) { + line.parent = null; + detachMarkedSpans(line); + } + + // Run the given mode's parser over a line, update the styles + // array, which contains alternating fragments of text and CSS + // classes. + function highlightLine(cm, line, state) { + var mode = cm.view.mode, flattenSpans = cm.options.flattenSpans; + var changed = !line.styles, pos = 0, curText = "", curStyle = null; + var stream = new StringStream(line.text, cm.options.tabSize), st = line.styles || (line.styles = []); + if (line.text == "" && mode.blankLine) mode.blankLine(state); + while (!stream.eol()) { + var style = mode.token(stream, state), substr = stream.current(); + stream.start = stream.pos; + if (!flattenSpans || curStyle != style) { + if (curText) { + changed = changed || pos >= st.length || curText != st[pos] || curStyle != st[pos+1]; + st[pos++] = curText; st[pos++] = curStyle; + } + curText = substr; curStyle = style; + } else curText = curText + substr; + // Give up when line is ridiculously long + if (stream.pos > 5000) break; + } + if (curText) { + changed = changed || pos >= st.length || curText != st[pos] || curStyle != st[pos+1]; + st[pos++] = curText; st[pos++] = curStyle; + } + if (stream.pos > 5000) { st[pos++] = line.text.slice(stream.pos); st[pos++] = null; } + if (pos != st.length) { st.length = pos; changed = true; } + return changed; + } + + // Lightweight form of highlight -- proceed over this line and + // update state, but don't save a style array. + function processLine(cm, line, state) { + var mode = cm.view.mode; + var stream = new StringStream(line.text, cm.options.tabSize); + if (line.text == "" && mode.blankLine) mode.blankLine(state); + while (!stream.eol() && stream.pos <= 5000) { + mode.token(stream, state); + stream.start = stream.pos; + } + } + + var styleToClassCache = {}; + function styleToClass(style) { + if (!style) return null; + return styleToClassCache[style] || + (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-")); + } + + function lineContent(cm, realLine, measure) { + var merged, line = realLine, lineBefore, sawBefore, simple = true; + while (merged = collapsedSpanAtStart(line)) { + simple = false; + line = getLine(cm.view.doc, merged.find().from.line); + if (!lineBefore) lineBefore = line; + } + + var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure, + measure: null, addedOne: false, cm: cm}; + if (line.textClass) builder.pre.className = line.textClass; + + do { + if (!line.styles) + highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line))); + builder.measure = line == realLine && measure; + builder.pos = 0; + builder.addToken = builder.measure ? buildTokenMeasure : buildToken; + if (measure && sawBefore && line != realLine && !builder.addedOne) { + measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure)); + builder.addedOne = true; + } + var next = insertLineContent(line, builder); + sawBefore = line == lineBefore; + if (next) { + line = getLine(cm.view.doc, next.to.line); + simple = false; + } + } while (next); + + if (measure && !builder.addedOne) + measure[0] = builder.pre.appendChild(simple ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure)); + if (!builder.pre.firstChild && !lineIsHidden(realLine)) + builder.pre.appendChild(document.createTextNode("\u00a0")); + + return builder.pre; + } + + var tokenSpecialChars = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g; + function buildToken(builder, text, style, startStyle, endStyle) { + if (!text) return; + if (!tokenSpecialChars.test(text)) { + builder.col += text.length; + var content = document.createTextNode(text); + } else { + var content = document.createDocumentFragment(), pos = 0; + while (true) { + tokenSpecialChars.lastIndex = pos; + var m = tokenSpecialChars.exec(text); + var skipped = m ? m.index - pos : text.length - pos; + if (skipped) { + content.appendChild(document.createTextNode(text.slice(pos, pos + skipped))); + builder.col += skipped; + } + if (!m) break; + pos += skipped + 1; + if (m[0] == "\t") { + var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; + content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); + builder.col += tabWidth; + } else { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + m[0].charCodeAt(0).toString(16); + content.appendChild(token); + builder.col += 1; + } + } + } + if (style || startStyle || endStyle || builder.measure) { + var fullStyle = style || ""; + if (startStyle) fullStyle += startStyle; + if (endStyle) fullStyle += endStyle; + return builder.pre.appendChild(elt("span", [content], fullStyle)); + } + builder.pre.appendChild(content); + } + + function buildTokenMeasure(builder, text, style, startStyle, endStyle) { + for (var i = 0; i < text.length; ++i) { + if (i && i < text.length - 1 && + builder.cm.options.lineWrapping && + spanAffectsWrapping.test(text.slice(i - 1, i + 1))) + builder.pre.appendChild(elt("wbr")); + builder.measure[builder.pos++] = + buildToken(builder, text.charAt(i), style, + i == 0 && startStyle, i == text.length - 1 && endStyle); + } + if (text.length) builder.addedOne = true; + } + + function buildCollapsedSpan(builder, size, widget) { + if (widget) { + if (!builder.display) widget = widget.cloneNode(true); + builder.pre.appendChild(widget); + if (builder.measure && size) { + builder.measure[builder.pos] = widget; + builder.addedOne = true; + } + } + builder.pos += size; + } + + // Outputs a number of spans to make up a line, taking highlighting + // and marked text into account. + function insertLineContent(line, builder) { + var st = line.styles, spans = line.markedSpans; + if (!spans) { + for (var i = 0; i < st.length; i+=2) + builder.addToken(builder, st[i], styleToClass(st[i+1])); + return; + } + + var allText = line.text, len = allText.length; + var pos = 0, i = 0, text = "", style; + var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed; + for (;;) { + if (nextChange == pos) { // Update current marker set + spanStyle = spanEndStyle = spanStartStyle = ""; + collapsed = null; nextChange = Infinity; + var foundBookmark = null; + for (var j = 0; j < spans.length; ++j) { + var sp = spans[j], m = sp.marker; + if (sp.from <= pos && (sp.to == null || sp.to > pos)) { + if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; } + if (m.className) spanStyle += " " + m.className; + if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; + if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle; + if (m.collapsed && (!collapsed || collapsed.marker.width < m.width)) + collapsed = sp; + } else if (sp.from > pos && nextChange > sp.from) { + nextChange = sp.from; + } + if (m.type == "bookmark" && sp.from == pos && m.replacedWith) + foundBookmark = m.replacedWith; + } + if (collapsed && (collapsed.from || 0) == pos) { + buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos, + collapsed.from != null && collapsed.marker.replacedWith); + if (collapsed.to == null) return collapsed.marker.find(); + } + if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark); + } + if (pos >= len) break; + + var upto = Math.min(len, nextChange); + while (true) { + if (text) { + var end = pos + text.length; + if (!collapsed) { + var tokenText = end > upto ? text.slice(0, upto - pos) : text; + builder.addToken(builder, tokenText, style + spanStyle, + spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : ""); + } + if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} + pos = end; + spanStartStyle = ""; + } + text = st[i++]; style = styleToClass(st[i++]); + } + } + } + + // DOCUMENT DATA STRUCTURE + + function LeafChunk(lines) { + this.lines = lines; + this.parent = null; + for (var i = 0, e = lines.length, height = 0; i < e; ++i) { + lines[i].parent = this; + height += lines[i].height; + } + this.height = height; + } + + LeafChunk.prototype = { + chunkSize: function() { return this.lines.length; }, + remove: function(at, n, cm) { + for (var i = at, e = at + n; i < e; ++i) { + var line = this.lines[i]; + this.height -= line.height; + cleanUpLine(line); + signalLater(cm, line, "delete"); + } + this.lines.splice(at, n); + }, + collapse: function(lines) { + lines.splice.apply(lines, [lines.length, 0].concat(this.lines)); + }, + insertHeight: function(at, lines, height) { + this.height += height; + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); + for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this; + }, + iterN: function(at, n, op) { + for (var e = at + n; at < e; ++at) + if (op(this.lines[at])) return true; + } + }; + + function BranchChunk(children) { + this.children = children; + var size = 0, height = 0; + for (var i = 0, e = children.length; i < e; ++i) { + var ch = children[i]; + size += ch.chunkSize(); height += ch.height; + ch.parent = this; + } + this.size = size; + this.height = height; + this.parent = null; + } + + BranchChunk.prototype = { + chunkSize: function() { return this.size; }, + remove: function(at, n, callbacks) { + this.size -= n; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height; + child.remove(at, rm, callbacks); + this.height -= oldHeight - child.height; + if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } + if ((n -= rm) == 0) break; + at = 0; + } else at -= sz; + } + if (this.size - n < 25) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + this.children[0].parent = this; + } + }, + collapse: function(lines) { + for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines); + }, + insert: function(at, lines) { + var height = 0; + for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height; + this.insertHeight(at, lines, height); + }, + insertHeight: function(at, lines, height) { + this.size += lines.length; + this.height += height; + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at <= sz) { + child.insertHeight(at, lines, height); + if (child.lines && child.lines.length > 50) { + while (child.lines.length > 50) { + var spilled = child.lines.splice(child.lines.length - 25, 25); + var newleaf = new LeafChunk(spilled); + child.height -= newleaf.height; + this.children.splice(i + 1, 0, newleaf); + newleaf.parent = this; + } + this.maybeSpill(); + } + break; + } + at -= sz; + } + }, + maybeSpill: function() { + if (this.children.length <= 10) return; + var me = this; + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + sibling.parent = me.parent; + } while (me.children.length > 10); + me.parent.maybeSpill(); + }, + iter: function(from, to, op) { this.iterN(from, to - from, op); }, + iterN: function(at, n, op) { + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var used = Math.min(n, sz - at); + if (child.iterN(at, used, op)) return true; + if ((n -= used) == 0) break; + at = 0; + } else at -= sz; + } + } + }; + + // LINE UTILITIES + + function getLine(chunk, n) { + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break; } + n -= sz; + } + } + return chunk.lines[n]; + } + + function updateLineHeight(line, height) { + var diff = height - line.height; + for (var n = line; n; n = n.parent) n.height += diff; + } + + function lineNo(line) { + if (line.parent == null) return null; + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) break; + no += chunk.children[i].chunkSize(); + } + } + return no; + } + + function lineAtHeight(chunk, h) { + var n = 0; + outer: do { + for (var i = 0, e = chunk.children.length; i < e; ++i) { + var child = chunk.children[i], ch = child.height; + if (h < ch) { chunk = child; continue outer; } + h -= ch; + n += child.chunkSize(); + } + return n; + } while (!chunk.lines); + for (var i = 0, e = chunk.lines.length; i < e; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) break; + h -= lh; + } + return n + i; + } + + function heightAtLine(cm, lineObj) { + lineObj = visualLine(cm.view.doc, lineObj); + + var h = 0, chunk = lineObj.parent; + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i]; + if (line == lineObj) break; + else h += line.height; + } + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i = 0; i < p.children.length; ++i) { + var cur = p.children[i]; + if (cur == chunk) break; + else h += cur.height; + } + } + return h; + } + + function getOrder(line) { + var order = line.order; + if (order == null) order = line.order = bidiOrdering(line.text); + return order; + } + + // HISTORY + + function makeHistory() { + return { + // Arrays of history events. Doing something adds an event to + // done and clears undo. Undoing moves events from done to + // undone, redoing moves them in the other direction. + done: [], undone: [], + // Used to track when changes can be merged into a single undo + // event + lastTime: 0, lastOp: null, lastOrigin: null, + // Used by the isClean() method + dirtyCounter: 0 + }; + } + + function addChange(cm, start, added, old, origin, fromBefore, toBefore, fromAfter, toAfter) { + var history = cm.view.history; + history.undone.length = 0; + var time = +new Date, cur = lst(history.done); + + if (cur && + (history.lastOp == cm.curOp.id || + history.lastOrigin == origin && (origin == "input" || origin == "delete") && + history.lastTime > time - 600)) { + // Merge this change into the last event + var last = lst(cur.events); + if (last.start > start + old.length || last.start + last.added < start) { + // Doesn't intersect with last sub-event, add new sub-event + cur.events.push({start: start, added: added, old: old}); + } else { + // Patch up the last sub-event + var startBefore = Math.max(0, last.start - start), + endAfter = Math.max(0, (start + old.length) - (last.start + last.added)); + for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]); + for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]); + if (startBefore) last.start = start; + last.added += added - (old.length - startBefore - endAfter); + } + cur.fromAfter = fromAfter; cur.toAfter = toAfter; + } else { + // Can not be merged, start a new event. + cur = {events: [{start: start, added: added, old: old}], + fromBefore: fromBefore, toBefore: toBefore, fromAfter: fromAfter, toAfter: toAfter}; + history.done.push(cur); + while (history.done.length > cm.options.undoDepth) + history.done.shift(); + if (history.dirtyCounter < 0) + // The user has made a change after undoing past the last clean state. + // We can never get back to a clean state now until markClean() is called. + history.dirtyCounter = NaN; + else + history.dirtyCounter++; + } + history.lastTime = time; + history.lastOp = cm.curOp.id; + history.lastOrigin = origin; + } + + // EVENT OPERATORS + + function stopMethod() {e_stop(this);} + // Ensure an event has a stop method. + function addStop(event) { + if (!event.stop) event.stop = stopMethod; + return event; + } + + function e_preventDefault(e) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + function e_stopPropagation(e) { + if (e.stopPropagation) e.stopPropagation(); + else e.cancelBubble = true; + } + function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} + CodeMirror.e_stop = e_stop; + CodeMirror.e_preventDefault = e_preventDefault; + CodeMirror.e_stopPropagation = e_stopPropagation; + + function e_target(e) {return e.target || e.srcElement;} + function e_button(e) { + var b = e.which; + if (b == null) { + if (e.button & 1) b = 1; + else if (e.button & 2) b = 3; + else if (e.button & 4) b = 2; + } + if (mac && e.ctrlKey && b == 1) b = 3; + return b; + } + + // Allow 3rd-party code to override event properties by adding an override + // object to an event object. + function e_prop(e, prop) { + var overridden = e.override && e.override.hasOwnProperty(prop); + return overridden ? e.override[prop] : e[prop]; + } + + // EVENT HANDLING + + function on(emitter, type, f) { + if (emitter.addEventListener) + emitter.addEventListener(type, f, false); + else if (emitter.attachEvent) + emitter.attachEvent("on" + type, f); + else { + var map = emitter._handlers || (emitter._handlers = {}); + var arr = map[type] || (map[type] = []); + arr.push(f); + } + } + + function off(emitter, type, f) { + if (emitter.removeEventListener) + emitter.removeEventListener(type, f, false); + else if (emitter.detachEvent) + emitter.detachEvent("on" + type, f); + else { + var arr = emitter._handlers && emitter._handlers[type]; + if (!arr) return; + for (var i = 0; i < arr.length; ++i) + if (arr[i] == f) { arr.splice(i, 1); break; } + } + } + + function signal(emitter, type /*, values...*/) { + var arr = emitter._handlers && emitter._handlers[type]; + if (!arr) return; + var args = Array.prototype.slice.call(arguments, 2); + for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args); + } + + function signalLater(cm, emitter, type /*, values...*/) { + var arr = emitter._handlers && emitter._handlers[type]; + if (!arr) return; + var args = Array.prototype.slice.call(arguments, 3), flist = cm.curOp && cm.curOp.delayedCallbacks; + function bnd(f) {return function(){f.apply(null, args);};}; + for (var i = 0; i < arr.length; ++i) + if (flist) flist.push(bnd(arr[i])); + else arr[i].apply(null, args); + } + + function hasHandler(emitter, type) { + var arr = emitter._handlers && emitter._handlers[type]; + return arr && arr.length > 0; + } + + CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal; + + // MISC UTILITIES + + // Number of pixels added to scroller and sizer to hide scrollbar + var scrollerCutOff = 30; + + // Returned or thrown by various protocols to signal 'I'm not + // handling this'. + var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; + + function Delayed() {this.id = null;} + Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}}; + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + function countColumn(string, end, tabSize) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) end = string.length; + } + for (var i = 0, n = 0; i < end; ++i) { + if (string.charAt(i) == "\t") n += tabSize - (n % tabSize); + else ++n; + } + return n; + } + CodeMirror.countColumn = countColumn; + + var spaceStrs = [""]; + function spaceStr(n) { + while (spaceStrs.length <= n) + spaceStrs.push(lst(spaceStrs) + " "); + return spaceStrs[n]; + } + + function lst(arr) { return arr[arr.length-1]; } + + function selectInput(node) { + if (ios) { // Mobile Safari apparently has a bug where select() is broken. + node.selectionStart = 0; + node.selectionEnd = node.value.length; + } else node.select(); + } + + function indexOf(collection, elt) { + if (collection.indexOf) return collection.indexOf(elt); + for (var i = 0, e = collection.length; i < e; ++i) + if (collection[i] == elt) return i; + return -1; + } + + function emptyArray(size) { + for (var a = [], i = 0; i < size; ++i) a.push(undefined); + return a; + } + + function bind(f) { + var args = Array.prototype.slice.call(arguments, 1); + return function(){return f.apply(null, args);}; + } + + var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/; + function isWordChar(ch) { + return /\w/.test(ch) || ch > "\x80" && + (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); + } + + function isEmpty(obj) { + var c = 0; + for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) ++c; + return !c; + } + + var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F]/; + + // DOM UTILITIES + + function elt(tag, content, className, style) { + var e = document.createElement(tag); + if (className) e.className = className; + if (style) e.style.cssText = style; + if (typeof content == "string") setTextContent(e, content); + else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); + return e; + } + + function removeChildren(e) { + e.innerHTML = ""; + return e; + } + + function removeChildrenAndAdd(parent, e) { + return removeChildren(parent).appendChild(e); + } + + function setTextContent(e, str) { + if (ie_lt9) { + e.innerHTML = ""; + e.appendChild(document.createTextNode(str)); + } else e.textContent = str; + } + + // FEATURE DETECTION + + // Detect drag-and-drop + var dragAndDrop = function() { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie_lt9) return false; + var div = elt('div'); + return "draggable" in div || "dragDrop" in div; + }(); + + // For a reason I have yet to figure out, some browsers disallow + // word wrapping between certain characters *only* if a new inline + // element is started between them. This makes it hard to reliably + // measure the position of things, since that requires inserting an + // extra span. This terribly fragile set of regexps matches the + // character combinations that suffer from this phenomenon on the + // various browsers. + var spanAffectsWrapping = /^$/; // Won't match any two-character string + if (gecko) spanAffectsWrapping = /$'/; + else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/; + else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/; + + var knownScrollbarWidth; + function scrollbarWidth(measure) { + if (knownScrollbarWidth != null) return knownScrollbarWidth; + var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll"); + removeChildrenAndAdd(measure, test); + if (test.offsetWidth) + knownScrollbarWidth = test.offsetHeight - test.clientHeight; + return knownScrollbarWidth || 0; + } + + var zwspSupported; + function zeroWidthElement(measure) { + if (zwspSupported == null) { + var test = elt("span", "\u200b"); + removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); + if (measure.firstChild.offsetHeight != 0) + zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8; + } + if (zwspSupported) return elt("span", "\u200b"); + else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { + var pos = 0, result = [], l = string.length; + while (pos <= l) { + var nl = string.indexOf("\n", pos); + if (nl == -1) nl = string.length; + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); + var rt = line.indexOf("\r"); + if (rt != -1) { + result.push(line.slice(0, rt)); + pos += rt + 1; + } else { + result.push(line); + pos = nl + 1; + } + } + return result; + } : function(string){return string.split(/\r\n?|\n/);}; + CodeMirror.splitLines = splitLines; + + var hasSelection = window.getSelection ? function(te) { + try { return te.selectionStart != te.selectionEnd; } + catch(e) { return false; } + } : function(te) { + try {var range = te.ownerDocument.selection.createRange();} + catch(e) {} + if (!range || range.parentElement() != te) return false; + return range.compareEndPoints("StartToEnd", range) != 0; + }; + + var hasCopyEvent = (function() { + var e = elt("div"); + if ("oncopy" in e) return true; + e.setAttribute("oncopy", "return;"); + return typeof e.oncopy == 'function'; + })(); + + // KEY NAMING + + var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete", + 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home", + 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"}; + CodeMirror.keyNames = keyNames; + (function() { + // Number keys + for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i); + // Alphabetic keys + for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); + // Function keys + for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; + })(); + + // BIDI HELPERS + + function iterateBidiSections(order, from, to, f) { + if (!order) return f(from, to, "ltr"); + for (var i = 0; i < order.length; ++i) { + var part = order[i]; + if (part.from < to && part.to > from) + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr"); + } + } + + function bidiLeft(part) { return part.level % 2 ? part.to : part.from; } + function bidiRight(part) { return part.level % 2 ? part.from : part.to; } + + function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; } + function lineRight(line) { + var order = getOrder(line); + if (!order) return line.text.length; + return bidiRight(lst(order)); + } + + function lineStart(cm, lineN) { + var line = getLine(cm.view.doc, lineN); + var visual = visualLine(cm.view.doc, line); + if (visual != line) lineN = lineNo(visual); + var order = getOrder(visual); + var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual); + return {line: lineN, ch: ch}; + } + function lineEnd(cm, lineNo) { + var merged, line; + while (merged = collapsedSpanAtEnd(line = getLine(cm.view.doc, lineNo))) + lineNo = merged.find().to.line; + var order = getOrder(line); + var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line); + return {line: lineNo, ch: ch}; + } + + // This is somewhat involved. It is needed in order to move + // 'visually' through bi-directional text -- i.e., pressing left + // should make the cursor go left, even when in RTL text. The + // tricky part is the 'jumps', where RTL and LTR text touch each + // other. This often requires the cursor offset to move more than + // one unit, in order to visually move one unit. + function moveVisually(line, start, dir, byUnit) { + var bidi = getOrder(line); + if (!bidi) return moveLogically(line, start, dir, byUnit); + var moveOneUnit = byUnit ? function(pos, dir) { + do pos += dir; + while (pos > 0 && isExtendingChar.test(line.text.charAt(pos))); + return pos; + } : function(pos, dir) { return pos + dir; }; + var linedir = bidi[0].level; + for (var i = 0; i < bidi.length; ++i) { + var part = bidi[i], sticky = part.level % 2 == linedir; + if ((part.from < start && part.to > start) || + (sticky && (part.from == start || part.to == start))) break; + } + var target = moveOneUnit(start, part.level % 2 ? -dir : dir); + + while (target != null) { + if (part.level % 2 == linedir) { + if (target < part.from || target > part.to) { + part = bidi[i += dir]; + target = part && (dir > 0 == part.level % 2 ? moveOneUnit(part.to, -1) : moveOneUnit(part.from, 1)); + } else break; + } else { + if (target == bidiLeft(part)) { + part = bidi[--i]; + target = part && bidiRight(part); + } else if (target == bidiRight(part)) { + part = bidi[++i]; + target = part && bidiLeft(part); + } else break; + } + } + + return target < 0 || target > line.text.length ? null : target; + } + + function moveLogically(line, start, dir, byUnit) { + var target = start + dir; + if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir; + return target < 0 || target > line.text.length ? null : target; + } + + // Bidirectional ordering algorithm + // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm + // that this (partially) implements. + + // One-char codes used for character types: + // L (L): Left-to-Right + // R (R): Right-to-Left + // r (AL): Right-to-Left Arabic + // 1 (EN): European Number + // + (ES): European Number Separator + // % (ET): European Number Terminator + // n (AN): Arabic Number + // , (CS): Common Number Separator + // m (NSM): Non-Spacing Mark + // b (BN): Boundary Neutral + // s (B): Paragraph Separator + // t (S): Segment Separator + // w (WS): Whitespace + // N (ON): Other Neutrals + + // Returns null if characters are ordered as they appear + // (left-to-right), or an array of sections ({from, to, level} + // objects) in the order in which they occur visually. + var bidiOrdering = (function() { + // Character types for codepoints 0 to 0xff + var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL"; + // Character types for codepoints 0x600 to 0x6ff + var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr"; + function charType(code) { + if (code <= 0xff) return lowTypes.charAt(code); + else if (0x590 <= code && code <= 0x5f4) return "R"; + else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600); + else if (0x700 <= code && code <= 0x8ac) return "r"; + else return "L"; + } + + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; + var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; + + return function charOrdering(str) { + if (!bidiRE.test(str)) return false; + var len = str.length, types = [], startType = null; + for (var i = 0, type; i < len; ++i) { + types.push(type = charType(str.charCodeAt(i))); + if (startType == null) { + if (type == "L") startType = "L"; + else if (type == "R" || type == "r") startType = "R"; + } + } + if (startType == null) startType = "L"; + + // W1. Examine each non-spacing mark (NSM) in the level run, and + // change the type of the NSM to the type of the previous + // character. If the NSM is at the start of the level run, it will + // get the type of sor. + for (var i = 0, prev = startType; i < len; ++i) { + var type = types[i]; + if (type == "m") types[i] = prev; + else prev = type; + } + + // W2. Search backwards from each instance of a European number + // until the first strong type (R, L, AL, or sor) is found. If an + // AL is found, change the type of the European number to Arabic + // number. + // W3. Change all ALs to R. + for (var i = 0, cur = startType; i < len; ++i) { + var type = types[i]; + if (type == "1" && cur == "r") types[i] = "n"; + else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; } + } + + // W4. A single European separator between two European numbers + // changes to a European number. A single common separator between + // two numbers of the same type changes to that type. + for (var i = 1, prev = types[0]; i < len - 1; ++i) { + var type = types[i]; + if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1"; + else if (type == "," && prev == types[i+1] && + (prev == "1" || prev == "n")) types[i] = prev; + prev = type; + } + + // W5. A sequence of European terminators adjacent to European + // numbers changes to all European numbers. + // W6. Otherwise, separators and terminators change to Other + // Neutral. + for (var i = 0; i < len; ++i) { + var type = types[i]; + if (type == ",") types[i] = "N"; + else if (type == "%") { + for (var end = i + 1; end < len && types[end] == "%"; ++end) {} + var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N"; + for (var j = i; j < end; ++j) types[j] = replace; + i = end - 1; + } + } + + // W7. Search backwards from each instance of a European number + // until the first strong type (R, L, or sor) is found. If an L is + // found, then change the type of the European number to L. + for (var i = 0, cur = startType; i < len; ++i) { + var type = types[i]; + if (cur == "L" && type == "1") types[i] = "L"; + else if (isStrong.test(type)) cur = type; + } + + // N1. A sequence of neutrals takes the direction of the + // surrounding strong text if the text on both sides has the same + // direction. European and Arabic numbers act as if they were R in + // terms of their influence on neutrals. Start-of-level-run (sor) + // and end-of-level-run (eor) are used at level run boundaries. + // N2. Any remaining neutrals take the embedding direction. + for (var i = 0; i < len; ++i) { + if (isNeutral.test(types[i])) { + for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} + var before = (i ? types[i-1] : startType) == "L"; + var after = (end < len - 1 ? types[end] : startType) == "L"; + var replace = before || after ? "L" : "R"; + for (var j = i; j < end; ++j) types[j] = replace; + i = end - 1; + } + } + + // Here we depart from the documented algorithm, in order to avoid + // building up an actual levels array. Since there are only three + // levels (0, 1, 2) in an implementation that doesn't take + // explicit embedding into account, we can build up the order on + // the fly, without following the level-based algorithm. + var order = [], m; + for (var i = 0; i < len;) { + if (countsAsLeft.test(types[i])) { + var start = i; + for (++i; i < len && countsAsLeft.test(types[i]); ++i) {} + order.push({from: start, to: i, level: 0}); + } else { + var pos = i, at = order.length; + for (++i; i < len && types[i] != "L"; ++i) {} + for (var j = pos; j < i;) { + if (countsAsNum.test(types[j])) { + if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1}); + var nstart = j; + for (++j; j < i && countsAsNum.test(types[j]); ++j) {} + order.splice(at, 0, {from: nstart, to: j, level: 2}); + pos = j; + } else ++j; + } + if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1}); + } + } + if (order[0].level == 1 && (m = str.match(/^\s+/))) { + order[0].from = m[0].length; + order.unshift({from: 0, to: m[0].length, level: 0}); + } + if (lst(order).level == 1 && (m = str.match(/\s+$/))) { + lst(order).to -= m[0].length; + order.push({from: len - m[0].length, to: len, level: 0}); + } + if (order[0].level != lst(order).level) + order.push({from: len, to: len, level: order[0].level}); + + return order; + }; + })(); + + // THE END + + CodeMirror.version = "3.0"; + + return CodeMirror; +})(); diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/clike.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/clike.js Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,300 @@ +CodeMirror.defineMode("clike", function(config, parserConfig) { + var indentUnit = config.indentUnit, + statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, + keywords = parserConfig.keywords || {}, + builtin = parserConfig.builtin || {}, + blockKeywords = parserConfig.blockKeywords || {}, + atoms = parserConfig.atoms || {}, + hooks = parserConfig.hooks || {}, + multiLineStrings = parserConfig.multiLineStrings; + var isOperatorChar = /[+\-*&%=<>!?|\/]/; + + var curPunc; + + function tokenBase(stream, state) { + var ch = stream.next(); + if (hooks[ch]) { + var result = hooks[ch](stream, state); + if (result !== false) return result; + } + if (ch == '"' || ch == "'") { + state.tokenize = tokenString(ch); + return state.tokenize(stream, state); + } + if (/[\[\]{}\(\),;\:\.]/.test(ch)) { + curPunc = ch; + return null; + } + if (/\d/.test(ch)) { + stream.eatWhile(/[\w\.]/); + return "number"; + } + if (ch == "/") { + if (stream.eat("*")) { + state.tokenize = tokenComment; + return tokenComment(stream, state); + } + if (stream.eat("/")) { + stream.skipToEnd(); + return "comment"; + } + } + if (isOperatorChar.test(ch)) { + stream.eatWhile(isOperatorChar); + return "operator"; + } + stream.eatWhile(/[\w\$_]/); + var cur = stream.current(); + if (keywords.propertyIsEnumerable(cur)) { + if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; + return "keyword"; + } + if (builtin.propertyIsEnumerable(cur)) { + if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; + return "builtin"; + } + if (atoms.propertyIsEnumerable(cur)) return "atom"; + return "variable"; + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, next, end = false; + while ((next = stream.next()) != null) { + if (next == quote && !escaped) {end = true; break;} + escaped = !escaped && next == "\\"; + } + if (end || !(escaped || multiLineStrings)) + state.tokenize = null; + return "string"; + }; + } + + function tokenComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (ch == "/" && maybeEnd) { + state.tokenize = null; + break; + } + maybeEnd = (ch == "*"); + } + return "comment"; + } + + function Context(indented, column, type, align, prev) { + this.indented = indented; + this.column = column; + this.type = type; + this.align = align; + this.prev = prev; + } + function pushContext(state, col, type) { + var indent = state.indented; + if (state.context && state.context.type == "statement") + indent = state.context.indented; + return state.context = new Context(indent, col, type, null, state.context); + } + function popContext(state) { + var t = state.context.type; + if (t == ")" || t == "]" || t == "}") + state.indented = state.context.indented; + return state.context = state.context.prev; + } + + // Interface + + return { + startState: function(basecolumn) { + return { + tokenize: null, + context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), + indented: 0, + startOfLine: true + }; + }, + + token: function(stream, state) { + var ctx = state.context; + if (stream.sol()) { + if (ctx.align == null) ctx.align = false; + state.indented = stream.indentation(); + state.startOfLine = true; + } + if (stream.eatSpace()) return null; + curPunc = null; + var style = (state.tokenize || tokenBase)(stream, state); + if (style == "comment" || style == "meta") return style; + if (ctx.align == null) ctx.align = true; + + if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state); + else if (curPunc == "{") pushContext(state, stream.column(), "}"); + else if (curPunc == "[") pushContext(state, stream.column(), "]"); + else if (curPunc == "(") pushContext(state, stream.column(), ")"); + else if (curPunc == "}") { + while (ctx.type == "statement") ctx = popContext(state); + if (ctx.type == "}") ctx = popContext(state); + while (ctx.type == "statement") ctx = popContext(state); + } + else if (curPunc == ctx.type) popContext(state); + else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement")) + pushContext(state, stream.column(), "statement"); + state.startOfLine = false; + return style; + }, + + indent: function(state, textAfter) { + if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass; + var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); + if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; + var closing = firstChar == ctx.type; + if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); + else if (ctx.align) return ctx.column + (closing ? 0 : 1); + else return ctx.indented + (closing ? 0 : indentUnit); + }, + + electricChars: "{}" + }; +}); + +(function() { + function words(str) { + var obj = {}, words = str.split(" "); + for (var i = 0; i < words.length; ++i) obj[words[i]] = true; + return obj; + } + var cKeywords = "auto if break int case long char register continue return default short do sizeof " + + "double static else struct entry switch extern typedef float union for unsigned " + + "goto while enum void const signed volatile"; + + function cppHook(stream, state) { + if (!state.startOfLine) return false; + for (;;) { + if (stream.skipTo("\\")) { + stream.next(); + if (stream.eol()) { + state.tokenize = cppHook; + break; + } + } else { + stream.skipToEnd(); + state.tokenize = null; + break; + } + } + return "meta"; + } + + // C#-style strings where "" escapes a quote. + function tokenAtString(stream, state) { + var next; + while ((next = stream.next()) != null) { + if (next == '"' && !stream.eat('"')) { + state.tokenize = null; + break; + } + } + return "string"; + } + + function mimes(ms, mode) { + for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode); + } + + mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], { + name: "clike", + keywords: words(cKeywords), + blockKeywords: words("case do else for if switch while struct"), + atoms: words("null"), + hooks: {"#": cppHook} + }); + mimes(["text/x-c++src", "text/x-c++hdr"], { + name: "clike", + keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " + + "static_cast typeid catch operator template typename class friend private " + + "this using const_cast inline public throw virtual delete mutable protected " + + "wchar_t"), + blockKeywords: words("catch class do else finally for if struct switch try while"), + atoms: words("true false null"), + hooks: {"#": cppHook} + }); + CodeMirror.defineMIME("text/x-java", { + name: "clike", + keywords: words("abstract assert boolean break byte case catch char class const continue default " + + "do double else enum extends final finally float for goto if implements import " + + "instanceof int interface long native new package private protected public " + + "return short static strictfp super switch synchronized this throw throws transient " + + "try void volatile while"), + blockKeywords: words("catch class do else finally for if switch try while"), + atoms: words("true false null"), + hooks: { + "@": function(stream) { + stream.eatWhile(/[\w\$_]/); + return "meta"; + } + } + }); + CodeMirror.defineMIME("text/x-csharp", { + name: "clike", + keywords: words("abstract as base break case catch checked class const continue" + + " default delegate do else enum event explicit extern finally fixed for" + + " foreach goto if implicit in interface internal is lock namespace new" + + " operator out override params private protected public readonly ref return sealed" + + " sizeof stackalloc static struct switch this throw try typeof unchecked" + + " unsafe using virtual void volatile while add alias ascending descending dynamic from get" + + " global group into join let orderby partial remove select set value var yield"), + blockKeywords: words("catch class do else finally for foreach if struct switch try while"), + builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" + + " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" + + " UInt64 bool byte char decimal double short int long object" + + " sbyte float string ushort uint ulong"), + atoms: words("true false null"), + hooks: { + "@": function(stream, state) { + if (stream.eat('"')) { + state.tokenize = tokenAtString; + return tokenAtString(stream, state); + } + stream.eatWhile(/[\w\$_]/); + return "meta"; + } + } + }); + CodeMirror.defineMIME("text/x-scala", { + name: "clike", + keywords: words( + + /* scala */ + "abstract case catch class def do else extends false final finally for forSome if " + + "implicit import lazy match new null object override package private protected return " + + "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " + + "<% >: # @ " + + + /* package scala */ + "assert assume require print println printf readLine readBoolean readByte readShort " + + "readChar readInt readLong readFloat readDouble " + + + "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " + + "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " + + "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " + + "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " + + "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " + + + /* package java.lang */ + "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " + + "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + + "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + + "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" + + + ), + blockKeywords: words("catch class do else finally for forSome if match switch try while"), + atoms: words("true false null"), + hooks: { + "@": function(stream) { + stream.eatWhile(/[\w\$_]/); + return "meta"; + } + } + }); +}()); diff -r 029e6eed60e9 -r 388e48c0a37a dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/xml.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dew/src/main/resources/org/apidesign/bck2brwsr/dew/js/codemirror/mode/xml.js Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,324 @@ +CodeMirror.defineMode("xml", function(config, parserConfig) { + var indentUnit = config.indentUnit; + var Kludges = parserConfig.htmlMode ? { + autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, + 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, + 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, + 'track': true, 'wbr': true}, + implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, + 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, + 'th': true, 'tr': true}, + contextGrabbers: { + 'dd': {'dd': true, 'dt': true}, + 'dt': {'dd': true, 'dt': true}, + 'li': {'li': true}, + 'option': {'option': true, 'optgroup': true}, + 'optgroup': {'optgroup': true}, + 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, + 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, + 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, + 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, + 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, + 'rp': {'rp': true, 'rt': true}, + 'rt': {'rp': true, 'rt': true}, + 'tbody': {'tbody': true, 'tfoot': true}, + 'td': {'td': true, 'th': true}, + 'tfoot': {'tbody': true}, + 'th': {'td': true, 'th': true}, + 'thead': {'tbody': true, 'tfoot': true}, + 'tr': {'tr': true} + }, + doNotIndent: {"pre": true}, + allowUnquoted: true, + allowMissing: true + } : { + autoSelfClosers: {}, + implicitlyClosed: {}, + contextGrabbers: {}, + doNotIndent: {}, + allowUnquoted: false, + allowMissing: false + }; + var alignCDATA = parserConfig.alignCDATA; + + // Return variables for tokenizers + var tagName, type; + + function inText(stream, state) { + function chain(parser) { + state.tokenize = parser; + return parser(stream, state); + } + + var ch = stream.next(); + if (ch == "<") { + if (stream.eat("!")) { + if (stream.eat("[")) { + if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); + else return null; + } + else if (stream.match("--")) return chain(inBlock("comment", "-->")); + else if (stream.match("DOCTYPE", true, true)) { + stream.eatWhile(/[\w\._\-]/); + return chain(doctype(1)); + } + else return null; + } + else if (stream.eat("?")) { + stream.eatWhile(/[\w\._\-]/); + state.tokenize = inBlock("meta", "?>"); + return "meta"; + } + else { + var isClose = stream.eat("/"); + tagName = ""; + var c; + while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; + if (!tagName) return "error"; + type = isClose ? "closeTag" : "openTag"; + state.tokenize = inTag; + return "tag"; + } + } + else if (ch == "&") { + var ok; + if (stream.eat("#")) { + if (stream.eat("x")) { + ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); + } else { + ok = stream.eatWhile(/[\d]/) && stream.eat(";"); + } + } else { + ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); + } + return ok ? "atom" : "error"; + } + else { + stream.eatWhile(/[^&<]/); + return null; + } + } + + function inTag(stream, state) { + var ch = stream.next(); + if (ch == ">" || (ch == "/" && stream.eat(">"))) { + state.tokenize = inText; + type = ch == ">" ? "endTag" : "selfcloseTag"; + return "tag"; + } + else if (ch == "=") { + type = "equals"; + return null; + } + else if (/[\'\"]/.test(ch)) { + state.tokenize = inAttribute(ch); + return state.tokenize(stream, state); + } + else { + stream.eatWhile(/[^\s\u00a0=<>\"\']/); + return "word"; + } + } + + function inAttribute(quote) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.next() == quote) { + state.tokenize = inTag; + break; + } + } + return "string"; + }; + } + + function inBlock(style, terminator) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.match(terminator)) { + state.tokenize = inText; + break; + } + stream.next(); + } + return style; + }; + } + function doctype(depth) { + return function(stream, state) { + var ch; + while ((ch = stream.next()) != null) { + if (ch == "<") { + state.tokenize = doctype(depth + 1); + return state.tokenize(stream, state); + } else if (ch == ">") { + if (depth == 1) { + state.tokenize = inText; + break; + } else { + state.tokenize = doctype(depth - 1); + return state.tokenize(stream, state); + } + } + } + return "meta"; + }; + } + + var curState, setStyle; + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); + } + function cont() { + pass.apply(null, arguments); + return true; + } + + function pushContext(tagName, startOfLine) { + var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent); + curState.context = { + prev: curState.context, + tagName: tagName, + indent: curState.indented, + startOfLine: startOfLine, + noIndent: noIndent + }; + } + function popContext() { + if (curState.context) curState.context = curState.context.prev; + } + + function element(type) { + if (type == "openTag") { + curState.tagName = tagName; + return cont(attributes, endtag(curState.startOfLine)); + } else if (type == "closeTag") { + var err = false; + if (curState.context) { + if (curState.context.tagName != tagName) { + if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) { + popContext(); + } + err = !curState.context || curState.context.tagName != tagName; + } + } else { + err = true; + } + if (err) setStyle = "error"; + return cont(endclosetag(err)); + } + return cont(); + } + function endtag(startOfLine) { + return function(type) { + var tagName = curState.tagName; + curState.tagName = null; + if (type == "selfcloseTag" || + (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))) { + maybePopContext(tagName.toLowerCase()); + return cont(); + } + if (type == "endTag") { + maybePopContext(tagName.toLowerCase()); + pushContext(tagName, startOfLine); + return cont(); + } + return cont(); + }; + } + function endclosetag(err) { + return function(type) { + if (err) setStyle = "error"; + if (type == "endTag") { popContext(); return cont(); } + setStyle = "error"; + return cont(arguments.callee); + }; + } + function maybePopContext(nextTagName) { + var parentTagName; + while (true) { + if (!curState.context) { + return; + } + parentTagName = curState.context.tagName.toLowerCase(); + if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || + !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { + return; + } + popContext(); + } + } + + function attributes(type) { + if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);} + if (type == "endTag" || type == "selfcloseTag") return pass(); + setStyle = "error"; + return cont(attributes); + } + function attribute(type) { + if (type == "equals") return cont(attvalue, attributes); + if (!Kludges.allowMissing) setStyle = "error"; + else if (type == "word") setStyle = "attribute"; + return (type == "endTag" || type == "selfcloseTag") ? pass() : cont(); + } + function attvalue(type) { + if (type == "string") return cont(attvaluemaybe); + if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();} + setStyle = "error"; + return (type == "endTag" || type == "selfCloseTag") ? pass() : cont(); + } + function attvaluemaybe(type) { + if (type == "string") return cont(attvaluemaybe); + else return pass(); + } + + return { + startState: function() { + return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null}; + }, + + token: function(stream, state) { + if (stream.sol()) { + state.startOfLine = true; + state.indented = stream.indentation(); + } + if (stream.eatSpace()) return null; + + setStyle = type = tagName = null; + var style = state.tokenize(stream, state); + state.type = type; + if ((style || type) && style != "comment") { + curState = state; + while (true) { + var comb = state.cc.pop() || element; + if (comb(type || style)) break; + } + } + state.startOfLine = false; + return setStyle || style; + }, + + indent: function(state, textAfter, fullLine) { + var context = state.context; + if ((state.tokenize != inTag && state.tokenize != inText) || + context && context.noIndent) + return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; + if (alignCDATA && / + * + * 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.bck2brwsr.dew; + +import java.io.IOException; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public class CompileTest { + @Test public void testCompile() throws IOException { + String html = "" + + " " + + ""; + String java = "package x.y.z;" + + "import org.apidesign.bck2brwsr.htmlpage.api.*;" + + "import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;" + + "@Page(xhtml=\"index.html\", className=\"Index\")" + + "class X { " + + " @On(event=CLICK, id=\"btn\") static void clcs() {}" + + "}"; + Compile result = Compile.create(html, java); + + assertNotNull(result.get("x/y/z/X.class"), "Class X is compiled: " + result); + assertNotNull(result.get("x/y/z/Index.class"), "Class Index is compiled: " + result); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/pom.xml --- a/emul/pom.xml Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -5,11 +5,11 @@ org.apidesign bck2brwsr - 1.0-SNAPSHOT + 0.3-SNAPSHOT org.apidesign.bck2brwsr emul - 1.0-SNAPSHOT + 0.3-SNAPSHOT Java API Emulation http://maven.apache.org @@ -17,15 +17,9 @@ - junit - junit - 3.8.1 - test - - org.apidesign.bck2brwsr core - 1.0-SNAPSHOT + 0.3-SNAPSHOT jar diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/ByteArrayInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/io/ByteArrayInputStream.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,283 @@ +/* + * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +/** + * A ByteArrayInputStream contains + * an internal buffer that contains bytes that + * may be read from the stream. An internal + * counter keeps track of the next byte to + * be supplied by the read method. + *

+ * Closing a ByteArrayInputStream has no effect. The methods in + * this class can be called after the stream has been closed without + * generating an IOException. + * + * @author Arthur van Hoff + * @see java.io.StringBufferInputStream + * @since JDK1.0 + */ +public +class ByteArrayInputStream extends InputStream { + + /** + * An array of bytes that was provided + * by the creator of the stream. Elements buf[0] + * through buf[count-1] are the + * only bytes that can ever be read from the + * stream; element buf[pos] is + * the next byte to be read. + */ + protected byte buf[]; + + /** + * The index of the next character to read from the input stream buffer. + * This value should always be nonnegative + * and not larger than the value of count. + * The next byte to be read from the input stream buffer + * will be buf[pos]. + */ + protected int pos; + + /** + * The currently marked position in the stream. + * ByteArrayInputStream objects are marked at position zero by + * default when constructed. They may be marked at another + * position within the buffer by the mark() method. + * The current buffer position is set to this point by the + * reset() method. + *

+ * If no mark has been set, then the value of mark is the offset + * passed to the constructor (or 0 if the offset was not supplied). + * + * @since JDK1.1 + */ + protected int mark = 0; + + /** + * The index one greater than the last valid character in the input + * stream buffer. + * This value should always be nonnegative + * and not larger than the length of buf. + * It is one greater than the position of + * the last byte within buf that + * can ever be read from the input stream buffer. + */ + protected int count; + + /** + * Creates a ByteArrayInputStream + * so that it uses buf as its + * buffer array. + * The buffer array is not copied. + * The initial value of pos + * is 0 and the initial value + * of count is the length of + * buf. + * + * @param buf the input buffer. + */ + public ByteArrayInputStream(byte buf[]) { + this.buf = buf; + this.pos = 0; + this.count = buf.length; + } + + /** + * Creates ByteArrayInputStream + * that uses buf as its + * buffer array. The initial value of pos + * is offset and the initial value + * of count is the minimum of offset+length + * and buf.length. + * The buffer array is not copied. The buffer's mark is + * set to the specified offset. + * + * @param buf the input buffer. + * @param offset the offset in the buffer of the first byte to read. + * @param length the maximum number of bytes to read from the buffer. + */ + public ByteArrayInputStream(byte buf[], int offset, int length) { + this.buf = buf; + this.pos = offset; + this.count = Math.min(offset + length, buf.length); + this.mark = offset; + } + + /** + * Reads the next byte of data from this input stream. The value + * byte is returned as an int in the range + * 0 to 255. If no byte is available + * because the end of the stream has been reached, the value + * -1 is returned. + *

+ * This read method + * cannot block. + * + * @return the next byte of data, or -1 if the end of the + * stream has been reached. + */ + public synchronized int read() { + return (pos < count) ? (buf[pos++] & 0xff) : -1; + } + + /** + * Reads up to len bytes of data into an array of bytes + * from this input stream. + * If pos equals count, + * then -1 is returned to indicate + * end of file. Otherwise, the number k + * of bytes read is equal to the smaller of + * len and count-pos. + * If k is positive, then bytes + * buf[pos] through buf[pos+k-1] + * are copied into b[off] through + * b[off+k-1] in the manner performed + * by System.arraycopy. The + * value k is added into pos + * and k is returned. + *

+ * This read method cannot block. + * + * @param b the buffer into which the data is read. + * @param off the start offset in the destination array b + * @param len the maximum number of bytes read. + * @return the total number of bytes read into the buffer, or + * -1 if there is no more data because the end of + * the stream has been reached. + * @exception NullPointerException If b is null. + * @exception IndexOutOfBoundsException If off is negative, + * len is negative, or len is greater than + * b.length - off + */ + public synchronized int read(byte b[], int off, int len) { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } + + if (pos >= count) { + return -1; + } + + int avail = count - pos; + if (len > avail) { + len = avail; + } + if (len <= 0) { + return 0; + } + PushbackInputStream.arraycopy(buf, pos, b, off, len); + pos += len; + return len; + } + + /** + * Skips n bytes of input from this input stream. Fewer + * bytes might be skipped if the end of the input stream is reached. + * The actual number k + * of bytes to be skipped is equal to the smaller + * of n and count-pos. + * The value k is added into pos + * and k is returned. + * + * @param n the number of bytes to be skipped. + * @return the actual number of bytes skipped. + */ + public synchronized long skip(long n) { + long k = count - pos; + if (n < k) { + k = n < 0 ? 0 : n; + } + + pos += k; + return k; + } + + /** + * Returns the number of remaining bytes that can be read (or skipped over) + * from this input stream. + *

+ * The value returned is count - pos, + * which is the number of bytes remaining to be read from the input buffer. + * + * @return the number of remaining bytes that can be read (or skipped + * over) from this input stream without blocking. + */ + public synchronized int available() { + return count - pos; + } + + /** + * Tests if this InputStream supports mark/reset. The + * markSupported method of ByteArrayInputStream + * always returns true. + * + * @since JDK1.1 + */ + public boolean markSupported() { + return true; + } + + /** + * Set the current marked position in the stream. + * ByteArrayInputStream objects are marked at position zero by + * default when constructed. They may be marked at another + * position within the buffer by this method. + *

+ * If no mark has been set, then the value of the mark is the + * offset passed to the constructor (or 0 if the offset was not + * supplied). + * + *

Note: The readAheadLimit for this class + * has no meaning. + * + * @since JDK1.1 + */ + public void mark(int readAheadLimit) { + mark = pos; + } + + /** + * Resets the buffer to the marked position. The marked position + * is 0 unless another position was marked or an offset was specified + * in the constructor. + */ + public synchronized void reset() { + pos = mark; + } + + /** + * Closing a ByteArrayInputStream has no effect. The methods in + * this class can be called after the stream has been closed without + * generating an IOException. + *

+ */ + public void close() throws IOException { + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/Closeable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/io/Closeable.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +import java.io.IOException; + +/** + * A {@code Closeable} is a source or destination of data that can be closed. + * The close method is invoked to release resources that the object is + * holding (such as open files). + * + * @since 1.5 + */ + +public interface Closeable extends AutoCloseable { + + /** + * Closes this stream and releases any system resources associated + * with it. If the stream is already closed then invoking this + * method has no effect. + * + * @throws IOException if an I/O error occurs + */ + public void close() throws IOException; +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/DataInput.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/io/DataInput.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,635 @@ +/* + * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +/** + * The DataInput interface provides + * for reading bytes from a binary stream and + * reconstructing from them data in any of + * the Java primitive types. There is also + * a + * facility for reconstructing a String + * from data in + * modified UTF-8 + * format. + *

+ * It is generally true of all the reading + * routines in this interface that if end of + * file is reached before the desired number + * of bytes has been read, an EOFException + * (which is a kind of IOException) + * is thrown. If any byte cannot be read for + * any reason other than end of file, an IOException + * other than EOFException is + * thrown. In particular, an IOException + * may be thrown if the input stream has been + * closed. + * + *

Modified UTF-8

+ *

+ * Implementations of the DataInput and DataOutput interfaces represent + * Unicode strings in a format that is a slight modification of UTF-8. + * (For information regarding the standard UTF-8 format, see section + * 3.9 Unicode Encoding Forms of The Unicode Standard, Version + * 4.0). + * Note that in the following tables, the most significant bit appears in the + * far left-hand column. + *

+ * All characters in the range '\u0001' to + * '\u007F' are represented by a single byte: + * + *

+ * + * + * + * + * + * + * + * + * + *
Bit Values
Byte 1 + * + * + * + *
0
+ *
bits 6-0
+ *
+ *
+ *
+ * + *

+ * The null character '\u0000' and characters in the + * range '\u0080' to '\u07FF' are + * represented by a pair of bytes: + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + *
Bit Values
Byte 1 + * + * + * + *
1
+ *
1
+ *
0
+ *
bits 10-6
+ *
+ *
Byte 2 + * + * + * + *
1
+ *
0
+ *
bits 5-0
+ *
+ *
+ *
+ * + *
+ * char values in the range '\u0800' to + * '\uFFFF' are represented by three bytes: + * + *
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Bit Values
Byte 1 + * + * + * + *
1
+ *
1
+ *
1
+ *
0
+ *
bits 15-12
+ *
+ *
Byte 2 + * + * + * + *
1
+ *
0
+ *
bits 11-6
+ *
+ *
Byte 3 + * + * + * + *
1
+ *
0
+ *
bits 5-0
+ *
+ *
+ *
+ * + *

+ * The differences between this format and the + * standard UTF-8 format are the following: + *

    + *
  • The null byte '\u0000' is encoded in 2-byte format + * rather than 1-byte, so that the encoded strings never have + * embedded nulls. + *
  • Only the 1-byte, 2-byte, and 3-byte formats are used. + *
  • Supplementary characters + * are represented in the form of surrogate pairs. + *
+ * @author Frank Yellin + * @see java.io.DataInputStream + * @see java.io.DataOutput + * @since JDK1.0 + */ +public +interface DataInput { + /** + * Reads some bytes from an input + * stream and stores them into the buffer + * array b. The number of bytes + * read is equal + * to the length of b. + *

+ * This method blocks until one of the + * following conditions occurs:

+ *

    + *
  • b.length + * bytes of input data are available, in which + * case a normal return is made. + * + *
  • End of + * file is detected, in which case an EOFException + * is thrown. + * + *
  • An I/O error occurs, in + * which case an IOException other + * than EOFException is thrown. + *
+ *

+ * If b is null, + * a NullPointerException is thrown. + * If b.length is zero, then + * no bytes are read. Otherwise, the first + * byte read is stored into element b[0], + * the next one into b[1], and + * so on. + * If an exception is thrown from + * this method, then it may be that some but + * not all bytes of b have been + * updated with data from the input stream. + * + * @param b the buffer into which the data is read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + void readFully(byte b[]) throws IOException; + + /** + * + * Reads len + * bytes from + * an input stream. + *

+ * This method + * blocks until one of the following conditions + * occurs:

+ *

    + *
  • len bytes + * of input data are available, in which case + * a normal return is made. + * + *
  • End of file + * is detected, in which case an EOFException + * is thrown. + * + *
  • An I/O error occurs, in + * which case an IOException other + * than EOFException is thrown. + *
+ *

+ * If b is null, + * a NullPointerException is thrown. + * If off is negative, or len + * is negative, or off+len is + * greater than the length of the array b, + * then an IndexOutOfBoundsException + * is thrown. + * If len is zero, + * then no bytes are read. Otherwise, the first + * byte read is stored into element b[off], + * the next one into b[off+1], + * and so on. The number of bytes read is, + * at most, equal to len. + * + * @param b the buffer into which the data is read. + * @param off an int specifying the offset into the data. + * @param len an int specifying the number of bytes to read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + void readFully(byte b[], int off, int len) throws IOException; + + /** + * Makes an attempt to skip over + * n bytes + * of data from the input + * stream, discarding the skipped bytes. However, + * it may skip + * over some smaller number of + * bytes, possibly zero. This may result from + * any of a + * number of conditions; reaching + * end of file before n bytes + * have been skipped is + * only one possibility. + * This method never throws an EOFException. + * The actual + * number of bytes skipped is returned. + * + * @param n the number of bytes to be skipped. + * @return the number of bytes actually skipped. + * @exception IOException if an I/O error occurs. + */ + int skipBytes(int n) throws IOException; + + /** + * Reads one input byte and returns + * true if that byte is nonzero, + * false if that byte is zero. + * This method is suitable for reading + * the byte written by the writeBoolean + * method of interface DataOutput. + * + * @return the boolean value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + boolean readBoolean() throws IOException; + + /** + * Reads and returns one input byte. + * The byte is treated as a signed value in + * the range -128 through 127, + * inclusive. + * This method is suitable for + * reading the byte written by the writeByte + * method of interface DataOutput. + * + * @return the 8-bit value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + byte readByte() throws IOException; + + /** + * Reads one input byte, zero-extends + * it to type int, and returns + * the result, which is therefore in the range + * 0 + * through 255. + * This method is suitable for reading + * the byte written by the writeByte + * method of interface DataOutput + * if the argument to writeByte + * was intended to be a value in the range + * 0 through 255. + * + * @return the unsigned 8-bit value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + int readUnsignedByte() throws IOException; + + /** + * Reads two input bytes and returns + * a short value. Let a + * be the first byte read and b + * be the second byte. The value + * returned + * is: + *

(short)((a << 8) | (b & 0xff))
+     * 
+ * This method + * is suitable for reading the bytes written + * by the writeShort method of + * interface DataOutput. + * + * @return the 16-bit value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + short readShort() throws IOException; + + /** + * Reads two input bytes and returns + * an int value in the range 0 + * through 65535. Let a + * be the first byte read and + * b + * be the second byte. The value returned is: + *

(((a & 0xff) << 8) | (b & 0xff))
+     * 
+ * This method is suitable for reading the bytes + * written by the writeShort method + * of interface DataOutput if + * the argument to writeShort + * was intended to be a value in the range + * 0 through 65535. + * + * @return the unsigned 16-bit value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + int readUnsignedShort() throws IOException; + + /** + * Reads two input bytes and returns a char value. + * Let a + * be the first byte read and b + * be the second byte. The value + * returned is: + *

(char)((a << 8) | (b & 0xff))
+     * 
+ * This method + * is suitable for reading bytes written by + * the writeChar method of interface + * DataOutput. + * + * @return the char value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + char readChar() throws IOException; + + /** + * Reads four input bytes and returns an + * int value. Let a-d + * be the first through fourth bytes read. The value returned is: + *

+     * 
+     * (((a & 0xff) << 24) | ((b & 0xff) << 16) |
+     *  ((c & 0xff) << 8) | (d & 0xff))
+     * 
+ * This method is suitable + * for reading bytes written by the writeInt + * method of interface DataOutput. + * + * @return the int value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + int readInt() throws IOException; + + /** + * Reads eight input bytes and returns + * a long value. Let a-h + * be the first through eighth bytes read. + * The value returned is: + *

 
+     * (((long)(a & 0xff) << 56) |
+     *  ((long)(b & 0xff) << 48) |
+     *  ((long)(c & 0xff) << 40) |
+     *  ((long)(d & 0xff) << 32) |
+     *  ((long)(e & 0xff) << 24) |
+     *  ((long)(f & 0xff) << 16) |
+     *  ((long)(g & 0xff) <<  8) |
+     *  ((long)(h & 0xff)))
+     * 
+ *

+ * This method is suitable + * for reading bytes written by the writeLong + * method of interface DataOutput. + * + * @return the long value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + long readLong() throws IOException; + + /** + * Reads four input bytes and returns + * a float value. It does this + * by first constructing an int + * value in exactly the manner + * of the readInt + * method, then converting this int + * value to a float in + * exactly the manner of the method Float.intBitsToFloat. + * This method is suitable for reading + * bytes written by the writeFloat + * method of interface DataOutput. + * + * @return the float value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + float readFloat() throws IOException; + + /** + * Reads eight input bytes and returns + * a double value. It does this + * by first constructing a long + * value in exactly the manner + * of the readlong + * method, then converting this long + * value to a double in exactly + * the manner of the method Double.longBitsToDouble. + * This method is suitable for reading + * bytes written by the writeDouble + * method of interface DataOutput. + * + * @return the double value read. + * @exception EOFException if this stream reaches the end before reading + * all the bytes. + * @exception IOException if an I/O error occurs. + */ + double readDouble() throws IOException; + + /** + * Reads the next line of text from the input stream. + * It reads successive bytes, converting + * each byte separately into a character, + * until it encounters a line terminator or + * end of + * file; the characters read are then + * returned as a String. Note + * that because this + * method processes bytes, + * it does not support input of the full Unicode + * character set. + *

+ * If end of file is encountered + * before even one byte can be read, then null + * is returned. Otherwise, each byte that is + * read is converted to type char + * by zero-extension. If the character '\n' + * is encountered, it is discarded and reading + * ceases. If the character '\r' + * is encountered, it is discarded and, if + * the following byte converts to the + * character '\n', then that is + * discarded also; reading then ceases. If + * end of file is encountered before either + * of the characters '\n' and + * '\r' is encountered, reading + * ceases. Once reading has ceased, a String + * is returned that contains all the characters + * read and not discarded, taken in order. + * Note that every character in this string + * will have a value less than \u0100, + * that is, (char)256. + * + * @return the next line of text from the input stream, + * or null if the end of file is + * encountered before a byte can be read. + * @exception IOException if an I/O error occurs. + */ + String readLine() throws IOException; + + /** + * Reads in a string that has been encoded using a + * modified UTF-8 + * format. + * The general contract of readUTF + * is that it reads a representation of a Unicode + * character string encoded in modified + * UTF-8 format; this string of characters + * is then returned as a String. + *

+ * First, two bytes are read and used to + * construct an unsigned 16-bit integer in + * exactly the manner of the readUnsignedShort + * method . This integer value is called the + * UTF length and specifies the number + * of additional bytes to be read. These bytes + * are then converted to characters by considering + * them in groups. The length of each group + * is computed from the value of the first + * byte of the group. The byte following a + * group, if any, is the first byte of the + * next group. + *

+ * If the first byte of a group + * matches the bit pattern 0xxxxxxx + * (where x means "may be 0 + * or 1"), then the group consists + * of just that byte. The byte is zero-extended + * to form a character. + *

+ * If the first byte + * of a group matches the bit pattern 110xxxxx, + * then the group consists of that byte a + * and a second byte b. If there + * is no byte b (because byte + * a was the last of the bytes + * to be read), or if byte b does + * not match the bit pattern 10xxxxxx, + * then a UTFDataFormatException + * is thrown. Otherwise, the group is converted + * to the character:

+ *

(char)(((a& 0x1F) << 6) | (b & 0x3F))
+     * 
+ * If the first byte of a group + * matches the bit pattern 1110xxxx, + * then the group consists of that byte a + * and two more bytes b and c. + * If there is no byte c (because + * byte a was one of the last + * two of the bytes to be read), or either + * byte b or byte c + * does not match the bit pattern 10xxxxxx, + * then a UTFDataFormatException + * is thrown. Otherwise, the group is converted + * to the character:

+ *


+     * (char)(((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F))
+     * 
+ * If the first byte of a group matches the + * pattern 1111xxxx or the pattern + * 10xxxxxx, then a UTFDataFormatException + * is thrown. + *

+ * If end of file is encountered + * at any time during this entire process, + * then an EOFException is thrown. + *

+ * After every group has been converted to + * a character by this process, the characters + * are gathered, in the same order in which + * their corresponding groups were read from + * the input stream, to form a String, + * which is returned. + *

+ * The writeUTF + * method of interface DataOutput + * may be used to write data that is suitable + * for reading by this method. + * @return a Unicode string. + * @exception EOFException if this stream reaches the end + * before reading all the bytes. + * @exception IOException if an I/O error occurs. + * @exception UTFDataFormatException if the bytes do not represent a + * valid modified UTF-8 encoding of a string. + */ + String readUTF() throws IOException; +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/DataInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/io/DataInputStream.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,704 @@ +/* + * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * A data input stream lets an application read primitive Java data + * types from an underlying input stream in a machine-independent + * way. An application uses a data output stream to write data that + * can later be read by a data input stream. + *

+ * DataInputStream is not necessarily safe for multithreaded access. + * Thread safety is optional and is the responsibility of users of + * methods in this class. + * + * @author Arthur van Hoff + * @see java.io.DataOutputStream + * @since JDK1.0 + */ +public +class DataInputStream extends FilterInputStream implements DataInput { + + /** + * Creates a DataInputStream that uses the specified + * underlying InputStream. + * + * @param in the specified input stream + */ + public DataInputStream(InputStream in) { + super(in); + } + + /** + * working arrays initialized on demand by readUTF + */ + private byte bytearr[] = new byte[80]; + private char chararr[] = new char[80]; + + /** + * Reads some number of bytes from the contained input stream and + * stores them into the buffer array b. The number of + * bytes actually read is returned as an integer. This method blocks + * until input data is available, end of file is detected, or an + * exception is thrown. + * + *

If b is null, a NullPointerException is + * thrown. If the length of b is zero, then no bytes are + * read and 0 is returned; otherwise, there is an attempt + * to read at least one byte. If no byte is available because the + * stream is at end of file, the value -1 is returned; + * otherwise, at least one byte is read and stored into b. + * + *

The first byte read is stored into element b[0], the + * next one into b[1], and so on. The number of bytes read + * is, at most, equal to the length of b. Let k + * be the number of bytes actually read; these bytes will be stored in + * elements b[0] through b[k-1], leaving + * elements b[k] through b[b.length-1] + * unaffected. + * + *

The read(b) method has the same effect as: + *

+     * read(b, 0, b.length)
+     * 
+ * + * @param b the buffer into which the data is read. + * @return the total number of bytes read into the buffer, or + * -1 if there is no more data because the end + * of the stream has been reached. + * @exception IOException if the first byte cannot be read for any reason + * other than end of file, the stream has been closed and the underlying + * input stream does not support reading after close, or another I/O + * error occurs. + * @see java.io.FilterInputStream#in + * @see java.io.InputStream#read(byte[], int, int) + */ + public final int read(byte b[]) throws IOException { + return in.read(b, 0, b.length); + } + + /** + * Reads up to len bytes of data from the contained + * input stream into an array of bytes. An attempt is made to read + * as many as len bytes, but a smaller number may be read, + * possibly zero. The number of bytes actually read is returned as an + * integer. + * + *

This method blocks until input data is available, end of file is + * detected, or an exception is thrown. + * + *

If len is zero, then no bytes are read and + * 0 is returned; otherwise, there is an attempt to read at + * least one byte. If no byte is available because the stream is at end of + * file, the value -1 is returned; otherwise, at least one + * byte is read and stored into b. + * + *

The first byte read is stored into element b[off], the + * next one into b[off+1], and so on. The number of bytes read + * is, at most, equal to len. Let k be the number of + * bytes actually read; these bytes will be stored in elements + * b[off] through b[off+k-1], + * leaving elements b[off+k] through + * b[off+len-1] unaffected. + * + *

In every case, elements b[0] through + * b[off] and elements b[off+len] through + * b[b.length-1] are unaffected. + * + * @param b the buffer into which the data is read. + * @param off the start offset in the destination array b + * @param len the maximum number of bytes read. + * @return the total number of bytes read into the buffer, or + * -1 if there is no more data because the end + * of the stream has been reached. + * @exception NullPointerException If b is null. + * @exception IndexOutOfBoundsException If off is negative, + * len is negative, or len is greater than + * b.length - off + * @exception IOException if the first byte cannot be read for any reason + * other than end of file, the stream has been closed and the underlying + * input stream does not support reading after close, or another I/O + * error occurs. + * @see java.io.FilterInputStream#in + * @see java.io.InputStream#read(byte[], int, int) + */ + public final int read(byte b[], int off, int len) throws IOException { + return in.read(b, off, len); + } + + /** + * See the general contract of the readFully + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @param b the buffer into which the data is read. + * @exception EOFException if this input stream reaches the end before + * reading all the bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final void readFully(byte b[]) throws IOException { + readFully(b, 0, b.length); + } + + /** + * See the general contract of the readFully + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @param b the buffer into which the data is read. + * @param off the start offset of the data. + * @param len the number of bytes to read. + * @exception EOFException if this input stream reaches the end before + * reading all the bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final void readFully(byte b[], int off, int len) throws IOException { + if (len < 0) + throw new IndexOutOfBoundsException(); + int n = 0; + while (n < len) { + int count = in.read(b, off + n, len - n); + if (count < 0) + throw new EOFException(); + n += count; + } + } + + /** + * See the general contract of the skipBytes + * method of DataInput. + *

+ * Bytes for this operation are read from the contained + * input stream. + * + * @param n the number of bytes to be skipped. + * @return the actual number of bytes skipped. + * @exception IOException if the contained input stream does not support + * seek, or the stream has been closed and + * the contained input stream does not support + * reading after close, or another I/O error occurs. + */ + public final int skipBytes(int n) throws IOException { + int total = 0; + int cur = 0; + + while ((total 0)) { + total += cur; + } + + return total; + } + + /** + * See the general contract of the readBoolean + * method of DataInput. + *

+ * Bytes for this operation are read from the contained + * input stream. + * + * @return the boolean value read. + * @exception EOFException if this input stream has reached the end. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final boolean readBoolean() throws IOException { + int ch = in.read(); + if (ch < 0) + throw new EOFException(); + return (ch != 0); + } + + /** + * See the general contract of the readByte + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return the next byte of this input stream as a signed 8-bit + * byte. + * @exception EOFException if this input stream has reached the end. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final byte readByte() throws IOException { + int ch = in.read(); + if (ch < 0) + throw new EOFException(); + return (byte)(ch); + } + + /** + * See the general contract of the readUnsignedByte + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return the next byte of this input stream, interpreted as an + * unsigned 8-bit number. + * @exception EOFException if this input stream has reached the end. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final int readUnsignedByte() throws IOException { + int ch = in.read(); + if (ch < 0) + throw new EOFException(); + return ch; + } + + /** + * See the general contract of the readShort + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return the next two bytes of this input stream, interpreted as a + * signed 16-bit number. + * @exception EOFException if this input stream reaches the end before + * reading two bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final short readShort() throws IOException { + int ch1 = in.read(); + int ch2 = in.read(); + if ((ch1 | ch2) < 0) + throw new EOFException(); + return (short)((ch1 << 8) + (ch2 << 0)); + } + + /** + * See the general contract of the readUnsignedShort + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return the next two bytes of this input stream, interpreted as an + * unsigned 16-bit integer. + * @exception EOFException if this input stream reaches the end before + * reading two bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final int readUnsignedShort() throws IOException { + int ch1 = in.read(); + int ch2 = in.read(); + if ((ch1 | ch2) < 0) + throw new EOFException(); + return (ch1 << 8) + (ch2 << 0); + } + + /** + * See the general contract of the readChar + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return the next two bytes of this input stream, interpreted as a + * char. + * @exception EOFException if this input stream reaches the end before + * reading two bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final char readChar() throws IOException { + int ch1 = in.read(); + int ch2 = in.read(); + if ((ch1 | ch2) < 0) + throw new EOFException(); + return (char)((ch1 << 8) + (ch2 << 0)); + } + + /** + * See the general contract of the readInt + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return the next four bytes of this input stream, interpreted as an + * int. + * @exception EOFException if this input stream reaches the end before + * reading four bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final int readInt() throws IOException { + int ch1 = in.read(); + int ch2 = in.read(); + int ch3 = in.read(); + int ch4 = in.read(); + if ((ch1 | ch2 | ch3 | ch4) < 0) + throw new EOFException(); + return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); + } + + private byte readBuffer[] = new byte[8]; + + /** + * See the general contract of the readLong + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return the next eight bytes of this input stream, interpreted as a + * long. + * @exception EOFException if this input stream reaches the end before + * reading eight bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public final long readLong() throws IOException { + readFully(readBuffer, 0, 8); + return (((long)readBuffer[0] << 56) + + ((long)(readBuffer[1] & 255) << 48) + + ((long)(readBuffer[2] & 255) << 40) + + ((long)(readBuffer[3] & 255) << 32) + + ((long)(readBuffer[4] & 255) << 24) + + ((readBuffer[5] & 255) << 16) + + ((readBuffer[6] & 255) << 8) + + ((readBuffer[7] & 255) << 0)); + } + + /** + * See the general contract of the readFloat + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return the next four bytes of this input stream, interpreted as a + * float. + * @exception EOFException if this input stream reaches the end before + * reading four bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.DataInputStream#readInt() + * @see java.lang.Float#intBitsToFloat(int) + */ + public final float readFloat() throws IOException { + return Float.intBitsToFloat(readInt()); + } + + /** + * See the general contract of the readDouble + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return the next eight bytes of this input stream, interpreted as a + * double. + * @exception EOFException if this input stream reaches the end before + * reading eight bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @see java.io.DataInputStream#readLong() + * @see java.lang.Double#longBitsToDouble(long) + */ + public final double readDouble() throws IOException { + int hi = readInt(); + int low = readInt(); + return toDouble(hi, low); + } + + @JavaScriptBody(args={ "hi", "low" }, + body= + "if (low == 0) {\n" + + " if (hi === 0x7ff00000) return Number.POSITIVE_INFINITY;\n" + + " if (hi === 0xfff00000) return Number.NEGATIVE_INFINITY;\n" + + "}\n" + + "if (hi >= 0x7ff00000 && hi <= 0x7fffffff) return Number.NaN;\n" + + "if (hi >= 0xfff00000 && hi <= 0xffffffff) return Number.NaN;\n" + + "var s = (hi & 0x80000000) === 0 ? 1 : -1;\n" + + "var e = (hi >> 20) & 0x7ff;\n" + + "var to32 = low >> 0;\n" + + "if (e === 0) {\n" + + " if (to32 & 0x80000000) {\n" + + " hi = hi << 1 + 1; low = low << 1;\n" + + " } else {\n" + + " hi = hi << 1; low = low << 1;\n" + + " }\n" + + "} else {\n" + + " hi = (hi & 0xfffff) | 0x100000;\n" + + "}\n" + + "to32 = low >> 0;\n" + + "var m = Math.pow(2.0, 32) * hi + to32;\n" + + "var r = s * m * Math.pow(2.0, e - 1075);\n" + + "//throw 'exp: ' + e + ' sign: ' + s + ' hi:' + hi + ' low: ' + low + ' m: ' + m + ' r: ' + r;\n" + + "return r;\n" + ) + private static double toDouble(int hi, int low) { + long both = hi; + both = (both << 32) & low; + return Double.doubleToLongBits(both); + } + + private char lineBuffer[]; + + /** + * See the general contract of the readLine + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @deprecated This method does not properly convert bytes to characters. + * As of JDK 1.1, the preferred way to read lines of text is via the + * BufferedReader.readLine() method. Programs that use the + * DataInputStream class to read lines can be converted to use + * the BufferedReader class by replacing code of the form: + *

+     *     DataInputStream d = new DataInputStream(in);
+     * 
+ * with: + *
+     *     BufferedReader d
+     *          = new BufferedReader(new InputStreamReader(in));
+     * 
+ * + * @return the next line of text from this input stream. + * @exception IOException if an I/O error occurs. + * @see java.io.BufferedReader#readLine() + * @see java.io.FilterInputStream#in + */ + @Deprecated + public final String readLine() throws IOException { + char buf[] = lineBuffer; + + if (buf == null) { + buf = lineBuffer = new char[128]; + } + + int room = buf.length; + int offset = 0; + int c; + +loop: while (true) { + switch (c = in.read()) { + case -1: + case '\n': + break loop; + + case '\r': + int c2 = in.read(); + if ((c2 != '\n') && (c2 != -1)) { + if (!(in instanceof PushbackInputStream)) { + this.in = new PushbackInputStream(in); + } + ((PushbackInputStream)in).unread(c2); + } + break loop; + + default: + if (--room < 0) { + buf = new char[offset + 128]; + room = buf.length - offset - 1; + arraycopy(lineBuffer, 0, buf, 0, offset); + lineBuffer = buf; + } + buf[offset++] = (char) c; + break; + } + } + if ((c == -1) && (offset == 0)) { + return null; + } + return String.copyValueOf(buf, 0, offset); + } + + /** + * See the general contract of the readUTF + * method of DataInput. + *

+ * Bytes + * for this operation are read from the contained + * input stream. + * + * @return a Unicode string. + * @exception EOFException if this input stream reaches the end before + * reading all the bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @exception UTFDataFormatException if the bytes do not represent a valid + * modified UTF-8 encoding of a string. + * @see java.io.DataInputStream#readUTF(java.io.DataInput) + */ + public final String readUTF() throws IOException { + return readUTF(this); + } + + /** + * Reads from the + * stream in a representation + * of a Unicode character string encoded in + * modified UTF-8 format; + * this string of characters is then returned as a String. + * The details of the modified UTF-8 representation + * are exactly the same as for the readUTF + * method of DataInput. + * + * @param in a data input stream. + * @return a Unicode string. + * @exception EOFException if the input stream reaches the end + * before all the bytes. + * @exception IOException the stream has been closed and the contained + * input stream does not support reading after close, or + * another I/O error occurs. + * @exception UTFDataFormatException if the bytes do not represent a + * valid modified UTF-8 encoding of a Unicode string. + * @see java.io.DataInputStream#readUnsignedShort() + */ + public final static String readUTF(DataInput in) throws IOException { + int utflen = in.readUnsignedShort(); + byte[] bytearr = null; + char[] chararr = null; + if (in instanceof DataInputStream) { + DataInputStream dis = (DataInputStream)in; + if (dis.bytearr.length < utflen){ + dis.bytearr = new byte[utflen*2]; + dis.chararr = new char[utflen*2]; + } + chararr = dis.chararr; + bytearr = dis.bytearr; + } else { + bytearr = new byte[utflen]; + chararr = new char[utflen]; + } + + int c, char2, char3; + int count = 0; + int chararr_count=0; + + in.readFully(bytearr, 0, utflen); + + while (count < utflen) { + c = (int) bytearr[count] & 0xff; + if (c > 127) break; + count++; + chararr[chararr_count++]=(char)c; + } + + while (count < utflen) { + c = (int) bytearr[count] & 0xff; + switch (c >> 4) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + /* 0xxxxxxx*/ + count++; + chararr[chararr_count++]=(char)c; + break; + case 12: case 13: + /* 110x xxxx 10xx xxxx*/ + count += 2; + if (count > utflen) + throw new UTFDataFormatException( + "malformed input: partial character at end"); + char2 = (int) bytearr[count-1]; + if ((char2 & 0xC0) != 0x80) + throw new UTFDataFormatException( + "malformed input around byte " + count); + chararr[chararr_count++]=(char)(((c & 0x1F) << 6) | + (char2 & 0x3F)); + break; + case 14: + /* 1110 xxxx 10xx xxxx 10xx xxxx */ + count += 3; + if (count > utflen) + throw new UTFDataFormatException( + "malformed input: partial character at end"); + char2 = (int) bytearr[count-2]; + char3 = (int) bytearr[count-1]; + if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) + throw new UTFDataFormatException( + "malformed input around byte " + (count-1)); + chararr[chararr_count++]=(char)(((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0)); + break; + default: + /* 10xx xxxx, 1111 xxxx */ + throw new UTFDataFormatException( + "malformed input around byte " + count); + } + } + // The number of chars produced may be less than utflen + return new String(chararr, 0, chararr_count); + } + static void arraycopy(char[] value, int srcBegin, char[] dst, int dstBegin, int count) { + while (count-- > 0) { + dst[dstBegin++] = value[srcBegin++]; + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/EOFException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/io/EOFException.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +/** + * Signals that an end of file or end of stream has been reached + * unexpectedly during input. + *

+ * This exception is mainly used by data input streams to signal end of + * stream. Note that many other input operations return a special value on + * end of stream rather than throwing an exception. + *

+ * + * @author Frank Yellin + * @see java.io.DataInputStream + * @see java.io.IOException + * @since JDK1.0 + */ +public +class EOFException extends IOException { + private static final long serialVersionUID = 6433858223774886977L; + + /** + * Constructs an EOFException with null + * as its error detail message. + */ + public EOFException() { + super(); + } + + /** + * Constructs an EOFException with the specified detail + * message. The string s may later be retrieved by the + * {@link java.lang.Throwable#getMessage} method of class + * java.lang.Throwable. + * + * @param s the detail message. + */ + public EOFException(String s) { + super(s); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/FilterInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/io/FilterInputStream.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +/** + * A FilterInputStream contains + * some other input stream, which it uses as + * its basic source of data, possibly transforming + * the data along the way or providing additional + * functionality. The class FilterInputStream + * itself simply overrides all methods of + * InputStream with versions that + * pass all requests to the contained input + * stream. Subclasses of FilterInputStream + * may further override some of these methods + * and may also provide additional methods + * and fields. + * + * @author Jonathan Payne + * @since JDK1.0 + */ +public +class FilterInputStream extends InputStream { + /** + * The input stream to be filtered. + */ + protected volatile InputStream in; + + /** + * Creates a FilterInputStream + * by assigning the argument in + * to the field this.in so as + * to remember it for later use. + * + * @param in the underlying input stream, or null if + * this instance is to be created without an underlying stream. + */ + protected FilterInputStream(InputStream in) { + this.in = in; + } + + /** + * Reads the next byte of data from this input stream. The value + * byte is returned as an int in the range + * 0 to 255. If no byte is available + * because the end of the stream has been reached, the value + * -1 is returned. This method blocks until input data + * is available, the end of the stream is detected, or an exception + * is thrown. + *

+ * This method + * simply performs in.read() and returns the result. + * + * @return the next byte of data, or -1 if the end of the + * stream is reached. + * @exception IOException if an I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public int read() throws IOException { + return in.read(); + } + + /** + * Reads up to byte.length bytes of data from this + * input stream into an array of bytes. This method blocks until some + * input is available. + *

+ * This method simply performs the call + * read(b, 0, b.length) and returns + * the result. It is important that it does + * not do in.read(b) instead; + * certain subclasses of FilterInputStream + * depend on the implementation strategy actually + * used. + * + * @param b the buffer into which the data is read. + * @return the total number of bytes read into the buffer, or + * -1 if there is no more data because the end of + * the stream has been reached. + * @exception IOException if an I/O error occurs. + * @see java.io.FilterInputStream#read(byte[], int, int) + */ + public int read(byte b[]) throws IOException { + return read(b, 0, b.length); + } + + /** + * Reads up to len bytes of data from this input stream + * into an array of bytes. If len is not zero, the method + * blocks until some input is available; otherwise, no + * bytes are read and 0 is returned. + *

+ * This method simply performs in.read(b, off, len) + * and returns the result. + * + * @param b the buffer into which the data is read. + * @param off the start offset in the destination array b + * @param len the maximum number of bytes read. + * @return the total number of bytes read into the buffer, or + * -1 if there is no more data because the end of + * the stream has been reached. + * @exception NullPointerException If b is null. + * @exception IndexOutOfBoundsException If off is negative, + * len is negative, or len is greater than + * b.length - off + * @exception IOException if an I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public int read(byte b[], int off, int len) throws IOException { + return in.read(b, off, len); + } + + /** + * Skips over and discards n bytes of data from the + * input stream. The skip method may, for a variety of + * reasons, end up skipping over some smaller number of bytes, + * possibly 0. The actual number of bytes skipped is + * returned. + *

+ * This method simply performs in.skip(n). + * + * @param n the number of bytes to be skipped. + * @return the actual number of bytes skipped. + * @exception IOException if the stream does not support seek, + * or if some other I/O error occurs. + */ + public long skip(long n) throws IOException { + return in.skip(n); + } + + /** + * Returns an estimate of the number of bytes that can be read (or + * skipped over) from this input stream without blocking by the next + * caller of a method for this input stream. The next caller might be + * the same thread or another thread. A single read or skip of this + * many bytes will not block, but may read or skip fewer bytes. + *

+ * This method returns the result of {@link #in in}.available(). + * + * @return an estimate of the number of bytes that can be read (or skipped + * over) from this input stream without blocking. + * @exception IOException if an I/O error occurs. + */ + public int available() throws IOException { + return in.available(); + } + + /** + * Closes this input stream and releases any system resources + * associated with the stream. + * This + * method simply performs in.close(). + * + * @exception IOException if an I/O error occurs. + * @see java.io.FilterInputStream#in + */ + public void close() throws IOException { + in.close(); + } + + /** + * Marks the current position in this input stream. A subsequent + * call to the reset method repositions this stream at + * the last marked position so that subsequent reads re-read the same bytes. + *

+ * The readlimit argument tells this input stream to + * allow that many bytes to be read before the mark position gets + * invalidated. + *

+ * This method simply performs in.mark(readlimit). + * + * @param readlimit the maximum limit of bytes that can be read before + * the mark position becomes invalid. + * @see java.io.FilterInputStream#in + * @see java.io.FilterInputStream#reset() + */ + public synchronized void mark(int readlimit) { + in.mark(readlimit); + } + + /** + * Repositions this stream to the position at the time the + * mark method was last called on this input stream. + *

+ * This method + * simply performs in.reset(). + *

+ * Stream marks are intended to be used in + * situations where you need to read ahead a little to see what's in + * the stream. Often this is most easily done by invoking some + * general parser. If the stream is of the type handled by the + * parse, it just chugs along happily. If the stream is not of + * that type, the parser should toss an exception when it fails. + * If this happens within readlimit bytes, it allows the outer + * code to reset the stream and try another parser. + * + * @exception IOException if the stream has not been marked or if the + * mark has been invalidated. + * @see java.io.FilterInputStream#in + * @see java.io.FilterInputStream#mark(int) + */ + public synchronized void reset() throws IOException { + in.reset(); + } + + /** + * Tests if this input stream supports the mark + * and reset methods. + * This method + * simply performs in.markSupported(). + * + * @return true if this stream type supports the + * mark and reset method; + * false otherwise. + * @see java.io.FilterInputStream#in + * @see java.io.InputStream#mark(int) + * @see java.io.InputStream#reset() + */ + public boolean markSupported() { + return in.markSupported(); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/InputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/io/InputStream.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,370 @@ +/* + * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +/** + * This abstract class is the superclass of all classes representing + * an input stream of bytes. + * + *

Applications that need to define a subclass of InputStream + * must always provide a method that returns the next byte of input. + * + * @author Arthur van Hoff + * @see java.io.BufferedInputStream + * @see java.io.ByteArrayInputStream + * @see java.io.DataInputStream + * @see java.io.FilterInputStream + * @see java.io.InputStream#read() + * @see java.io.OutputStream + * @see java.io.PushbackInputStream + * @since JDK1.0 + */ +public abstract class InputStream implements Closeable { + + // SKIP_BUFFER_SIZE is used to determine the size of skipBuffer + private static final int SKIP_BUFFER_SIZE = 2048; + // skipBuffer is initialized in skip(long), if needed. + private static byte[] skipBuffer; + + /** + * Reads the next byte of data from the input stream. The value byte is + * returned as an int in the range 0 to + * 255. If no byte is available because the end of the stream + * has been reached, the value -1 is returned. This method + * blocks until input data is available, the end of the stream is detected, + * or an exception is thrown. + * + *

A subclass must provide an implementation of this method. + * + * @return the next byte of data, or -1 if the end of the + * stream is reached. + * @exception IOException if an I/O error occurs. + */ + public abstract int read() throws IOException; + + /** + * Reads some number of bytes from the input stream and stores them into + * the buffer array b. The number of bytes actually read is + * returned as an integer. This method blocks until input data is + * available, end of file is detected, or an exception is thrown. + * + *

If the length of b is zero, then no bytes are read and + * 0 is returned; otherwise, there is an attempt to read at + * least one byte. If no byte is available because the stream is at the + * end of the file, the value -1 is returned; otherwise, at + * least one byte is read and stored into b. + * + *

The first byte read is stored into element b[0], the + * next one into b[1], and so on. The number of bytes read is, + * at most, equal to the length of b. Let k be the + * number of bytes actually read; these bytes will be stored in elements + * b[0] through b[k-1], + * leaving elements b[k] through + * b[b.length-1] unaffected. + * + *

The read(b) method for class InputStream + * has the same effect as:

 read(b, 0, b.length) 
+ * + * @param b the buffer into which the data is read. + * @return the total number of bytes read into the buffer, or + * -1 if there is no more data because the end of + * the stream has been reached. + * @exception IOException If the first byte cannot be read for any reason + * other than the end of the file, if the input stream has been closed, or + * if some other I/O error occurs. + * @exception NullPointerException if b is null. + * @see java.io.InputStream#read(byte[], int, int) + */ + public int read(byte b[]) throws IOException { + return read(b, 0, b.length); + } + + /** + * Reads up to len bytes of data from the input stream into + * an array of bytes. An attempt is made to read as many as + * len bytes, but a smaller number may be read. + * The number of bytes actually read is returned as an integer. + * + *

This method blocks until input data is available, end of file is + * detected, or an exception is thrown. + * + *

If len is zero, then no bytes are read and + * 0 is returned; otherwise, there is an attempt to read at + * least one byte. If no byte is available because the stream is at end of + * file, the value -1 is returned; otherwise, at least one + * byte is read and stored into b. + * + *

The first byte read is stored into element b[off], the + * next one into b[off+1], and so on. The number of bytes read + * is, at most, equal to len. Let k be the number of + * bytes actually read; these bytes will be stored in elements + * b[off] through b[off+k-1], + * leaving elements b[off+k] through + * b[off+len-1] unaffected. + * + *

In every case, elements b[0] through + * b[off] and elements b[off+len] through + * b[b.length-1] are unaffected. + * + *

The read(b, off, len) method + * for class InputStream simply calls the method + * read() repeatedly. If the first such call results in an + * IOException, that exception is returned from the call to + * the read(b, off, len) method. If + * any subsequent call to read() results in a + * IOException, the exception is caught and treated as if it + * were end of file; the bytes read up to that point are stored into + * b and the number of bytes read before the exception + * occurred is returned. The default implementation of this method blocks + * until the requested amount of input data len has been read, + * end of file is detected, or an exception is thrown. Subclasses are encouraged + * to provide a more efficient implementation of this method. + * + * @param b the buffer into which the data is read. + * @param off the start offset in array b + * at which the data is written. + * @param len the maximum number of bytes to read. + * @return the total number of bytes read into the buffer, or + * -1 if there is no more data because the end of + * the stream has been reached. + * @exception IOException If the first byte cannot be read for any reason + * other than end of file, or if the input stream has been closed, or if + * some other I/O error occurs. + * @exception NullPointerException If b is null. + * @exception IndexOutOfBoundsException If off is negative, + * len is negative, or len is greater than + * b.length - off + * @see java.io.InputStream#read() + */ + public int read(byte b[], int off, int len) throws IOException { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + + int c = read(); + if (c == -1) { + return -1; + } + b[off] = (byte)c; + + int i = 1; + try { + for (; i < len ; i++) { + c = read(); + if (c == -1) { + break; + } + b[off + i] = (byte)c; + } + } catch (IOException ee) { + } + return i; + } + + /** + * Skips over and discards n bytes of data from this input + * stream. The skip method may, for a variety of reasons, end + * up skipping over some smaller number of bytes, possibly 0. + * This may result from any of a number of conditions; reaching end of file + * before n bytes have been skipped is only one possibility. + * The actual number of bytes skipped is returned. If n is + * negative, no bytes are skipped. + * + *

The skip method of this class creates a + * byte array and then repeatedly reads into it until n bytes + * have been read or the end of the stream has been reached. Subclasses are + * encouraged to provide a more efficient implementation of this method. + * For instance, the implementation may depend on the ability to seek. + * + * @param n the number of bytes to be skipped. + * @return the actual number of bytes skipped. + * @exception IOException if the stream does not support seek, + * or if some other I/O error occurs. + */ + public long skip(long n) throws IOException { + + long remaining = n; + int nr; + if (skipBuffer == null) + skipBuffer = new byte[SKIP_BUFFER_SIZE]; + + byte[] localSkipBuffer = skipBuffer; + + if (n <= 0) { + return 0; + } + + while (remaining > 0) { + nr = read(localSkipBuffer, 0, + (int) Math.min(SKIP_BUFFER_SIZE, remaining)); + if (nr < 0) { + break; + } + remaining -= nr; + } + + return n - remaining; + } + + /** + * Returns an estimate of the number of bytes that can be read (or + * skipped over) from this input stream without blocking by the next + * invocation of a method for this input stream. The next invocation + * might be the same thread or another thread. A single read or skip of this + * many bytes will not block, but may read or skip fewer bytes. + * + *

Note that while some implementations of {@code InputStream} will return + * the total number of bytes in the stream, many will not. It is + * never correct to use the return value of this method to allocate + * a buffer intended to hold all data in this stream. + * + *

A subclass' implementation of this method may choose to throw an + * {@link IOException} if this input stream has been closed by + * invoking the {@link #close()} method. + * + *

The {@code available} method for class {@code InputStream} always + * returns {@code 0}. + * + *

This method should be overridden by subclasses. + * + * @return an estimate of the number of bytes that can be read (or skipped + * over) from this input stream without blocking or {@code 0} when + * it reaches the end of the input stream. + * @exception IOException if an I/O error occurs. + */ + public int available() throws IOException { + return 0; + } + + /** + * Closes this input stream and releases any system resources associated + * with the stream. + * + *

The close method of InputStream does + * nothing. + * + * @exception IOException if an I/O error occurs. + */ + public void close() throws IOException {} + + /** + * Marks the current position in this input stream. A subsequent call to + * the reset method repositions this stream at the last marked + * position so that subsequent reads re-read the same bytes. + * + *

The readlimit arguments tells this input stream to + * allow that many bytes to be read before the mark position gets + * invalidated. + * + *

The general contract of mark is that, if the method + * markSupported returns true, the stream somehow + * remembers all the bytes read after the call to mark and + * stands ready to supply those same bytes again if and whenever the method + * reset is called. However, the stream is not required to + * remember any data at all if more than readlimit bytes are + * read from the stream before reset is called. + * + *

Marking a closed stream should not have any effect on the stream. + * + *

The mark method of InputStream does + * nothing. + * + * @param readlimit the maximum limit of bytes that can be read before + * the mark position becomes invalid. + * @see java.io.InputStream#reset() + */ + public synchronized void mark(int readlimit) {} + + /** + * Repositions this stream to the position at the time the + * mark method was last called on this input stream. + * + *

The general contract of reset is: + * + *

    + * + *
  • If the method markSupported returns + * true, then: + * + *
    • If the method mark has not been called since + * the stream was created, or the number of bytes read from the stream + * since mark was last called is larger than the argument + * to mark at that last call, then an + * IOException might be thrown. + * + *
    • If such an IOException is not thrown, then the + * stream is reset to a state such that all the bytes read since the + * most recent call to mark (or since the start of the + * file, if mark has not been called) will be resupplied + * to subsequent callers of the read method, followed by + * any bytes that otherwise would have been the next input data as of + * the time of the call to reset.
    + * + *
  • If the method markSupported returns + * false, then: + * + *
    • The call to reset may throw an + * IOException. + * + *
    • If an IOException is not thrown, then the stream + * is reset to a fixed state that depends on the particular type of the + * input stream and how it was created. The bytes that will be supplied + * to subsequent callers of the read method depend on the + * particular type of the input stream.
+ * + *

The method reset for class InputStream + * does nothing except throw an IOException. + * + * @exception IOException if this stream has not been marked or if the + * mark has been invalidated. + * @see java.io.InputStream#mark(int) + * @see java.io.IOException + */ + public synchronized void reset() throws IOException { + throw new IOException("mark/reset not supported"); + } + + /** + * Tests if this input stream supports the mark and + * reset methods. Whether or not mark and + * reset are supported is an invariant property of a + * particular input stream instance. The markSupported method + * of InputStream returns false. + * + * @return true if this stream instance supports the mark + * and reset methods; false otherwise. + * @see java.io.InputStream#mark(int) + * @see java.io.InputStream#reset() + */ + public boolean markSupported() { + return false; + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/PushbackInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/io/PushbackInputStream.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,388 @@ +/* + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +/** + * A PushbackInputStream adds + * functionality to another input stream, namely + * the ability to "push back" or "unread" + * one byte. This is useful in situations where + * it is convenient for a fragment of code + * to read an indefinite number of data bytes + * that are delimited by a particular byte + * value; after reading the terminating byte, + * the code fragment can "unread" it, so that + * the next read operation on the input stream + * will reread the byte that was pushed back. + * For example, bytes representing the characters + * constituting an identifier might be terminated + * by a byte representing an operator character; + * a method whose job is to read just an identifier + * can read until it sees the operator and + * then push the operator back to be re-read. + * + * @author David Connelly + * @author Jonathan Payne + * @since JDK1.0 + */ +public +class PushbackInputStream extends FilterInputStream { + /** + * The pushback buffer. + * @since JDK1.1 + */ + protected byte[] buf; + + /** + * The position within the pushback buffer from which the next byte will + * be read. When the buffer is empty, pos is equal to + * buf.length; when the buffer is full, pos is + * equal to zero. + * + * @since JDK1.1 + */ + protected int pos; + + /** + * Check to make sure that this stream has not been closed + */ + private void ensureOpen() throws IOException { + if (in == null) + throw new IOException("Stream closed"); + } + + /** + * Creates a PushbackInputStream + * with a pushback buffer of the specified size, + * and saves its argument, the input stream + * in, for later use. Initially, + * there is no pushed-back byte (the field + * pushBack is initialized to + * -1). + * + * @param in the input stream from which bytes will be read. + * @param size the size of the pushback buffer. + * @exception IllegalArgumentException if size is <= 0 + * @since JDK1.1 + */ + public PushbackInputStream(InputStream in, int size) { + super(in); + if (size <= 0) { + throw new IllegalArgumentException("size <= 0"); + } + this.buf = new byte[size]; + this.pos = size; + } + + /** + * Creates a PushbackInputStream + * and saves its argument, the input stream + * in, for later use. Initially, + * there is no pushed-back byte (the field + * pushBack is initialized to + * -1). + * + * @param in the input stream from which bytes will be read. + */ + public PushbackInputStream(InputStream in) { + this(in, 1); + } + + /** + * Reads the next byte of data from this input stream. The value + * byte is returned as an int in the range + * 0 to 255. If no byte is available + * because the end of the stream has been reached, the value + * -1 is returned. This method blocks until input data + * is available, the end of the stream is detected, or an exception + * is thrown. + * + *

This method returns the most recently pushed-back byte, if there is + * one, and otherwise calls the read method of its underlying + * input stream and returns whatever value that method returns. + * + * @return the next byte of data, or -1 if the end of the + * stream has been reached. + * @exception IOException if this input stream has been closed by + * invoking its {@link #close()} method, + * or an I/O error occurs. + * @see java.io.InputStream#read() + */ + public int read() throws IOException { + ensureOpen(); + if (pos < buf.length) { + return buf[pos++] & 0xff; + } + return super.read(); + } + + /** + * Reads up to len bytes of data from this input stream into + * an array of bytes. This method first reads any pushed-back bytes; after + * that, if fewer than len bytes have been read then it + * reads from the underlying input stream. If len is not zero, the method + * blocks until at least 1 byte of input is available; otherwise, no + * bytes are read and 0 is returned. + * + * @param b the buffer into which the data is read. + * @param off the start offset in the destination array b + * @param len the maximum number of bytes read. + * @return the total number of bytes read into the buffer, or + * -1 if there is no more data because the end of + * the stream has been reached. + * @exception NullPointerException If b is null. + * @exception IndexOutOfBoundsException If off is negative, + * len is negative, or len is greater than + * b.length - off + * @exception IOException if this input stream has been closed by + * invoking its {@link #close()} method, + * or an I/O error occurs. + * @see java.io.InputStream#read(byte[], int, int) + */ + public int read(byte[] b, int off, int len) throws IOException { + ensureOpen(); + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + + int avail = buf.length - pos; + if (avail > 0) { + if (len < avail) { + avail = len; + } + arraycopy(buf, pos, b, off, avail); + pos += avail; + off += avail; + len -= avail; + } + if (len > 0) { + len = super.read(b, off, len); + if (len == -1) { + return avail == 0 ? -1 : avail; + } + return avail + len; + } + return avail; + } + + /** + * Pushes back a byte by copying it to the front of the pushback buffer. + * After this method returns, the next byte to be read will have the value + * (byte)b. + * + * @param b the int value whose low-order + * byte is to be pushed back. + * @exception IOException If there is not enough room in the pushback + * buffer for the byte, or this input stream has been closed by + * invoking its {@link #close()} method. + */ + public void unread(int b) throws IOException { + ensureOpen(); + if (pos == 0) { + throw new IOException("Push back buffer is full"); + } + buf[--pos] = (byte)b; + } + + /** + * Pushes back a portion of an array of bytes by copying it to the front + * of the pushback buffer. After this method returns, the next byte to be + * read will have the value b[off], the byte after that will + * have the value b[off+1], and so forth. + * + * @param b the byte array to push back. + * @param off the start offset of the data. + * @param len the number of bytes to push back. + * @exception IOException If there is not enough room in the pushback + * buffer for the specified number of bytes, + * or this input stream has been closed by + * invoking its {@link #close()} method. + * @since JDK1.1 + */ + public void unread(byte[] b, int off, int len) throws IOException { + ensureOpen(); + if (len > pos) { + throw new IOException("Push back buffer is full"); + } + pos -= len; + arraycopy(b, off, buf, pos, len); + } + + /** + * Pushes back an array of bytes by copying it to the front of the + * pushback buffer. After this method returns, the next byte to be read + * will have the value b[0], the byte after that will have the + * value b[1], and so forth. + * + * @param b the byte array to push back + * @exception IOException If there is not enough room in the pushback + * buffer for the specified number of bytes, + * or this input stream has been closed by + * invoking its {@link #close()} method. + * @since JDK1.1 + */ + public void unread(byte[] b) throws IOException { + unread(b, 0, b.length); + } + + /** + * Returns an estimate of the number of bytes that can be read (or + * skipped over) from this input stream without blocking by the next + * invocation of a method for this input stream. The next invocation might be + * the same thread or another thread. A single read or skip of this + * many bytes will not block, but may read or skip fewer bytes. + * + *

The method returns the sum of the number of bytes that have been + * pushed back and the value returned by {@link + * java.io.FilterInputStream#available available}. + * + * @return the number of bytes that can be read (or skipped over) from + * the input stream without blocking. + * @exception IOException if this input stream has been closed by + * invoking its {@link #close()} method, + * or an I/O error occurs. + * @see java.io.FilterInputStream#in + * @see java.io.InputStream#available() + */ + public int available() throws IOException { + ensureOpen(); + int n = buf.length - pos; + int avail = super.available(); + return n > (Integer.MAX_VALUE - avail) + ? Integer.MAX_VALUE + : n + avail; + } + + /** + * Skips over and discards n bytes of data from this + * input stream. The skip method may, for a variety of + * reasons, end up skipping over some smaller number of bytes, + * possibly zero. If n is negative, no bytes are skipped. + * + *

The skip method of PushbackInputStream + * first skips over the bytes in the pushback buffer, if any. It then + * calls the skip method of the underlying input stream if + * more bytes need to be skipped. The actual number of bytes skipped + * is returned. + * + * @param n {@inheritDoc} + * @return {@inheritDoc} + * @exception IOException if the stream does not support seek, + * or the stream has been closed by + * invoking its {@link #close()} method, + * or an I/O error occurs. + * @see java.io.FilterInputStream#in + * @see java.io.InputStream#skip(long n) + * @since 1.2 + */ + public long skip(long n) throws IOException { + ensureOpen(); + if (n <= 0) { + return 0; + } + + long pskip = buf.length - pos; + if (pskip > 0) { + if (n < pskip) { + pskip = n; + } + pos += pskip; + n -= pskip; + } + if (n > 0) { + pskip += super.skip(n); + } + return pskip; + } + + /** + * Tests if this input stream supports the mark and + * reset methods, which it does not. + * + * @return false, since this class does not support the + * mark and reset methods. + * @see java.io.InputStream#mark(int) + * @see java.io.InputStream#reset() + */ + public boolean markSupported() { + return false; + } + + /** + * Marks the current position in this input stream. + * + *

The mark method of PushbackInputStream + * does nothing. + * + * @param readlimit the maximum limit of bytes that can be read before + * the mark position becomes invalid. + * @see java.io.InputStream#reset() + */ + public synchronized void mark(int readlimit) { + } + + /** + * Repositions this stream to the position at the time the + * mark method was last called on this input stream. + * + *

The method reset for class + * PushbackInputStream does nothing except throw an + * IOException. + * + * @exception IOException if this method is invoked. + * @see java.io.InputStream#mark(int) + * @see java.io.IOException + */ + public synchronized void reset() throws IOException { + throw new IOException("mark/reset not supported"); + } + + /** + * Closes this input stream and releases any system resources + * associated with the stream. + * Once the stream has been closed, further read(), unread(), + * available(), reset(), or skip() invocations will throw an IOException. + * Closing a previously closed stream has no effect. + * + * @exception IOException if an I/O error occurs. + */ + public synchronized void close() throws IOException { + if (in == null) + return; + in.close(); + in = null; + buf = null; + } + static void arraycopy(byte[] value, int srcBegin, byte[] dst, int dstBegin, int count) { + while (count-- > 0) { + dst[dstBegin++] = value[srcBegin++]; + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/io/UTFDataFormatException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/io/UTFDataFormatException.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.io; + +/** + * Signals that a malformed string in + * modified UTF-8 + * format has been read in a data + * input stream or by any class that implements the data input + * interface. + * See the + * DataInput + * class description for the format in + * which modified UTF-8 strings are read and written. + * + * @author Frank Yellin + * @see java.io.DataInput + * @see java.io.DataInputStream#readUTF(java.io.DataInput) + * @see java.io.IOException + * @since JDK1.0 + */ +public +class UTFDataFormatException extends IOException { + private static final long serialVersionUID = 420743449228280612L; + + /** + * Constructs a UTFDataFormatException with + * null as its error detail message. + */ + public UTFDataFormatException() { + super(); + } + + /** + * Constructs a UTFDataFormatException with the + * specified detail message. The string s can be + * retrieved later by the + * {@link java.lang.Throwable#getMessage} + * method of class java.lang.Throwable. + * + * @param s the detail message. + */ + public UTFDataFormatException(String s) { + super(s); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/AbstractStringBuilder.java --- a/emul/src/main/java/java/lang/AbstractStringBuilder.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/AbstractStringBuilder.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,8 +25,6 @@ package java.lang; -import org.apidesign.bck2brwsr.core.JavaScriptBody; - /** * A mutable sequence of characters. *

@@ -126,7 +124,7 @@ throw new OutOfMemoryError(); newCapacity = Integer.MAX_VALUE; } - value = String.copyOf(value, newCapacity); + value = copyOf(value, newCapacity); } /** @@ -138,7 +136,7 @@ */ public void trimToSize() { if (count < value.length) { - value = String.copyOf(value, count); + value = copyOf(value, count); } } @@ -352,7 +350,7 @@ throw new StringIndexOutOfBoundsException(srcEnd); if (srcBegin > srcEnd) throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); - String.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); + arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); } /** @@ -502,7 +500,7 @@ public AbstractStringBuilder append(char[] str) { int len = str.length; ensureCapacityInternal(count + len); - String.arraycopy(str, 0, value, count, len); + arraycopy(str, 0, value, count, len); count += len; return this; } @@ -532,7 +530,7 @@ public AbstractStringBuilder append(char str[], int offset, int len) { if (len > 0) // let arraycopy report AIOOBE for len < 0 ensureCapacityInternal(count + len); - String.arraycopy(str, offset, value, count, len); + arraycopy(str, offset, value, count, len); count += len; return this; } @@ -600,22 +598,8 @@ * @param i an {@code int}. * @return a reference to this object. */ - @JavaScriptBody( - args={ "self", "i" }, - body="return java_lang_AbstractStringBuilder_appendLjava_lang_AbstractStringBuilderLjava_lang_String(self,i.toString());" - ) public AbstractStringBuilder append(int i) { - if (i == Integer.MIN_VALUE) { - append("-2147483648"); - return this; - } - int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1 - : Integer.stringSize(i); - int spaceNeeded = count + appendedLength; - ensureCapacityInternal(spaceNeeded); - Integer.getChars(i, spaceNeeded, value); - count = spaceNeeded; - return this; + return append(Integer.toString(i)); } /** @@ -657,7 +641,7 @@ * @return a reference to this object. */ public AbstractStringBuilder append(float f) { - throw new UnsupportedOperationException(); + return append(Float.toString(f)); } /** @@ -673,7 +657,7 @@ * @return a reference to this object. */ public AbstractStringBuilder append(double d) { - throw new UnsupportedOperationException(); + return append(Double.toString(d)); } /** @@ -699,7 +683,7 @@ throw new StringIndexOutOfBoundsException(); int len = end - start; if (len > 0) { - String.arraycopy(value, start+len, value, start, count-end); + arraycopy(value, start+len, value, start, count-end); count -= len; } return this; @@ -761,7 +745,7 @@ public AbstractStringBuilder deleteCharAt(int index) { if ((index < 0) || (index >= count)) throw new StringIndexOutOfBoundsException(index); - String.arraycopy(value, index+1, value, index, count-index-1); + arraycopy(value, index+1, value, index, count-index-1); count--; return this; } @@ -799,7 +783,7 @@ int newCount = count + len - (end - start); ensureCapacityInternal(newCount); - String.arraycopy(value, end, value, start + len, count - end); + arraycopy(value, end, value, start + len, count - end); str.getChars(value, start); count = newCount; return this; @@ -905,8 +889,8 @@ "offset " + offset + ", len " + len + ", str.length " + str.length); ensureCapacityInternal(count + len); - String.arraycopy(value, index, value, index + len, count - index); - String.arraycopy(str, offset, value, index, len); + arraycopy(value, index, value, index + len, count - index); + arraycopy(str, offset, value, index, len); count += len; return this; } @@ -972,7 +956,7 @@ str = "null"; int len = str.length(); ensureCapacityInternal(count + len); - String.arraycopy(value, offset, value, offset + len, count - offset); + arraycopy(value, offset, value, offset + len, count - offset); str.getChars(value, offset); count += len; return this; @@ -1007,8 +991,8 @@ throw new StringIndexOutOfBoundsException(offset); int len = str.length; ensureCapacityInternal(count + len); - String.arraycopy(value, offset, value, offset + len, count - offset); - String.arraycopy(str, 0, value, offset, len); + arraycopy(value, offset, value, offset + len, count - offset); + arraycopy(str, 0, value, offset, len); count += len; return this; } @@ -1098,7 +1082,7 @@ + s.length()); int len = end - start; ensureCapacityInternal(count + len); - String.arraycopy(value, dstOffset, value, dstOffset + len, + arraycopy(value, dstOffset, value, dstOffset + len, count - dstOffset); for (int i=start; inull. */ public int indexOf(String str, int fromIndex) { - return String.indexOf(value, 0, count, - str.toCharArray(), 0, str.length(), fromIndex); + return toString().indexOf(str, fromIndex); } /** @@ -1405,4 +1388,37 @@ return value; } + static char[] copyOfRange(char[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) { + throw new IllegalArgumentException(from + " > " + to); + } + char[] copy = new char[newLength]; + arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); + return copy; + } + + static void arraycopy(char[] value, int srcBegin, char[] dst, int dstBegin, int count) { + if (srcBegin < dstBegin) { + while (count-- > 0) { + dst[dstBegin + count] = value[srcBegin + count]; + } + } else { + while (count-- > 0) { + dst[dstBegin++] = value[srcBegin++]; + } + } + } + + // access system property + static String getProperty(String nm) { + return null; + } + + static char[] copyOf(char[] original, int newLength) { + char[] copy = new char[newLength]; + arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); + return copy; + } + } diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/AutoCloseable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/AutoCloseable.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * A resource that must be closed when it is no longer needed. + * + * @author Josh Bloch + * @since 1.7 + */ +public interface AutoCloseable { + /** + * Closes this resource, relinquishing any underlying resources. + * This method is invoked automatically on objects managed by the + * {@code try}-with-resources statement. + * + *

While this interface method is declared to throw {@code + * Exception}, implementers are strongly encouraged to + * declare concrete implementations of the {@code close} method to + * throw more specific exceptions, or to throw no exception at all + * if the close operation cannot fail. + * + *

Implementers of this interface are also strongly advised + * to not have the {@code close} method throw {@link + * InterruptedException}. + * + * This exception interacts with a thread's interrupted status, + * and runtime misbehavior is likely to occur if an {@code + * InterruptedException} is {@linkplain Throwable#addSuppressed + * suppressed}. + * + * More generally, if it would cause problems for an + * exception to be suppressed, the {@code AutoCloseable.close} + * method should not throw it. + * + *

Note that unlike the {@link java.io.Closeable#close close} + * method of {@link java.io.Closeable}, this {@code close} method + * is not required to be idempotent. In other words, + * calling this {@code close} method more than once may have some + * visible side effect, unlike {@code Closeable.close} which is + * required to have no effect if called more than once. + * + * However, implementers of this interface are strongly encouraged + * to make their {@code close} methods idempotent. + * + * @throws Exception if this resource cannot be closed + */ + void close() throws Exception; +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Boolean.java --- a/emul/src/main/java/java/lang/Boolean.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Boolean.java Wed Jan 23 20:16:48 2013 +0100 @@ -235,7 +235,7 @@ public static boolean getBoolean(String name) { boolean result = false; try { - result = toBoolean(String.getProperty(name)); + result = toBoolean(AbstractStringBuilder.getProperty(name)); } catch (IllegalArgumentException e) { } catch (NullPointerException e) { } diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Character.java --- a/emul/src/main/java/java/lang/Character.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Character.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,6 +25,8 @@ package java.lang; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * The {@code Character} class wraps a value of the primitive * type {@code char} in an object. An object of type @@ -1525,7 +1527,7 @@ * @see Character#getType(char) */ public static boolean isLowerCase(char ch) { - throw new UnsupportedOperationException(); + return ch == toLowerCase(ch); } /** @@ -1560,7 +1562,7 @@ * @since 1.0 */ public static boolean isUpperCase(char ch) { - throw new UnsupportedOperationException(); + return ch == toUpperCase(ch); } /** @@ -1676,7 +1678,7 @@ * @see Character#getType(char) */ public static boolean isDigit(char ch) { - return isDigit((int)ch); + return String.valueOf(ch).matches("\\d"); } /** @@ -1710,8 +1712,11 @@ * @since 1.5 */ public static boolean isDigit(int codePoint) { - return getType(codePoint) == Character.DECIMAL_DIGIT_NUMBER; + return fromCodeChars(codePoint).matches("\\d"); } + + @JavaScriptBody(args = "c", body = "return String.fromCharCode(c);") + private native static String fromCodeChars(int codePoint); /** * Determines if a character is defined in Unicode. @@ -1802,7 +1807,7 @@ * @see Character#isUpperCase(char) */ public static boolean isLetter(char ch) { - return isLetter((int)ch); + return String.valueOf(ch).matches("\\w") && !isDigit(ch); } /** @@ -1835,12 +1840,7 @@ * @since 1.5 */ public static boolean isLetter(int codePoint) { - return ((((1 << Character.UPPERCASE_LETTER) | - (1 << Character.LOWERCASE_LETTER) | - (1 << Character.TITLECASE_LETTER) | - (1 << Character.MODIFIER_LETTER) | - (1 << Character.OTHER_LETTER)) >> getType(codePoint)) & 1) - != 0; + return fromCodeChars(codePoint).matches("\\w") && !isDigit(codePoint); } /** @@ -1868,7 +1868,7 @@ * @since 1.0.2 */ public static boolean isLetterOrDigit(char ch) { - return isLetterOrDigit((int)ch); + return String.valueOf(ch).matches("\\w"); } /** @@ -1889,13 +1889,7 @@ * @since 1.5 */ public static boolean isLetterOrDigit(int codePoint) { - return ((((1 << Character.UPPERCASE_LETTER) | - (1 << Character.LOWERCASE_LETTER) | - (1 << Character.TITLECASE_LETTER) | - (1 << Character.MODIFIER_LETTER) | - (1 << Character.OTHER_LETTER) | - (1 << Character.DECIMAL_DIGIT_NUMBER)) >> getType(codePoint)) & 1) - != 0; + return fromCodeChars(codePoint).matches("\\w"); } static int getType(int x) { @@ -1930,7 +1924,7 @@ * @see String#toLowerCase() */ public static char toLowerCase(char ch) { - throw new UnsupportedOperationException(); + return String.valueOf(ch).toLowerCase().charAt(0); } /** @@ -1961,7 +1955,7 @@ * @see String#toUpperCase() */ public static char toUpperCase(char ch) { - throw new UnsupportedOperationException(); + return String.valueOf(ch).toUpperCase().charAt(0); } /** diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Class.java --- a/emul/src/main/java/java/lang/Class.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Class.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,7 +25,15 @@ package java.lang; +import java.io.ByteArrayInputStream; +import org.apidesign.bck2brwsr.emul.AnnotationImpl; +import java.io.InputStream; import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.TypeVariable; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.emul.MethodImpl; /** * Instances of the class {@code Class} represent classes and @@ -73,10 +81,10 @@ * @since JDK1.0 */ public final - class Class implements java.io.Serializable { -// java.lang.reflect.GenericDeclaration, -// java.lang.reflect.Type, -// java.lang.reflect.AnnotatedElement { + class Class implements java.io.Serializable, + java.lang.reflect.GenericDeclaration, + java.lang.reflect.Type, + java.lang.reflect.AnnotatedElement { private static final int ANNOTATION= 0x00002000; private static final int ENUM = 0x00004000; private static final int SYNTHETIC = 0x00001000; @@ -137,9 +145,31 @@ * @exception ClassNotFoundException if the class cannot be located */ public static Class forName(String className) - throws ClassNotFoundException { - throw new UnsupportedOperationException(); + throws ClassNotFoundException { + if (className.startsWith("[")) { + Class arrType = defineArray(className); + Class c = arrType; + while (c != null && c.isArray()) { + c = c.getComponentType0(); // verify component type is sane + } + return arrType; + } + Class c = loadCls(className, className.replace('.', '_')); + if (c == null) { + throw new ClassNotFoundException(className); + } + return c; } + + @JavaScriptBody(args = {"n", "c" }, body = + "if (vm[c]) return vm[c].$class;\n" + + "if (vm.loadClass) {\n" + + " vm.loadClass(n);\n" + + " if (vm[c]) return vm[c].$class;\n" + + "}\n" + + "return null;" + ) + private static native Class loadCls(String n, String c); /** @@ -189,10 +219,32 @@ * * */ + @JavaScriptBody(args = { "self", "illegal" }, body = + "\nvar c = self.cnstr;" + + "\nif (c['cons__V']) {" + + "\n if ((c.cons__V.access & 0x1) != 0) {" + + "\n var inst = c();" + + "\n c.cons__V.call(inst);" + + "\n return inst;" + + "\n }" + + "\n return illegal;" + + "\n}" + + "\nreturn null;" + ) + private static native Object newInstance0(Class self, Object illegal); + public T newInstance() throws InstantiationException, IllegalAccessException { - throw new UnsupportedOperationException("Should be somehow supported"); + Object illegal = new Object(); + Object inst = newInstance0(this, illegal); + if (inst == null) { + throw new InstantiationException(getName()); + } + if (inst == illegal) { + throw new IllegalAccessException(); + } + return (T)inst; } /** @@ -225,7 +277,15 @@ * * @since JDK1.1 */ - public native boolean isInstance(Object obj); + public boolean isInstance(Object obj) { + String prop = "$instOf_" + getName().replace('.', '_'); + return hasProperty(obj, prop); + } + + @JavaScriptBody(args = { "who", "prop" }, body = + "if (who[prop]) return true; else return false;" + ) + private static native boolean hasProperty(Object who, String prop); /** @@ -262,7 +322,12 @@ * @return {@code true} if this object represents an interface; * {@code false} otherwise. */ - public native boolean isInterface(); + public boolean isInterface() { + return (getAccess() & 0x200) != 0; + } + + @JavaScriptBody(args = {}, body = "return this.access;") + private native int getAccess(); /** @@ -272,7 +337,9 @@ * {@code false} otherwise. * @since JDK1.1 */ - public native boolean isArray(); + public boolean isArray() { + return hasProperty(this, "array"); // NOI18N + } /** @@ -303,6 +370,10 @@ * @see java.lang.Void#TYPE * @since JDK1.1 */ + @JavaScriptBody(args = {}, body = + "if (this.primitive) return true;" + + "else return false;" + ) public native boolean isPrimitive(); /** @@ -381,13 +452,32 @@ * represented by this object. */ public String getName() { - throw new UnsupportedOperationException(); -// String name = this.name; -// if (name == null) -// this.name = name = getName0(); -// return name; + return jvmName().replace('/', '.'); } + @JavaScriptBody(args = {}, body = "return this.jvmName;") + private native String jvmName(); + + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws java.lang.reflect.GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * The Java™ Virtual Machine Specification + * @since 1.5 + */ + public TypeVariable>[] getTypeParameters() { + throw new UnsupportedOperationException(); + } + /** * Returns the {@code Class} representing the superclass of the entity * (class, interface, primitive type or void) represented by this @@ -399,6 +489,7 @@ * * @return the superclass of the class represented by this object. */ + @JavaScriptBody(args = {}, body = "return this.superclass;") public native Class getSuperclass(); /** @@ -444,37 +535,290 @@ * @since 1.5 */ public String getSimpleName() { - throw new UnsupportedOperationException(); -//// if (isArray()) -//// return getComponentType().getSimpleName()+"[]"; -//// -//// String simpleName = getSimpleBinaryName(); -//// if (simpleName == null) { // top level class -//// simpleName = getName(); -//// return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name -//// } -//// // According to JLS3 "Binary Compatibility" (13.1) the binary -//// // name of non-package classes (not top level) is the binary -//// // name of the immediately enclosing class followed by a '$' followed by: -//// // (for nested and inner classes): the simple name. -//// // (for local classes): 1 or more digits followed by the simple name. -//// // (for anonymous classes): 1 or more digits. -//// -//// // Since getSimpleBinaryName() will strip the binary name of -//// // the immediatly enclosing class, we are now looking at a -//// // string that matches the regular expression "\$[0-9]*" -//// // followed by a simple name (considering the simple of an -//// // anonymous class to be the empty string). -//// -//// // Remove leading "\$[0-9]*" from the name -//// int length = simpleName.length(); -//// if (length < 1 || simpleName.charAt(0) != '$') -//// throw new InternalError("Malformed class name"); -//// int index = 1; -//// while (index < length && isAsciiDigit(simpleName.charAt(index))) -//// index++; -//// // Eventually, this is the empty string iff this is an anonymous class -//// return simpleName.substring(index); + if (isArray()) + return getComponentType().getSimpleName()+"[]"; + + String simpleName = getSimpleBinaryName(); + if (simpleName == null) { // top level class + simpleName = getName(); + return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name + } + // According to JLS3 "Binary Compatibility" (13.1) the binary + // name of non-package classes (not top level) is the binary + // name of the immediately enclosing class followed by a '$' followed by: + // (for nested and inner classes): the simple name. + // (for local classes): 1 or more digits followed by the simple name. + // (for anonymous classes): 1 or more digits. + + // Since getSimpleBinaryName() will strip the binary name of + // the immediatly enclosing class, we are now looking at a + // string that matches the regular expression "\$[0-9]*" + // followed by a simple name (considering the simple of an + // anonymous class to be the empty string). + + // Remove leading "\$[0-9]*" from the name + int length = simpleName.length(); + if (length < 1 || simpleName.charAt(0) != '$') + throw new IllegalStateException("Malformed class name"); + int index = 1; + while (index < length && isAsciiDigit(simpleName.charAt(index))) + index++; + // Eventually, this is the empty string iff this is an anonymous class + return simpleName.substring(index); + } + + /** + * Returns the "simple binary name" of the underlying class, i.e., + * the binary name without the leading enclosing class name. + * Returns {@code null} if the underlying class is a top level + * class. + */ + private String getSimpleBinaryName() { + Class enclosingClass = null; // XXX getEnclosingClass(); + if (enclosingClass == null) // top level class + return null; + // Otherwise, strip the enclosing class' name + try { + return getName().substring(enclosingClass.getName().length()); + } catch (IndexOutOfBoundsException ex) { + throw new IllegalStateException("Malformed class name"); + } + } + + /** + * Returns an array containing {@code Field} objects reflecting all + * the accessible public fields of the class or interface represented by + * this {@code Class} object. The elements in the array returned are + * not sorted and are not in any particular order. This method returns an + * array of length 0 if the class or interface has no accessible public + * fields, or if it represents an array class, a primitive type, or void. + * + *

Specifically, if this {@code Class} object represents a class, + * this method returns the public fields of this class and of all its + * superclasses. If this {@code Class} object represents an + * interface, this method returns the fields of this interface and of all + * its superinterfaces. + * + *

The implicit length field for array class is not reflected by this + * method. User code should use the methods of class {@code Array} to + * manipulate arrays. + * + *

See The Java Language Specification, sections 8.2 and 8.3. + * + * @return the array of {@code Field} objects representing the + * public fields + * @exception SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • invocation of + * {@link SecurityManager#checkMemberAccess + * s.checkMemberAccess(this, Member.PUBLIC)} denies + * access to the fields within this class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + */ + public Field[] getFields() throws SecurityException { + throw new SecurityException(); + } + + /** + * Returns an array containing {@code Method} objects reflecting all + * the public member methods of the class or interface represented + * by this {@code Class} object, including those declared by the class + * or interface and those inherited from superclasses and + * superinterfaces. Array classes return all the (public) member methods + * inherited from the {@code Object} class. The elements in the array + * returned are not sorted and are not in any particular order. This + * method returns an array of length 0 if this {@code Class} object + * represents a class or interface that has no public member methods, or if + * this {@code Class} object represents a primitive type or void. + * + *

The class initialization method {@code } is not + * included in the returned array. If the class declares multiple public + * member methods with the same parameter types, they are all included in + * the returned array. + * + *

See The Java Language Specification, sections 8.2 and 8.4. + * + * @return the array of {@code Method} objects representing the + * public methods of this class + * @exception SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • invocation of + * {@link SecurityManager#checkMemberAccess + * s.checkMemberAccess(this, Member.PUBLIC)} denies + * access to the methods within this class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + */ + public Method[] getMethods() throws SecurityException { + return MethodImpl.findMethods(this, 0x01); + } + + /** + * Returns a {@code Field} object that reflects the specified public + * member field of the class or interface represented by this + * {@code Class} object. The {@code name} parameter is a + * {@code String} specifying the simple name of the desired field. + * + *

The field to be reflected is determined by the algorithm that + * follows. Let C be the class represented by this object: + *

    + *
  1. If C declares a public field with the name specified, that is the + * field to be reflected.
  2. + *
  3. If no field was found in step 1 above, this algorithm is applied + * recursively to each direct superinterface of C. The direct + * superinterfaces are searched in the order they were declared.
  4. + *
  5. If no field was found in steps 1 and 2 above, and C has a + * superclass S, then this algorithm is invoked recursively upon S. + * If C has no superclass, then a {@code NoSuchFieldException} + * is thrown.
  6. + *
+ * + *

See The Java Language Specification, sections 8.2 and 8.3. + * + * @param name the field name + * @return the {@code Field} object of this class specified by + * {@code name} + * @exception NoSuchFieldException if a field with the specified name is + * not found. + * @exception NullPointerException if {@code name} is {@code null} + * @exception SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • invocation of + * {@link SecurityManager#checkMemberAccess + * s.checkMemberAccess(this, Member.PUBLIC)} denies + * access to the field + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + */ + public Field getField(String name) + throws SecurityException { + throw new SecurityException(); + } + + + /** + * Returns a {@code Method} object that reflects the specified public + * member method of the class or interface represented by this + * {@code Class} object. The {@code name} parameter is a + * {@code String} specifying the simple name of the desired method. The + * {@code parameterTypes} parameter is an array of {@code Class} + * objects that identify the method's formal parameter types, in declared + * order. If {@code parameterTypes} is {@code null}, it is + * treated as if it were an empty array. + * + *

If the {@code name} is "{@code };"or "{@code }" a + * {@code NoSuchMethodException} is raised. Otherwise, the method to + * be reflected is determined by the algorithm that follows. Let C be the + * class represented by this object: + *

    + *
  1. C is searched for any matching methods. If no matching + * method is found, the algorithm of step 1 is invoked recursively on + * the superclass of C.
  2. + *
  3. If no method was found in step 1 above, the superinterfaces of C + * are searched for a matching method. If any such method is found, it + * is reflected.
  4. + *
+ * + * To find a matching method in a class C:  If C declares exactly one + * public method with the specified name and exactly the same formal + * parameter types, that is the method reflected. If more than one such + * method is found in C, and one of these methods has a return type that is + * more specific than any of the others, that method is reflected; + * otherwise one of the methods is chosen arbitrarily. + * + *

Note that there may be more than one matching method in a + * class because while the Java language forbids a class to + * declare multiple methods with the same signature but different + * return types, the Java virtual machine does not. This + * increased flexibility in the virtual machine can be used to + * implement various language features. For example, covariant + * returns can be implemented with {@linkplain + * java.lang.reflect.Method#isBridge bridge methods}; the bridge + * method and the method being overridden would have the same + * signature but different return types. + * + *

See The Java Language Specification, sections 8.2 and 8.4. + * + * @param name the name of the method + * @param parameterTypes the list of parameters + * @return the {@code Method} object that matches the specified + * {@code name} and {@code parameterTypes} + * @exception NoSuchMethodException if a matching method is not found + * or if the name is "<init>"or "<clinit>". + * @exception NullPointerException if {@code name} is {@code null} + * @exception SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

    + * + *
  • invocation of + * {@link SecurityManager#checkMemberAccess + * s.checkMemberAccess(this, Member.PUBLIC)} denies + * access to the method + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + */ + public Method getMethod(String name, Class... parameterTypes) + throws SecurityException, NoSuchMethodException { + Method m = MethodImpl.findMethod(this, name, parameterTypes); + if (m == null) { + StringBuilder sb = new StringBuilder(); + sb.append(getName()).append('.').append(name).append('('); + String sep = ""; + for (int i = 0; i < parameterTypes.length; i++) { + sb.append(sep).append(parameterTypes[i].getName()); + sep = ", "; + } + sb.append(')'); + throw new NoSuchMethodException(sb.toString()); + } + return m; } /** @@ -496,25 +840,25 @@ * @since 1.5 */ public String getCanonicalName() { - throw new UnsupportedOperationException(); -// if (isArray()) { -// String canonicalName = getComponentType().getCanonicalName(); -// if (canonicalName != null) -// return canonicalName + "[]"; -// else -// return null; -// } + if (isArray()) { + String canonicalName = getComponentType().getCanonicalName(); + if (canonicalName != null) + return canonicalName + "[]"; + else + return null; + } // if (isLocalOrAnonymousClass()) // return null; // Class enclosingClass = getEnclosingClass(); -// if (enclosingClass == null) { // top level class -// return getName(); -// } else { -// String enclosingName = enclosingClass.getCanonicalName(); -// if (enclosingName == null) -// return null; -// return enclosingName + "." + getSimpleName(); -// } + Class enclosingClass = null; + if (enclosingClass == null) { // top level class + return getName(); + } else { + String enclosingName = enclosingClass.getCanonicalName(); + if (enclosingName == null) + return null; + return enclosingName + "." + getSimpleName(); + } } /** @@ -552,15 +896,16 @@ * @throws NullPointerException If {@code name} is {@code null} * @since JDK1.1 */ -// public InputStream getResourceAsStream(String name) { -// name = resolveName(name); -// ClassLoader cl = getClassLoader0(); -// if (cl==null) { -// // A system class. -// return ClassLoader.getSystemResourceAsStream(name); -// } -// return cl.getResourceAsStream(name); -// } + public InputStream getResourceAsStream(String name) { + name = resolveName(name); + byte[] arr = getResourceAsStream0(name); + return arr == null ? null : new ByteArrayInputStream(arr); + } + + @JavaScriptBody(args = "name", body = + "return (vm.loadBytes) ? vm.loadBytes(name) : null;" + ) + private static native byte[] getResourceAsStream0(String name); /** * Finds a resource with a given name. The rules for searching resources @@ -596,19 +941,136 @@ * resource with this name is found * @since JDK1.1 */ -// public java.net.URL getResource(String name) { -// name = resolveName(name); -// ClassLoader cl = getClassLoader0(); -// if (cl==null) { -// // A system class. -// return ClassLoader.getSystemResource(name); -// } -// return cl.getResource(name); -// } + public java.net.URL getResource(String name) { + name = resolveName(name); + ClassLoader cl = null; + if (cl==null) { + // A system class. + return ClassLoader.getSystemResource(name); + } + return cl.getResource(name); + } + /** + * Add a package name prefix if the name is not absolute Remove leading "/" + * if name is absolute + */ + private String resolveName(String name) { + if (name == null) { + return name; + } + if (!name.startsWith("/")) { + Class c = this; + while (c.isArray()) { + c = c.getComponentType(); + } + String baseName = c.getName(); + int index = baseName.lastIndexOf('.'); + if (index != -1) { + name = baseName.substring(0, index).replace('.', '/') + +"/"+name; + } + } else { + name = name.substring(1); + } + return name; + } + + /** + * Returns the class loader for the class. Some implementations may use + * null to represent the bootstrap class loader. This method will return + * null in such implementations if this class was loaded by the bootstrap + * class loader. + * + *

If a security manager is present, and the caller's class loader is + * not null and the caller's class loader is not the same as or an ancestor of + * the class loader for the class whose class loader is requested, then + * this method calls the security manager's {@code checkPermission} + * method with a {@code RuntimePermission("getClassLoader")} + * permission to ensure it's ok to access the class loader for the class. + * + *

If this object + * represents a primitive type or void, null is returned. + * + * @return the class loader that loaded the class or interface + * represented by this object. + * @throws SecurityException + * if a security manager exists and its + * {@code checkPermission} method denies + * access to the class loader for the class. + * @see java.lang.ClassLoader + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + */ + public ClassLoader getClassLoader() { + throw new SecurityException(); + } + + /** + * Returns the {@code Class} representing the component type of an + * array. If this class does not represent an array class this method + * returns null. + * + * @return the {@code Class} representing the component type of this + * class if this class is an array + * @see java.lang.reflect.Array + * @since JDK1.1 + */ + public Class getComponentType() { + if (isArray()) { + try { + return getComponentType0(); + } catch (ClassNotFoundException cnfe) { + throw new IllegalStateException(cnfe); + } + } + return null; + } - + private Class getComponentType0() throws ClassNotFoundException { + String n = getName().substring(1); + switch (n.charAt(0)) { + case 'L': + n = n.substring(1, n.length() - 1); + return Class.forName(n); + case 'I': + return Integer.TYPE; + case 'J': + return Long.TYPE; + case 'D': + return Double.TYPE; + case 'F': + return Float.TYPE; + case 'B': + return Byte.TYPE; + case 'Z': + return Boolean.TYPE; + case 'S': + return Short.TYPE; + case 'V': + return Void.TYPE; + case 'C': + return Character.TYPE; + case '[': + return defineArray(n); + default: + throw new ClassNotFoundException("Unknown component type of " + getName()); + } + } + + @JavaScriptBody(args = { "sig" }, body = + "var c = Array[sig];\n" + + "if (c) return c;\n" + + "c = vm.java_lang_Class(true);\n" + + "c.jvmName = sig;\n" + + "c.superclass = vm.java_lang_Object(false).$class;\n" + + "c.array = true;\n" + + "Array[sig] = c;\n" + + "return c;" + ) + private static native Class defineArray(String sig); + /** * Returns true if and only if this class was declared as an enum in the * source code. @@ -674,18 +1136,32 @@ throw new ClassCastException(this.toString()); } + @JavaScriptBody(args = { "ac" }, + body = + "if (this.anno) {" + + " return this.anno['L' + ac.jvmName + ';'];" + + "} else return null;" + ) + private Object getAnnotationData(Class annotationClass) { + throw new UnsupportedOperationException(); + } /** * @throws NullPointerException {@inheritDoc} * @since 1.5 */ public A getAnnotation(Class annotationClass) { - throw new UnsupportedOperationException(); + Object data = getAnnotationData(annotationClass); + return data == null ? null : AnnotationImpl.create(annotationClass, data); } /** * @throws NullPointerException {@inheritDoc} * @since 1.5 */ + @JavaScriptBody(args = { "ac" }, + body = "if (this.anno && this.anno['L' + ac.jvmName + ';']) { return true; }" + + "else return false;" + ) public boolean isAnnotationPresent( Class annotationClass) { if (annotationClass == null) @@ -694,12 +1170,17 @@ return getAnnotation(annotationClass) != null; } + @JavaScriptBody(args = {}, body = "return this.anno;") + private Object getAnnotationData() { + throw new UnsupportedOperationException(); + } /** * @since 1.5 */ public Annotation[] getAnnotations() { - throw new UnsupportedOperationException(); + Object data = getAnnotationData(); + return data == null ? new Annotation[0] : AnnotationImpl.create(data); } /** @@ -709,12 +1190,16 @@ throw new UnsupportedOperationException(); } - static Class getPrimitiveClass(String type) { - // XXX - return Object.class; - } + @JavaScriptBody(args = "type", body = "" + + "var c = vm.java_lang_Class(true);" + + "c.jvmName = type;" + + "c.primitive = true;" + + "return c;" + ) + native static Class getPrimitiveClass(String type); - public boolean desiredAssertionStatus() { - return false; - } + @JavaScriptBody(args = {}, body = + "return vm.desiredAssertionStatus ? vm.desiredAssertionStatus : false;" + ) + public native boolean desiredAssertionStatus(); } diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/ClassFormatError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/ClassFormatError.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * Thrown when the Java Virtual Machine attempts to read a class + * file and determines that the file is malformed or otherwise cannot + * be interpreted as a class file. + * + * @author unascribed + * @since JDK1.0 + */ +public +class ClassFormatError extends LinkageError { + private static final long serialVersionUID = -8420114879011949195L; + + /** + * Constructs a ClassFormatError with no detail message. + */ + public ClassFormatError() { + super(); + } + + /** + * Constructs a ClassFormatError with the specified + * detail message. + * + * @param s the detail message. + */ + public ClassFormatError(String s) { + super(s); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/ClassLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/ClassLoader.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,914 @@ +/* + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.lang; + +import java.io.InputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; +import java.util.NoSuchElementException; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * A class loader is an object that is responsible for loading classes. The + * class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to + * locate or generate data that constitutes a definition for the class. A + * typical strategy is to transform the name into a file name and then read a + * "class file" of that name from a file system. + * + *

Every {@link Class Class} object contains a {@link + * Class#getClassLoader() reference} to the ClassLoader that defined + * it. + * + *

Class objects for array classes are not created by class + * loaders, but are created automatically as required by the Java runtime. + * The class loader for an array class, as returned by {@link + * Class#getClassLoader()} is the same as the class loader for its element + * type; if the element type is a primitive type, then the array class has no + * class loader. + * + *

Applications implement subclasses of ClassLoader in order to + * extend the manner in which the Java virtual machine dynamically loads + * classes. + * + *

Class loaders may typically be used by security managers to indicate + * security domains. + * + *

The ClassLoader class uses a delegation model to search for + * classes and resources. Each instance of ClassLoader has an + * associated parent class loader. When requested to find a class or + * resource, a ClassLoader instance will delegate the search for the + * class or resource to its parent class loader before attempting to find the + * class or resource itself. The virtual machine's built-in class loader, + * called the "bootstrap class loader", does not itself have a parent but may + * serve as the parent of a ClassLoader instance. + * + *

Class loaders that support concurrent loading of classes are known as + * parallel capable class loaders and are required to register + * themselves at their class initialization time by invoking the + * {@link + * #registerAsParallelCapable ClassLoader.registerAsParallelCapable} + * method. Note that the ClassLoader class is registered as parallel + * capable by default. However, its subclasses still need to register themselves + * if they are parallel capable.
+ * In environments in which the delegation model is not strictly + * hierarchical, class loaders need to be parallel capable, otherwise class + * loading can lead to deadlocks because the loader lock is held for the + * duration of the class loading process (see {@link #loadClass + * loadClass} methods). + * + *

Normally, the Java virtual machine loads classes from the local file + * system in a platform-dependent manner. For example, on UNIX systems, the + * virtual machine loads classes from the directory defined by the + * CLASSPATH environment variable. + * + *

However, some classes may not originate from a file; they may originate + * from other sources, such as the network, or they could be constructed by an + * application. The method {@link #defineClass(String, byte[], int, int) + * defineClass} converts an array of bytes into an instance of class + * Class. Instances of this newly defined class can be created using + * {@link Class#newInstance Class.newInstance}. + * + *

The methods and constructors of objects created by a class loader may + * reference other classes. To determine the class(es) referred to, the Java + * virtual machine invokes the {@link #loadClass loadClass} method of + * the class loader that originally created the class. + * + *

For example, an application could create a network class loader to + * download class files from a server. Sample code might look like: + * + *

+ *   ClassLoader loader = new NetworkClassLoader(host, port);
+ *   Object main = loader.loadClass("Main", true).newInstance();
+ *        . . .
+ * 
+ * + *

The network class loader subclass must define the methods {@link + * #findClass findClass} and loadClassData to load a class + * from the network. Once it has downloaded the bytes that make up the class, + * it should use the method {@link #defineClass defineClass} to + * create a class instance. A sample implementation is: + * + *

+ *     class NetworkClassLoader extends ClassLoader {
+ *         String host;
+ *         int port;
+ *
+ *         public Class findClass(String name) {
+ *             byte[] b = loadClassData(name);
+ *             return defineClass(name, b, 0, b.length);
+ *         }
+ *
+ *         private byte[] loadClassData(String name) {
+ *             // load the class data from the connection
+ *              . . .
+ *         }
+ *     }
+ * 
+ * + *

Binary names

+ * + *

Any class name provided as a {@link String} parameter to methods in + * ClassLoader must be a binary name as defined by + * The Java™ Language Specification. + * + *

Examples of valid class names include: + *

+ *   "java.lang.String"
+ *   "javax.swing.JSpinner$DefaultEditor"
+ *   "java.security.KeyStore$Builder$FileBuilder$1"
+ *   "java.net.URLClassLoader$3$1"
+ * 
+ * + * @see #resolveClass(Class) + * @since 1.0 + */ +public abstract class ClassLoader { + + @JavaScriptBody(args = {}, body = "") + private static native void registerNatives(); + static { + registerNatives(); + } + + // The parent class loader for delegation + // Note: VM hardcoded the offset of this field, thus all new fields + // must be added *after* it. + private final ClassLoader parent; + + + /** + * Creates a new class loader using the specified parent class loader for + * delegation. + * + *

If there is a security manager, its {@link + * SecurityManager#checkCreateClassLoader() + * checkCreateClassLoader} method is invoked. This may result in + * a security exception.

+ * + * @param parent + * The parent class loader + * + * @throws SecurityException + * If a security manager exists and its + * checkCreateClassLoader method doesn't allow creation + * of a new class loader. + * + * @since 1.2 + */ + protected ClassLoader(ClassLoader parent) { + throw new SecurityException(); + } + + /** + * Creates a new class loader using the ClassLoader returned by + * the method {@link #getSystemClassLoader() + * getSystemClassLoader()} as the parent class loader. + * + *

If there is a security manager, its {@link + * SecurityManager#checkCreateClassLoader() + * checkCreateClassLoader} method is invoked. This may result in + * a security exception.

+ * + * @throws SecurityException + * If a security manager exists and its + * checkCreateClassLoader method doesn't allow creation + * of a new class loader. + */ + protected ClassLoader() { + throw new SecurityException(); + } + + // -- Class -- + + /** + * Loads the class with the specified binary name. + * This method searches for classes in the same manner as the {@link + * #loadClass(String, boolean)} method. It is invoked by the Java virtual + * machine to resolve class references. Invoking this method is equivalent + * to invoking {@link #loadClass(String, boolean) loadClass(name, + * false)}.

+ * + * @param name + * The binary name of the class + * + * @return The resulting Class object + * + * @throws ClassNotFoundException + * If the class was not found + */ + public Class loadClass(String name) throws ClassNotFoundException { + return loadClass(name, false); + } + + /** + * Loads the class with the specified binary name. The + * default implementation of this method searches for classes in the + * following order: + * + *

    + * + *
  1. Invoke {@link #findLoadedClass(String)} to check if the class + * has already been loaded.

  2. + * + *
  3. Invoke the {@link #loadClass(String) loadClass} method + * on the parent class loader. If the parent is null the class + * loader built-in to the virtual machine is used, instead.

  4. + * + *
  5. Invoke the {@link #findClass(String)} method to find the + * class.

  6. + * + *
+ * + *

If the class was found using the above steps, and the + * resolve flag is true, this method will then invoke the {@link + * #resolveClass(Class)} method on the resulting Class object. + * + *

Subclasses of ClassLoader are encouraged to override {@link + * #findClass(String)}, rather than this method.

+ * + *

Unless overridden, this method synchronizes on the result of + * {@link #getClassLoadingLock getClassLoadingLock} method + * during the entire class loading process. + * + * @param name + * The binary name of the class + * + * @param resolve + * If true then resolve the class + * + * @return The resulting Class object + * + * @throws ClassNotFoundException + * If the class could not be found + */ + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + synchronized (getClassLoadingLock(name)) { + // First, check if the class has already been loaded + Class c = findLoadedClass(name); + if (c == null) { + try { + if (parent != null) { + c = parent.loadClass(name, false); + } else { + c = findBootstrapClassOrNull(name); + } + } catch (ClassNotFoundException e) { + // ClassNotFoundException thrown if class not found + // from the non-null parent class loader + } + + if (c == null) { + // If still not found, then invoke findClass in order + // to find the class. + c = findClass(name); + +// // this is the defining class loader; record the stats +// sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); +// sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); +// sun.misc.PerfCounter.getFindClasses().increment(); + } + } + if (resolve) { + resolveClass(c); + } + return c; + } + } + + /** + * Returns the lock object for class loading operations. + * For backward compatibility, the default implementation of this method + * behaves as follows. If this ClassLoader object is registered as + * parallel capable, the method returns a dedicated object associated + * with the specified class name. Otherwise, the method returns this + * ClassLoader object.

+ * + * @param className + * The name of the to-be-loaded class + * + * @return the lock for class loading operations + * + * @throws NullPointerException + * If registered as parallel capable and className is null + * + * @see #loadClass(String, boolean) + * + * @since 1.7 + */ + protected Object getClassLoadingLock(String className) { + Object lock = this; + return lock; + } + + /** + * Finds the class with the specified binary name. + * This method should be overridden by class loader implementations that + * follow the delegation model for loading classes, and will be invoked by + * the {@link #loadClass loadClass} method after checking the + * parent class loader for the requested class. The default implementation + * throws a ClassNotFoundException.

+ * + * @param name + * The binary name of the class + * + * @return The resulting Class object + * + * @throws ClassNotFoundException + * If the class could not be found + * + * @since 1.2 + */ + protected Class findClass(String name) throws ClassNotFoundException { + throw new ClassNotFoundException(name); + } + + /** + * Converts an array of bytes into an instance of class Class. + * Before the Class can be used it must be resolved. This method + * is deprecated in favor of the version that takes a binary name as its first argument, and is more secure. + * + * @param b + * The bytes that make up the class data. The bytes in positions + * off through off+len-1 should have the format + * of a valid class file as defined by + * The Java™ Virtual Machine Specification. + * + * @param off + * The start offset in b of the class data + * + * @param len + * The length of the class data + * + * @return The Class object that was created from the specified + * class data + * + * @throws ClassFormatError + * If the data did not contain a valid class + * + * @throws IndexOutOfBoundsException + * If either off or len is negative, or if + * off+len is greater than b.length. + * + * @throws SecurityException + * If an attempt is made to add this class to a package that + * contains classes that were signed by a different set of + * certificates than this class, or if an attempt is made + * to define a class in a package with a fully-qualified name + * that starts with "{@code java.}". + * + * @see #loadClass(String, boolean) + * @see #resolveClass(Class) + * + * @deprecated Replaced by {@link #defineClass(String, byte[], int, int) + * defineClass(String, byte[], int, int)} + */ + @Deprecated + protected final Class defineClass(byte[] b, int off, int len) + throws ClassFormatError + { + throw new SecurityException(); + } + + /** + * Converts an array of bytes into an instance of class Class. + * Before the Class can be used it must be resolved. + * + *

This method assigns a default {@link java.security.ProtectionDomain + * ProtectionDomain} to the newly defined class. The + * ProtectionDomain is effectively granted the same set of + * permissions returned when {@link + * java.security.Policy#getPermissions(java.security.CodeSource) + * Policy.getPolicy().getPermissions(new CodeSource(null, null))} + * is invoked. The default domain is created on the first invocation of + * {@link #defineClass(String, byte[], int, int) defineClass}, + * and re-used on subsequent invocations. + * + *

To assign a specific ProtectionDomain to the class, use + * the {@link #defineClass(String, byte[], int, int, + * java.security.ProtectionDomain) defineClass} method that takes a + * ProtectionDomain as one of its arguments.

+ * + * @param name + * The expected binary name of the class, or + * null if not known + * + * @param b + * The bytes that make up the class data. The bytes in positions + * off through off+len-1 should have the format + * of a valid class file as defined by + * The Java™ Virtual Machine Specification. + * + * @param off + * The start offset in b of the class data + * + * @param len + * The length of the class data + * + * @return The Class object that was created from the specified + * class data. + * + * @throws ClassFormatError + * If the data did not contain a valid class + * + * @throws IndexOutOfBoundsException + * If either off or len is negative, or if + * off+len is greater than b.length. + * + * @throws SecurityException + * If an attempt is made to add this class to a package that + * contains classes that were signed by a different set of + * certificates than this class (which is unsigned), or if + * name begins with "java.". + * + * @see #loadClass(String, boolean) + * @see #resolveClass(Class) + * @see java.security.CodeSource + * @see java.security.SecureClassLoader + * + * @since 1.1 + */ + protected final Class defineClass(String name, byte[] b, int off, int len) + throws ClassFormatError + { + throw new SecurityException(); + } + + /** + * Links the specified class. This (misleadingly named) method may be + * used by a class loader to link a class. If the class c has + * already been linked, then this method simply returns. Otherwise, the + * class is linked as described in the "Execution" chapter of + * The Java™ Language Specification. + *

+ * + * @param c + * The class to link + * + * @throws NullPointerException + * If c is null. + * + * @see #defineClass(String, byte[], int, int) + */ + protected final void resolveClass(Class c) { + resolveClass0(c); + } + + private native void resolveClass0(Class c); + + + /** + * Returns the class with the given binary name if this + * loader has been recorded by the Java virtual machine as an initiating + * loader of a class with that binary name. Otherwise + * null is returned.

+ * + * @param name + * The binary name of the class + * + * @return The Class object, or null if the class has + * not been loaded + * + * @since 1.1 + */ + protected final Class findLoadedClass(String name) { + if (!checkName(name)) + return null; + return findLoadedClass0(name); + } + + private native final Class findLoadedClass0(String name); + + /** + * Sets the signers of a class. This should be invoked after defining a + * class.

+ * + * @param c + * The Class object + * + * @param signers + * The signers for the class + * + * @since 1.1 + */ + protected final void setSigners(Class c, Object[] signers) { + //c.setSigners(signers); + throw new UnsupportedOperationException(); + } + + + // -- Resource -- + + /** + * Finds the resource with the given name. A resource is some data + * (images, audio, text, etc) that can be accessed by class code in a way + * that is independent of the location of the code. + * + *

The name of a resource is a '/'-separated path name that + * identifies the resource. + * + *

This method will first search the parent class loader for the + * resource; if the parent is null the path of the class loader + * built-in to the virtual machine is searched. That failing, this method + * will invoke {@link #findResource(String)} to find the resource.

+ * + * @param name + * The resource name + * + * @return A URL object for reading the resource, or + * null if the resource could not be found or the invoker + * doesn't have adequate privileges to get the resource. + * + * @since 1.1 + */ + public URL getResource(String name) { + URL url; + if (parent != null) { + url = parent.getResource(name); + } else { + url = getBootstrapResource(name); + } + if (url == null) { + url = findResource(name); + } + return url; + } + + /** + * Finds all the resources with the given name. A resource is some data + * (images, audio, text, etc) that can be accessed by class code in a way + * that is independent of the location of the code. + * + *

The name of a resource is a /-separated path name that + * identifies the resource. + * + *

The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @param name + * The resource name + * + * @return An enumeration of {@link java.net.URL URL} objects for + * the resource. If no resources could be found, the enumeration + * will be empty. Resources that the class loader doesn't have + * access to will not be in the enumeration. + * + * @throws IOException + * If I/O errors occur + * + * @see #findResources(String) + * + * @since 1.2 + */ + public Enumeration getResources(String name) throws IOException { + Enumeration[] tmp = new Enumeration[2]; + if (parent != null) { + tmp[0] = parent.getResources(name); + } else { + tmp[0] = getBootstrapResources(name); + } + tmp[1] = findResources(name); + + return new CompoundEnumeration(tmp); + } + + /** + * Finds the resource with the given name. Class loader implementations + * should override this method to specify where to find resources.

+ * + * @param name + * The resource name + * + * @return A URL object for reading the resource, or + * null if the resource could not be found + * + * @since 1.2 + */ + protected URL findResource(String name) { + return null; + } + + /** + * Returns an enumeration of {@link java.net.URL URL} objects + * representing all the resources with the given name. Class loader + * implementations should override this method to specify where to load + * resources from.

+ * + * @param name + * The resource name + * + * @return An enumeration of {@link java.net.URL URL} objects for + * the resources + * + * @throws IOException + * If I/O errors occur + * + * @since 1.2 + */ + protected Enumeration findResources(String name) throws IOException { + return new CompoundEnumeration(new Enumeration[0]); + } + + // index 0: java.lang.ClassLoader.class + // index 1: the immediate caller of index 0. + // index 2: the immediate caller of index 1. + private static native Class getCaller(int index); + + /** + * Registers the caller as parallel capable.

+ * The registration succeeds if and only if all of the following + * conditions are met:
+ * 1. no instance of the caller has been created

+ * 2. all of the super classes (except class Object) of the caller are + * registered as parallel capable

+ * Note that once a class loader is registered as parallel capable, there + * is no way to change it back.

+ * + * @return true if the caller is successfully registered as + * parallel capable and false if otherwise. + * + * @since 1.7 + */ +// protected static boolean registerAsParallelCapable() { +// return false; +// } + + /** + * Find a resource of the specified name from the search path used to load + * classes. This method locates the resource through the system class + * loader (see {@link #getSystemClassLoader()}).

+ * + * @param name + * The resource name + * + * @return A {@link java.net.URL URL} object for reading the + * resource, or null if the resource could not be found + * + * @since 1.1 + */ + public static URL getSystemResource(String name) { + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return getBootstrapResource(name); + } + return system.getResource(name); + } + + /** + * Finds all resources of the specified name from the search path used to + * load classes. The resources thus found are returned as an + * {@link java.util.Enumeration Enumeration} of {@link + * java.net.URL URL} objects. + * + *

The search order is described in the documentation for {@link + * #getSystemResource(String)}.

+ * + * @param name + * The resource name + * + * @return An enumeration of resource {@link java.net.URL URL} + * objects + * + * @throws IOException + * If I/O errors occur + + * @since 1.2 + */ + public static Enumeration getSystemResources(String name) + throws IOException + { + ClassLoader system = getSystemClassLoader(); + if (system == null) { + return getBootstrapResources(name); + } + return system.getResources(name); + } + + + + /** + * Returns an input stream for reading the specified resource. + * + *

The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @param name + * The resource name + * + * @return An input stream for reading the resource, or null + * if the resource could not be found + * + * @since 1.1 + */ + public InputStream getResourceAsStream(String name) { + URL url = getResource(name); + try { + return url != null ? url.openStream() : null; + } catch (IOException e) { + return null; + } + } + + /** + * Open for reading, a resource of the specified name from the search path + * used to load classes. This method locates the resource through the + * system class loader (see {@link #getSystemClassLoader()}).

+ * + * @param name + * The resource name + * + * @return An input stream for reading the resource, or null + * if the resource could not be found + * + * @since 1.1 + */ + public static InputStream getSystemResourceAsStream(String name) { + URL url = getSystemResource(name); + try { + return url != null ? url.openStream() : null; + } catch (IOException e) { + return null; + } + } + + + // -- Hierarchy -- + + /** + * Returns the parent class loader for delegation. Some implementations may + * use null to represent the bootstrap class loader. This method + * will return null in such implementations if this class loader's + * parent is the bootstrap class loader. + * + *

If a security manager is present, and the invoker's class loader is + * not null and is not an ancestor of this class loader, then this + * method invokes the security manager's {@link + * SecurityManager#checkPermission(java.security.Permission) + * checkPermission} method with a {@link + * RuntimePermission#RuntimePermission(String) + * RuntimePermission("getClassLoader")} permission to verify + * access to the parent class loader is permitted. If not, a + * SecurityException will be thrown.

+ * + * @return The parent ClassLoader + * + * @throws SecurityException + * If a security manager exists and its checkPermission + * method doesn't allow access to this class loader's parent class + * loader. + * + * @since 1.2 + */ + public final ClassLoader getParent() { + throw new SecurityException(); + } + + /** + * Returns the system class loader for delegation. This is the default + * delegation parent for new ClassLoader instances, and is + * typically the class loader used to start the application. + * + *

This method is first invoked early in the runtime's startup + * sequence, at which point it creates the system class loader and sets it + * as the context class loader of the invoking Thread. + * + *

The default system class loader is an implementation-dependent + * instance of this class. + * + *

If the system property "java.system.class.loader" is defined + * when this method is first invoked then the value of that property is + * taken to be the name of a class that will be returned as the system + * class loader. The class is loaded using the default system class loader + * and must define a public constructor that takes a single parameter of + * type ClassLoader which is used as the delegation parent. An + * instance is then created using this constructor with the default system + * class loader as the parameter. The resulting class loader is defined + * to be the system class loader. + * + *

If a security manager is present, and the invoker's class loader is + * not null and the invoker's class loader is not the same as or + * an ancestor of the system class loader, then this method invokes the + * security manager's {@link + * SecurityManager#checkPermission(java.security.Permission) + * checkPermission} method with a {@link + * RuntimePermission#RuntimePermission(String) + * RuntimePermission("getClassLoader")} permission to verify + * access to the system class loader. If not, a + * SecurityException will be thrown.

+ * + * @return The system ClassLoader for delegation, or + * null if none + * + * @throws SecurityException + * If a security manager exists and its checkPermission + * method doesn't allow access to the system class loader. + * + * @throws IllegalStateException + * If invoked recursively during the construction of the class + * loader specified by the "java.system.class.loader" + * property. + * + * @throws Error + * If the system property "java.system.class.loader" + * is defined but the named class could not be loaded, the + * provider class does not define the required constructor, or an + * exception is thrown by that constructor when it is invoked. The + * underlying cause of the error can be retrieved via the + * {@link Throwable#getCause()} method. + * + * @revised 1.4 + */ + public static ClassLoader getSystemClassLoader() { + throw new SecurityException(); + } + + // Returns true if the specified class loader can be found in this class + // loader's delegation chain. + boolean isAncestor(ClassLoader cl) { + ClassLoader acl = this; + do { + acl = acl.parent; + if (cl == acl) { + return true; + } + } while (acl != null); + return false; + } + + private boolean checkName(String name) { + throw new UnsupportedOperationException(); + } + + private Class findBootstrapClassOrNull(String name) { + throw new UnsupportedOperationException(); + } + + private static URL getBootstrapResource(String name) { + throw new UnsupportedOperationException(); + } + + private static Enumeration getBootstrapResources(String name) { + throw new UnsupportedOperationException(); + } + + private static class CompoundEnumeration implements Enumeration { + private URL next; + private int index; + private final Enumeration[] arr; + + public CompoundEnumeration(Enumeration[] arr) { + this.arr = arr; + this.index = 0; + } + + public boolean hasMoreElements() { + if (next == null) { + if (arr[index].hasMoreElements()) { + next = (URL) arr[index].nextElement(); + } else { + if (index < arr.length) { + index++; + return hasMoreElements(); + } + } + } + return next != null; + } + + public URL nextElement() { + if (!hasMoreElements()) { + throw new NoSuchElementException(); + } + URL r = next; + next = null; + return r; + } + + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Double.java --- a/emul/src/main/java/java/lang/Double.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Double.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,6 +25,8 @@ package java.lang; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * The {@code Double} class wraps a value of the primitive type * {@code double} in an object. An object of type @@ -188,6 +190,9 @@ * @param d the {@code double} to be converted. * @return a string representation of the argument. */ + @JavaScriptBody(args="d", body="var r = d.toString();" + + "if (r.indexOf('.') === -1) r = r + '.0';" + + "return r;") public static String toString(double d) { throw new UnsupportedOperationException(); } @@ -497,6 +502,7 @@ * @throws NumberFormatException if the string does not contain a * parsable number. */ + @JavaScriptBody(args="s", body="return parseFloat(s);") public static Double valueOf(String s) throws NumberFormatException { throw new UnsupportedOperationException(); // return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue()); @@ -534,6 +540,7 @@ * @see java.lang.Double#valueOf(String) * @since 1.2 */ + @JavaScriptBody(args="s", body="return parseFloat(s);") public static double parseDouble(String s) throws NumberFormatException { throw new UnsupportedOperationException(); // return FloatingDecimal.readJavaFormatString(s).doubleValue(); @@ -767,8 +774,7 @@ */ public boolean equals(Object obj) { return (obj instanceof Double) - && (doubleToLongBits(((Double)obj).value) == - doubleToLongBits(value)); + && (((Double)obj).value) == value; } /** diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Float.java --- a/emul/src/main/java/java/lang/Float.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Float.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,6 +25,8 @@ package java.lang; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * The {@code Float} class wraps a value of primitive type * {@code float} in an object. An object of type @@ -191,8 +193,7 @@ * @return a string representation of the argument. */ public static String toString(float f) { - throw new UnsupportedOperationException(); -// return new FloatingDecimal(f).toJavaFormatString(); + return Double.toString(f); } /** @@ -816,6 +817,18 @@ * @return the {@code float} floating-point value with the same bit * pattern. */ + @JavaScriptBody(args = "bits", + body = + "if (bits === 0x7f800000) return Number.POSITIVE_INFINITY;\n" + + "if (bits === 0xff800000) return Number.NEGATIVE_INFINITY;\n" + + "if (bits >= 0x7f800001 && bits <= 0xffffffff) return Number.NaN;\n" + + "var s = ((bits >> 31) == 0) ? 1 : -1;\n" + + "var e = ((bits >> 23) & 0xff);\n" + + "var m = (e == 0) ?\n" + + " (bits & 0x7fffff) << 1 :\n" + + " (bits & 0x7fffff) | 0x800000;\n" + + "return s * m * Math.pow(2.0, e - 150);\n" + ) public static native float intBitsToFloat(int bits); /** diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Integer.java --- a/emul/src/main/java/java/lang/Integer.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Integer.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,6 +25,8 @@ package java.lang; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * The {@code Integer} class wraps a value of the primitive type * {@code int} in an object. An object of type {@code Integer} @@ -322,13 +324,14 @@ * @param i an integer to be converted. * @return a string representation of the argument in base 10. */ + @JavaScriptBody(args = "i", body = "return i.toString();") public static String toString(int i) { if (i == Integer.MIN_VALUE) return "-2147483648"; int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); char[] buf = new char[size]; getChars(i, size, buf); - return new String(0, size, buf); + return new String(buf, 0, size); } /** @@ -439,6 +442,7 @@ * @exception NumberFormatException if the {@code String} * does not contain a parsable {@code int}. */ + @JavaScriptBody(args={"s", "radix"}, body="return parseInt(s,radix);") public static int parseInt(String s, int radix) throws NumberFormatException { @@ -600,7 +604,7 @@ // high value may be configured by property int h = 127; String integerCacheHighPropValue = - String.getProperty("java.lang.Integer.IntegerCache.high"); + AbstractStringBuilder.getProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); @@ -882,7 +886,7 @@ public static Integer getInteger(String nm, Integer val) { String v = null; try { - v = String.getProperty(nm); + v = AbstractStringBuilder.getProperty(nm); } catch (IllegalArgumentException e) { } catch (NullPointerException e) { } diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/LinkageError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/LinkageError.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * Subclasses of {@code LinkageError} indicate that a class has + * some dependency on another class; however, the latter class has + * incompatibly changed after the compilation of the former class. + * + * + * @author Frank Yellin + * @since JDK1.0 + */ +public +class LinkageError extends Error { + private static final long serialVersionUID = 3579600108157160122L; + + /** + * Constructs a {@code LinkageError} with no detail message. + */ + public LinkageError() { + super(); + } + + /** + * Constructs a {@code LinkageError} with the specified detail + * message. + * + * @param s the detail message. + */ + public LinkageError(String s) { + super(s); + } + + /** + * Constructs a {@code LinkageError} with the specified detail + * message and cause. + * + * @param s the detail message. + * @param cause the cause, may be {@code null} + * @since 1.7 + */ + public LinkageError(String s, Throwable cause) { + super(s, cause); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Long.java --- a/emul/src/main/java/java/lang/Long.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Long.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,6 +25,8 @@ package java.lang; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * The {@code Long} class wraps a value of the primitive type {@code * long} in an object. An object of type {@code Long} contains a @@ -260,13 +262,14 @@ * @param i a {@code long} to be converted. * @return a string representation of the argument in base 10. */ + @JavaScriptBody(args = "i", body = "return i.toString();") public static String toString(long i) { if (i == Long.MIN_VALUE) return "-9223372036854775808"; int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); char[] buf = new char[size]; getChars(i, size, buf); - return new String(0, size, buf); + return new String(buf, 0, size); } /** @@ -923,7 +926,7 @@ public static Long getLong(String nm, Long val) { String v = null; try { - v = String.getProperty(nm); + v = AbstractStringBuilder.getProperty(nm); } catch (IllegalArgumentException e) { } catch (NullPointerException e) { } diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Math.java --- a/emul/src/main/java/java/lang/Math.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Math.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,6 +25,8 @@ package java.lang; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * The class {@code Math} contains methods for performing basic @@ -116,8 +118,9 @@ * @param a an angle, in radians. * @return the sine of the argument. */ + @JavaScriptBody(args="a", body="return Math.sin(a);") public static double sin(double a) { - return StrictMath.sin(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -131,8 +134,9 @@ * @param a an angle, in radians. * @return the cosine of the argument. */ + @JavaScriptBody(args="a", body="return Math.cos(a);") public static double cos(double a) { - return StrictMath.cos(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -148,8 +152,9 @@ * @param a an angle, in radians. * @return the tangent of the argument. */ + @JavaScriptBody(args="a", body="return Math.tan(a);") public static double tan(double a) { - return StrictMath.tan(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -166,8 +171,9 @@ * @param a the value whose arc sine is to be returned. * @return the arc sine of the argument. */ + @JavaScriptBody(args="a", body="return Math.asin(a);") public static double asin(double a) { - return StrictMath.asin(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -182,8 +188,9 @@ * @param a the value whose arc cosine is to be returned. * @return the arc cosine of the argument. */ + @JavaScriptBody(args="a", body="return Math.acos(a);") public static double acos(double a) { - return StrictMath.acos(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -199,8 +206,9 @@ * @param a the value whose arc tangent is to be returned. * @return the arc tangent of the argument. */ + @JavaScriptBody(args="a", body="return Math.atan(a);") public static double atan(double a) { - return StrictMath.atan(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -249,8 +257,9 @@ * @return the value e{@code a}, * where e is the base of the natural logarithms. */ + @JavaScriptBody(args="a", body="return Math.exp(a);") public static double exp(double a) { - return StrictMath.exp(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -270,8 +279,9 @@ * @return the value ln {@code a}, the natural logarithm of * {@code a}. */ + @JavaScriptBody(args="a", body="return Math.log(a);") public static double log(double a) { - return StrictMath.log(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -295,8 +305,9 @@ * @return the base 10 logarithm of {@code a}. * @since 1.5 */ + @JavaScriptBody(args="a", body="return Math.log(a) / Math.LN10;") public static double log10(double a) { - return StrictMath.log10(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -316,69 +327,9 @@ * @return the positive square root of {@code a}. * If the argument is NaN or less than zero, the result is NaN. */ + @JavaScriptBody(args="a", body="return Math.sqrt(a);") public static double sqrt(double a) { - return StrictMath.sqrt(a); // default impl. delegates to StrictMath - // Note that hardware sqrt instructions - // frequently can be directly used by JITs - // and should be much faster than doing - // Math.sqrt in software. - } - - - /** - * Returns the cube root of a {@code double} value. For - * positive finite {@code x}, {@code cbrt(-x) == - * -cbrt(x)}; that is, the cube root of a negative value is - * the negative of the cube root of that value's magnitude. - * - * Special cases: - * - *
    - * - *
  • If the argument is NaN, then the result is NaN. - * - *
  • If the argument is infinite, then the result is an infinity - * with the same sign as the argument. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
- * - *

The computed result must be within 1 ulp of the exact result. - * - * @param a a value. - * @return the cube root of {@code a}. - * @since 1.5 - */ - public static double cbrt(double a) { - return StrictMath.cbrt(a); - } - - /** - * Computes the remainder operation on two arguments as prescribed - * by the IEEE 754 standard. - * The remainder value is mathematically equal to - * f1 - f2 × n, - * where n is the mathematical integer closest to the exact - * mathematical value of the quotient {@code f1/f2}, and if two - * mathematical integers are equally close to {@code f1/f2}, - * then n is the integer that is even. If the remainder is - * zero, its sign is the same as the sign of the first argument. - * Special cases: - *

  • If either argument is NaN, or the first argument is infinite, - * or the second argument is positive zero or negative zero, then the - * result is NaN. - *
  • If the first argument is finite and the second argument is - * infinite, then the result is the same as the first argument.
- * - * @param f1 the dividend. - * @param f2 the divisor. - * @return the remainder when {@code f1} is divided by - * {@code f2}. - */ - public static double IEEEremainder(double f1, double f2) { - return StrictMath.IEEEremainder(f1, f2); // delegate to StrictMath + throw new UnsupportedOperationException(); } /** @@ -400,8 +351,9 @@ * floating-point value that is greater than or equal to * the argument and is equal to a mathematical integer. */ + @JavaScriptBody(args="a", body="return Math.ceil(a);") public static double ceil(double a) { - return StrictMath.ceil(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -419,27 +371,9 @@ * floating-point value that less than or equal to the argument * and is equal to a mathematical integer. */ + @JavaScriptBody(args="a", body="return Math.floor(a);") public static double floor(double a) { - return StrictMath.floor(a); // default impl. delegates to StrictMath - } - - /** - * Returns the {@code double} value that is closest in value - * to the argument and is equal to a mathematical integer. If two - * {@code double} values that are mathematical integers are - * equally close, the result is the integer value that is - * even. Special cases: - *
  • If the argument value is already equal to a mathematical - * integer, then the result is the same as the argument. - *
  • If the argument is NaN or an infinity or positive zero or negative - * zero, then the result is the same as the argument.
- * - * @param a a {@code double} value. - * @return the closest floating-point value to {@code a} that is - * equal to a mathematical integer. - */ - public static double rint(double a) { - return StrictMath.rint(a); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -494,8 +428,9 @@ * in polar coordinates that corresponds to the point * (xy) in Cartesian coordinates. */ + @JavaScriptBody(args={"y", "x"}, body="return Math.atan2(y, x);") public static double atan2(double y, double x) { - return StrictMath.atan2(y, x); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -621,8 +556,9 @@ * @param b the exponent. * @return the value {@code a}{@code b}. */ + @JavaScriptBody(args={"a", "b"}, body="return Math.pow(a, b);") public static double pow(double a, double b) { - return StrictMath.pow(a, b); // default impl. delegates to StrictMath + throw new UnsupportedOperationException(); } /** @@ -645,11 +581,9 @@ * @see java.lang.Integer#MAX_VALUE * @see java.lang.Integer#MIN_VALUE */ + @JavaScriptBody(args="a", body="return Math.round(a);") public static int round(float a) { - if (a != 0x1.fffffep-2f) // greatest float value less than 0.5 - return (int)floor(a + 0.5f); - else - return 0; + throw new UnsupportedOperationException(); } /** @@ -672,11 +606,9 @@ * @see java.lang.Long#MAX_VALUE * @see java.lang.Long#MIN_VALUE */ + @JavaScriptBody(args="a", body="return Math.round(a);") public static long round(double a) { - if (a != 0x1.fffffffffffffp-2) // greatest double value less than 0.5 - return (long)floor(a + 0.5d); - else - return 0; + throw new UnsupportedOperationException(); } // private static Random randomNumberGenerator; @@ -709,6 +641,7 @@ * to {@code 0.0} and less than {@code 1.0}. * @see Random#nextDouble() */ + @JavaScriptBody(args={}, body="return Math.random();") public static double random() { throw new UnsupportedOperationException(); } @@ -813,9 +746,6 @@ return (a >= b) ? a : b; } - private static long negativeZeroFloatBits = Float.floatToIntBits(-0.0f); - private static long negativeZeroDoubleBits = Double.doubleToLongBits(-0.0d); - /** * Returns the greater of two {@code float} values. That is, * the result is the argument closer to positive infinity. If the @@ -830,13 +760,11 @@ * @param b another argument. * @return the larger of {@code a} and {@code b}. */ + @JavaScriptBody(args={"a", "b"}, + body="return Math.max(a,b);" + ) public static float max(float a, float b) { - if (a != a) return a; // a is NaN - if ((a == 0.0f) && (b == 0.0f) - && (Float.floatToIntBits(a) == negativeZeroFloatBits)) { - return b; - } - return (a >= b) ? a : b; + throw new UnsupportedOperationException(); } /** @@ -853,13 +781,11 @@ * @param b another argument. * @return the larger of {@code a} and {@code b}. */ + @JavaScriptBody(args={"a", "b"}, + body="return Math.max(a,b);" + ) public static double max(double a, double b) { - if (a != a) return a; // a is NaN - if ((a == 0.0d) && (b == 0.0d) - && (Double.doubleToLongBits(a) == negativeZeroDoubleBits)) { - return b; - } - return (a >= b) ? a : b; + throw new UnsupportedOperationException(); } /** @@ -904,13 +830,11 @@ * @param b another argument. * @return the smaller of {@code a} and {@code b}. */ + @JavaScriptBody(args={"a", "b"}, + body="return Math.min(a,b);" + ) public static float min(float a, float b) { - if (a != a) return a; // a is NaN - if ((a == 0.0f) && (b == 0.0f) - && (Float.floatToIntBits(b) == negativeZeroFloatBits)) { - return b; - } - return (a <= b) ? a : b; + throw new UnsupportedOperationException(); } /** @@ -927,13 +851,11 @@ * @param b another argument. * @return the smaller of {@code a} and {@code b}. */ + @JavaScriptBody(args={"a", "b"}, + body="return Math.min(a,b);" + ) public static double min(double a, double b) { - if (a != a) return a; // a is NaN - if ((a == 0.0d) && (b == 0.0d) - && (Double.doubleToLongBits(b) == negativeZeroDoubleBits)) { - return b; - } - return (a <= b) ? a : b; + throw new UnsupportedOperationException(); } /** @@ -1033,207 +955,6 @@ // } /** - * Returns the hyperbolic sine of a {@code double} value. - * The hyperbolic sine of x is defined to be - * (ex - e-x)/2 - * where e is {@linkplain Math#E Euler's number}. - * - *

Special cases: - *

    - * - *
  • If the argument is NaN, then the result is NaN. - * - *
  • If the argument is infinite, then the result is an infinity - * with the same sign as the argument. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
- * - *

The computed result must be within 2.5 ulps of the exact result. - * - * @param x The number whose hyperbolic sine is to be returned. - * @return The hyperbolic sine of {@code x}. - * @since 1.5 - */ - public static double sinh(double x) { - return StrictMath.sinh(x); - } - - /** - * Returns the hyperbolic cosine of a {@code double} value. - * The hyperbolic cosine of x is defined to be - * (ex + e-x)/2 - * where e is {@linkplain Math#E Euler's number}. - * - *

Special cases: - *

    - * - *
  • If the argument is NaN, then the result is NaN. - * - *
  • If the argument is infinite, then the result is positive - * infinity. - * - *
  • If the argument is zero, then the result is {@code 1.0}. - * - *
- * - *

The computed result must be within 2.5 ulps of the exact result. - * - * @param x The number whose hyperbolic cosine is to be returned. - * @return The hyperbolic cosine of {@code x}. - * @since 1.5 - */ - public static double cosh(double x) { - return StrictMath.cosh(x); - } - - /** - * Returns the hyperbolic tangent of a {@code double} value. - * The hyperbolic tangent of x is defined to be - * (ex - e-x)/(ex + e-x), - * in other words, {@linkplain Math#sinh - * sinh(x)}/{@linkplain Math#cosh cosh(x)}. Note - * that the absolute value of the exact tanh is always less than - * 1. - * - *

Special cases: - *

    - * - *
  • If the argument is NaN, then the result is NaN. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
  • If the argument is positive infinity, then the result is - * {@code +1.0}. - * - *
  • If the argument is negative infinity, then the result is - * {@code -1.0}. - * - *
- * - *

The computed result must be within 2.5 ulps of the exact result. - * The result of {@code tanh} for any finite input must have - * an absolute value less than or equal to 1. Note that once the - * exact result of tanh is within 1/2 of an ulp of the limit value - * of ±1, correctly signed ±{@code 1.0} should - * be returned. - * - * @param x The number whose hyperbolic tangent is to be returned. - * @return The hyperbolic tangent of {@code x}. - * @since 1.5 - */ - public static double tanh(double x) { - return StrictMath.tanh(x); - } - - /** - * Returns sqrt(x2 +y2) - * without intermediate overflow or underflow. - * - *

Special cases: - *

    - * - *
  • If either argument is infinite, then the result - * is positive infinity. - * - *
  • If either argument is NaN and neither argument is infinite, - * then the result is NaN. - * - *
- * - *

The computed result must be within 1 ulp of the exact - * result. If one parameter is held constant, the results must be - * semi-monotonic in the other parameter. - * - * @param x a value - * @param y a value - * @return sqrt(x2 +y2) - * without intermediate overflow or underflow - * @since 1.5 - */ - public static double hypot(double x, double y) { - return StrictMath.hypot(x, y); - } - - /** - * Returns ex -1. Note that for values of - * x near 0, the exact sum of - * {@code expm1(x)} + 1 is much closer to the true - * result of ex than {@code exp(x)}. - * - *

Special cases: - *

    - *
  • If the argument is NaN, the result is NaN. - * - *
  • If the argument is positive infinity, then the result is - * positive infinity. - * - *
  • If the argument is negative infinity, then the result is - * -1.0. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
- * - *

The computed result must be within 1 ulp of the exact result. - * Results must be semi-monotonic. The result of - * {@code expm1} for any finite input must be greater than or - * equal to {@code -1.0}. Note that once the exact result of - * e{@code x} - 1 is within 1/2 - * ulp of the limit value -1, {@code -1.0} should be - * returned. - * - * @param x the exponent to raise e to in the computation of - * e{@code x} -1. - * @return the value e{@code x} - 1. - * @since 1.5 - */ - public static double expm1(double x) { - return StrictMath.expm1(x); - } - - /** - * Returns the natural logarithm of the sum of the argument and 1. - * Note that for small values {@code x}, the result of - * {@code log1p(x)} is much closer to the true result of ln(1 - * + {@code x}) than the floating-point evaluation of - * {@code log(1.0+x)}. - * - *

Special cases: - * - *

    - * - *
  • If the argument is NaN or less than -1, then the result is - * NaN. - * - *
  • If the argument is positive infinity, then the result is - * positive infinity. - * - *
  • If the argument is negative one, then the result is - * negative infinity. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
- * - *

The computed result must be within 1 ulp of the exact result. - * Results must be semi-monotonic. - * - * @param x a value - * @return the value ln({@code x} + 1), the natural - * log of {@code x} + 1 - * @since 1.5 - */ - public static double log1p(double x) { - return StrictMath.log1p(x); - } - - /** * Returns the first floating-point argument with the sign of the * second floating-point argument. Note that unlike the {@link * StrictMath#copySign(double, double) StrictMath.copySign} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/NegativeArraySizeException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/NegativeArraySizeException.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * Thrown if an application tries to create an array with negative size. + * + * @author unascribed + * @since JDK1.0 + */ +public +class NegativeArraySizeException extends RuntimeException { + private static final long serialVersionUID = -8960118058596991861L; + + /** + * Constructs a NegativeArraySizeException with no + * detail message. + */ + public NegativeArraySizeException() { + super(); + } + + /** + * Constructs a NegativeArraySizeException with the + * specified detail message. + * + * @param s the detail message. + */ + public NegativeArraySizeException(String s) { + super(s); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/NoSuchMethodException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/NoSuchMethodException.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * Thrown when a particular method cannot be found. + * + * @author unascribed + * @since JDK1.0 + */ +public +class NoSuchMethodException extends ReflectiveOperationException { + private static final long serialVersionUID = 5034388446362600923L; + + /** + * Constructs a NoSuchMethodException without a detail message. + */ + public NoSuchMethodException() { + super(); + } + + /** + * Constructs a NoSuchMethodException with a detail message. + * + * @param s the detail message. + */ + public NoSuchMethodException(String s) { + super(s); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Number.java --- a/emul/src/main/java/java/lang/Number.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Number.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,6 +25,8 @@ package java.lang; +import org.apidesign.bck2brwsr.core.ExtraJavaScript; + /** * The abstract class Number is the superclass of classes * BigDecimal, BigInteger, @@ -46,6 +48,10 @@ * @see java.lang.Short * @since JDK1.0 */ +@ExtraJavaScript( + resource="/org/apidesign/vm4brwsr/emul/java_lang_Number.js", + processByteCode=true +) public abstract class Number implements java.io.Serializable { /** * Returns the value of the specified number as an int. diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Object.java --- a/emul/src/main/java/java/lang/Object.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Object.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,6 +25,10 @@ package java.lang; +import java.lang.reflect.Array; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.core.JavaScriptPrototype; + /** * Class {@code Object} is the root of the class hierarchy. * Every class has {@code Object} as a superclass. All objects, @@ -34,9 +38,16 @@ * @see java.lang.Class * @since JDK1.0 */ +@JavaScriptPrototype(container = "Object.prototype", prototype = "new Object") public class Object { - private static native void registerNatives(); + private static void registerNatives() { + try { + Array.get(null, 0); + } catch (Throwable ex) { + // ignore + } + } static { registerNatives(); } @@ -61,6 +72,7 @@ * @see Class Literals, section 15.8.2 of * The Java™ Language Specification. */ + @JavaScriptBody(args={}, body="return this.constructor.$class;") public final native Class getClass(); /** @@ -98,8 +110,16 @@ * @see java.lang.Object#equals(java.lang.Object) * @see java.lang.System#identityHashCode */ + @JavaScriptBody(args = {}, body = + "if (this.$hashCode) return this.$hashCode;\n" + + "var h = this.computeHashCode__I();\n" + + "return this.$hashCode = h & h;" + ) public native int hashCode(); + @JavaScriptBody(args = {}, body = "Math.random() * Math.pow(2, 32);") + native int computeHashCode(); + /** * Indicates whether some other object is "equal to" this one. *

@@ -210,7 +230,28 @@ * be cloned. * @see java.lang.Cloneable */ - protected native Object clone() throws CloneNotSupportedException; + protected Object clone() throws CloneNotSupportedException { + Object ret = clone(this); + if (ret == null) { + throw new CloneNotSupportedException(getClass().getName()); + } + return ret; + } + + @JavaScriptBody(args = "self", body = + "\nif (!self.$instOf_java_lang_Cloneable) {" + + "\n return null;" + + "\n} else {" + + "\n var clone = self.constructor(true);" + + "\n var props = Object.getOwnPropertyNames(self);" + + "\n for (var i = 0; i < props.length; i++) {" + + "\n var p = props[i];" + + "\n clone[p] = self[p];" + + "\n };" + + "\n return clone;" + + "\n}" + ) + private static native Object clone(Object self) throws CloneNotSupportedException; /** * Returns a string representation of the object. In general, the diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Runnable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/Runnable.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * The Runnable interface should be implemented by any + * class whose instances are intended to be executed by a thread. The + * class must define a method of no arguments called run. + *

+ * This interface is designed to provide a common protocol for objects that + * wish to execute code while they are active. For example, + * Runnable is implemented by class Thread. + * Being active simply means that a thread has been started and has not + * yet been stopped. + *

+ * In addition, Runnable provides the means for a class to be + * active while not subclassing Thread. A class that implements + * Runnable can run without subclassing Thread + * by instantiating a Thread instance and passing itself in + * as the target. In most cases, the Runnable interface should + * be used if you are only planning to override the run() + * method and no other Thread methods. + * This is important because classes should not be subclassed + * unless the programmer intends on modifying or enhancing the fundamental + * behavior of the class. + * + * @author Arthur van Hoff + * @see java.lang.Thread + * @see java.util.concurrent.Callable + * @since JDK1.0 + */ +public +interface Runnable { + /** + * When an object implementing interface Runnable is used + * to create a thread, starting the thread causes the object's + * run method to be called in that separately executing + * thread. + *

+ * The general contract of the method run is that it may + * take any action whatsoever. + * + * @see java.lang.Thread#run() + */ + public abstract void run(); +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/SecurityException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/SecurityException.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.lang; + +/** + * Thrown by the security manager to indicate a security violation. + * + * @author unascribed + * @see java.lang.SecurityManager + * @since JDK1.0 + */ +public class SecurityException extends RuntimeException { + + private static final long serialVersionUID = 6878364983674394167L; + + /** + * Constructs a SecurityException with no detail message. + */ + public SecurityException() { + super(); + } + + /** + * Constructs a SecurityException with the specified + * detail message. + * + * @param s the detail message. + */ + public SecurityException(String s) { + super(s); + } + + /** + * Creates a SecurityException with the specified + * detail message and cause. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is permitted, + * and indicates that the cause is nonexistent or unknown.) + * @since 1.5 + */ + public SecurityException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Creates a SecurityException with the specified cause + * and a detail message of (cause==null ? null : cause.toString()) + * (which typically contains the class and detail message of + * cause). + * + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is permitted, + * and indicates that the cause is nonexistent or unknown.) + * @since 1.5 + */ + public SecurityException(Throwable cause) { + super(cause); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/StrictMath.java --- a/emul/src/main/java/java/lang/StrictMath.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1457 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code 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 - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang; - -/** - * The class {@code StrictMath} contains methods for performing basic - * numeric operations such as the elementary exponential, logarithm, - * square root, and trigonometric functions. - * - *

To help ensure portability of Java programs, the definitions of - * some of the numeric functions in this package require that they - * produce the same results as certain published algorithms. These - * algorithms are available from the well-known network library - * {@code netlib} as the package "Freely Distributable Math - * Library," {@code fdlibm}. These - * algorithms, which are written in the C programming language, are - * then to be understood as executed with all floating-point - * operations following the rules of Java floating-point arithmetic. - * - *

The Java math library is defined with respect to - * {@code fdlibm} version 5.3. Where {@code fdlibm} provides - * more than one definition for a function (such as - * {@code acos}), use the "IEEE 754 core function" version - * (residing in a file whose name begins with the letter - * {@code e}). The methods which require {@code fdlibm} - * semantics are {@code sin}, {@code cos}, {@code tan}, - * {@code asin}, {@code acos}, {@code atan}, - * {@code exp}, {@code log}, {@code log10}, - * {@code cbrt}, {@code atan2}, {@code pow}, - * {@code sinh}, {@code cosh}, {@code tanh}, - * {@code hypot}, {@code expm1}, and {@code log1p}. - * - * @author unascribed - * @author Joseph D. Darcy - * @since 1.3 - */ - -public final class StrictMath { - - /** - * Don't let anyone instantiate this class. - */ - private StrictMath() {} - - /** - * The {@code double} value that is closer than any other to - * e, the base of the natural logarithms. - */ - public static final double E = 2.7182818284590452354; - - /** - * The {@code double} value that is closer than any other to - * pi, the ratio of the circumference of a circle to its - * diameter. - */ - public static final double PI = 3.14159265358979323846; - - /** - * Returns the trigonometric sine of an angle. Special cases: - *

  • If the argument is NaN or an infinity, then the - * result is NaN. - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument.
- * - * @param a an angle, in radians. - * @return the sine of the argument. - */ - public static native double sin(double a); - - /** - * Returns the trigonometric cosine of an angle. Special cases: - *
  • If the argument is NaN or an infinity, then the - * result is NaN.
- * - * @param a an angle, in radians. - * @return the cosine of the argument. - */ - public static native double cos(double a); - - /** - * Returns the trigonometric tangent of an angle. Special cases: - *
  • If the argument is NaN or an infinity, then the result - * is NaN. - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument.
- * - * @param a an angle, in radians. - * @return the tangent of the argument. - */ - public static native double tan(double a); - - /** - * Returns the arc sine of a value; the returned angle is in the - * range -pi/2 through pi/2. Special cases: - *
  • If the argument is NaN or its absolute value is greater - * than 1, then the result is NaN. - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument.
- * - * @param a the value whose arc sine is to be returned. - * @return the arc sine of the argument. - */ - public static native double asin(double a); - - /** - * Returns the arc cosine of a value; the returned angle is in the - * range 0.0 through pi. Special case: - *
  • If the argument is NaN or its absolute value is greater - * than 1, then the result is NaN.
- * - * @param a the value whose arc cosine is to be returned. - * @return the arc cosine of the argument. - */ - public static native double acos(double a); - - /** - * Returns the arc tangent of a value; the returned angle is in the - * range -pi/2 through pi/2. Special cases: - *
  • If the argument is NaN, then the result is NaN. - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument.
- * - * @param a the value whose arc tangent is to be returned. - * @return the arc tangent of the argument. - */ - public static native double atan(double a); - - /** - * Converts an angle measured in degrees to an approximately - * equivalent angle measured in radians. The conversion from - * degrees to radians is generally inexact. - * - * @param angdeg an angle, in degrees - * @return the measurement of the angle {@code angdeg} - * in radians. - */ - public static strictfp double toRadians(double angdeg) { - return angdeg / 180.0 * PI; - } - - /** - * Converts an angle measured in radians to an approximately - * equivalent angle measured in degrees. The conversion from - * radians to degrees is generally inexact; users should - * not expect {@code cos(toRadians(90.0))} to exactly - * equal {@code 0.0}. - * - * @param angrad an angle, in radians - * @return the measurement of the angle {@code angrad} - * in degrees. - */ - public static strictfp double toDegrees(double angrad) { - return angrad * 180.0 / PI; - } - - /** - * Returns Euler's number e raised to the power of a - * {@code double} value. Special cases: - *
  • If the argument is NaN, the result is NaN. - *
  • If the argument is positive infinity, then the result is - * positive infinity. - *
  • If the argument is negative infinity, then the result is - * positive zero.
- * - * @param a the exponent to raise e to. - * @return the value e{@code a}, - * where e is the base of the natural logarithms. - */ - public static native double exp(double a); - - /** - * Returns the natural logarithm (base e) of a {@code double} - * value. Special cases: - *
  • If the argument is NaN or less than zero, then the result - * is NaN. - *
  • If the argument is positive infinity, then the result is - * positive infinity. - *
  • If the argument is positive zero or negative zero, then the - * result is negative infinity.
- * - * @param a a value - * @return the value ln {@code a}, the natural logarithm of - * {@code a}. - */ - public static native double log(double a); - - - /** - * Returns the base 10 logarithm of a {@code double} value. - * Special cases: - * - *
  • If the argument is NaN or less than zero, then the result - * is NaN. - *
  • If the argument is positive infinity, then the result is - * positive infinity. - *
  • If the argument is positive zero or negative zero, then the - * result is negative infinity. - *
  • If the argument is equal to 10n for - * integer n, then the result is n. - *
- * - * @param a a value - * @return the base 10 logarithm of {@code a}. - * @since 1.5 - */ - public static native double log10(double a); - - /** - * Returns the correctly rounded positive square root of a - * {@code double} value. - * Special cases: - *
  • If the argument is NaN or less than zero, then the result - * is NaN. - *
  • If the argument is positive infinity, then the result is positive - * infinity. - *
  • If the argument is positive zero or negative zero, then the - * result is the same as the argument.
- * Otherwise, the result is the {@code double} value closest to - * the true mathematical square root of the argument value. - * - * @param a a value. - * @return the positive square root of {@code a}. - */ - public static native double sqrt(double a); - - /** - * Returns the cube root of a {@code double} value. For - * positive finite {@code x}, {@code cbrt(-x) == - * -cbrt(x)}; that is, the cube root of a negative value is - * the negative of the cube root of that value's magnitude. - * Special cases: - * - *
    - * - *
  • If the argument is NaN, then the result is NaN. - * - *
  • If the argument is infinite, then the result is an infinity - * with the same sign as the argument. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
- * - * @param a a value. - * @return the cube root of {@code a}. - * @since 1.5 - */ - public static native double cbrt(double a); - - /** - * Computes the remainder operation on two arguments as prescribed - * by the IEEE 754 standard. - * The remainder value is mathematically equal to - * f1 - f2 × n, - * where n is the mathematical integer closest to the exact - * mathematical value of the quotient {@code f1/f2}, and if two - * mathematical integers are equally close to {@code f1/f2}, - * then n is the integer that is even. If the remainder is - * zero, its sign is the same as the sign of the first argument. - * Special cases: - *
  • If either argument is NaN, or the first argument is infinite, - * or the second argument is positive zero or negative zero, then the - * result is NaN. - *
  • If the first argument is finite and the second argument is - * infinite, then the result is the same as the first argument.
- * - * @param f1 the dividend. - * @param f2 the divisor. - * @return the remainder when {@code f1} is divided by - * {@code f2}. - */ - public static native double IEEEremainder(double f1, double f2); - - /** - * Returns the smallest (closest to negative infinity) - * {@code double} value that is greater than or equal to the - * argument and is equal to a mathematical integer. Special cases: - *
  • If the argument value is already equal to a - * mathematical integer, then the result is the same as the - * argument.
  • If the argument is NaN or an infinity or - * positive zero or negative zero, then the result is the same as - * the argument.
  • If the argument value is less than zero but - * greater than -1.0, then the result is negative zero.
Note - * that the value of {@code StrictMath.ceil(x)} is exactly the - * value of {@code -StrictMath.floor(-x)}. - * - * @param a a value. - * @return the smallest (closest to negative infinity) - * floating-point value that is greater than or equal to - * the argument and is equal to a mathematical integer. - */ - public static double ceil(double a) { - return floorOrCeil(a, -0.0, 1.0, 1.0); - } - - /** - * Returns the largest (closest to positive infinity) - * {@code double} value that is less than or equal to the - * argument and is equal to a mathematical integer. Special cases: - *
  • If the argument value is already equal to a - * mathematical integer, then the result is the same as the - * argument.
  • If the argument is NaN or an infinity or - * positive zero or negative zero, then the result is the same as - * the argument.
- * - * @param a a value. - * @return the largest (closest to positive infinity) - * floating-point value that less than or equal to the argument - * and is equal to a mathematical integer. - */ - public static double floor(double a) { - return floorOrCeil(a, -1.0, 0.0, -1.0); - } - - /** - * Internal method to share logic between floor and ceil. - * - * @param a the value to be floored or ceiled - * @param negativeBoundary result for values in (-1, 0) - * @param positiveBoundary result for values in (0, 1) - * @param increment value to add when the argument is non-integral - */ - private static double floorOrCeil(double a, - double negativeBoundary, - double positiveBoundary, - double sign) { - int exponent = getExponent(a); - - if (exponent < 0) { - /* - * Absolute value of argument is less than 1. - * floorOrceil(-0.0) => -0.0 - * floorOrceil(+0.0) => +0.0 - */ - return ((a == 0.0) ? a : - ( (a < 0.0) ? negativeBoundary : positiveBoundary) ); - } else if (exponent >= 52) { - /* - * Infinity, NaN, or a value so large it must be integral. - */ - return a; - } - // Else the argument is either an integral value already XOR it - // has to be rounded to one. - assert exponent >= 0 && exponent <= 51; - - long doppel = Double.doubleToRawLongBits(a); - long mask = 0; // DoubleConsts.SIGNIF_BIT_MASK >> exponent; - - if ( (mask & doppel) == 0L ) - return a; // integral value - else { - double result = Double.longBitsToDouble(doppel & (~mask)); - if (sign*a > 0.0) - result = result + sign; - return result; - } - } - - /** - * Returns the {@code double} value that is closest in value - * to the argument and is equal to a mathematical integer. If two - * {@code double} values that are mathematical integers are - * equally close to the value of the argument, the result is the - * integer value that is even. Special cases: - *
  • If the argument value is already equal to a mathematical - * integer, then the result is the same as the argument. - *
  • If the argument is NaN or an infinity or positive zero or negative - * zero, then the result is the same as the argument.
- * - * @param a a value. - * @return the closest floating-point value to {@code a} that is - * equal to a mathematical integer. - * @author Joseph D. Darcy - */ - public static double rint(double a) { - throw new UnsupportedOperationException(); - /* - * If the absolute value of a is not less than 2^52, it - * is either a finite integer (the double format does not have - * enough significand bits for a number that large to have any - * fractional portion), an infinity, or a NaN. In any of - * these cases, rint of the argument is the argument. - * - * Otherwise, the sum (twoToThe52 + a ) will properly round - * away any fractional portion of a since ulp(twoToThe52) == - * 1.0; subtracting out twoToThe52 from this sum will then be - * exact and leave the rounded integer portion of a. - * - * This method does *not* need to be declared strictfp to get - * fully reproducible results. Whether or not a method is - * declared strictfp can only make a difference in the - * returned result if some operation would overflow or - * underflow with strictfp semantics. The operation - * (twoToThe52 + a ) cannot overflow since large values of a - * are screened out; the add cannot underflow since twoToThe52 - * is too large. The subtraction ((twoToThe52 + a ) - - * twoToThe52) will be exact as discussed above and thus - * cannot overflow or meaningfully underflow. Finally, the - * last multiply in the return statement is by plus or minus - * 1.0, which is exact too. - */ -// double twoToThe52 = (double)(1L << 52); // 2^52 -// double sign = FpUtils.rawCopySign(1.0, a); // preserve sign info -// a = Math.abs(a); -// -// if (a < twoToThe52) { // E_min <= ilogb(a) <= 51 -// a = ((twoToThe52 + a ) - twoToThe52); -// } -// -// return sign * a; // restore original sign - } - - /** - * Returns the angle theta from the conversion of rectangular - * coordinates ({@code x}, {@code y}) to polar - * coordinates (r, theta). - * This method computes the phase theta by computing an arc tangent - * of {@code y/x} in the range of -pi to pi. Special - * cases: - *
  • If either argument is NaN, then the result is NaN. - *
  • If the first argument is positive zero and the second argument - * is positive, or the first argument is positive and finite and the - * second argument is positive infinity, then the result is positive - * zero. - *
  • If the first argument is negative zero and the second argument - * is positive, or the first argument is negative and finite and the - * second argument is positive infinity, then the result is negative zero. - *
  • If the first argument is positive zero and the second argument - * is negative, or the first argument is positive and finite and the - * second argument is negative infinity, then the result is the - * {@code double} value closest to pi. - *
  • If the first argument is negative zero and the second argument - * is negative, or the first argument is negative and finite and the - * second argument is negative infinity, then the result is the - * {@code double} value closest to -pi. - *
  • If the first argument is positive and the second argument is - * positive zero or negative zero, or the first argument is positive - * infinity and the second argument is finite, then the result is the - * {@code double} value closest to pi/2. - *
  • If the first argument is negative and the second argument is - * positive zero or negative zero, or the first argument is negative - * infinity and the second argument is finite, then the result is the - * {@code double} value closest to -pi/2. - *
  • If both arguments are positive infinity, then the result is the - * {@code double} value closest to pi/4. - *
  • If the first argument is positive infinity and the second argument - * is negative infinity, then the result is the {@code double} - * value closest to 3*pi/4. - *
  • If the first argument is negative infinity and the second argument - * is positive infinity, then the result is the {@code double} value - * closest to -pi/4. - *
  • If both arguments are negative infinity, then the result is the - * {@code double} value closest to -3*pi/4.
- * - * @param y the ordinate coordinate - * @param x the abscissa coordinate - * @return the theta component of the point - * (rtheta) - * in polar coordinates that corresponds to the point - * (xy) in Cartesian coordinates. - */ - public static native double atan2(double y, double x); - - - /** - * Returns the value of the first argument raised to the power of the - * second argument. Special cases: - * - *
  • If the second argument is positive or negative zero, then the - * result is 1.0. - *
  • If the second argument is 1.0, then the result is the same as the - * first argument. - *
  • If the second argument is NaN, then the result is NaN. - *
  • If the first argument is NaN and the second argument is nonzero, - * then the result is NaN. - * - *
  • If - *
      - *
    • the absolute value of the first argument is greater than 1 - * and the second argument is positive infinity, or - *
    • the absolute value of the first argument is less than 1 and - * the second argument is negative infinity, - *
    - * then the result is positive infinity. - * - *
  • If - *
      - *
    • the absolute value of the first argument is greater than 1 and - * the second argument is negative infinity, or - *
    • the absolute value of the - * first argument is less than 1 and the second argument is positive - * infinity, - *
    - * then the result is positive zero. - * - *
  • If the absolute value of the first argument equals 1 and the - * second argument is infinite, then the result is NaN. - * - *
  • If - *
      - *
    • the first argument is positive zero and the second argument - * is greater than zero, or - *
    • the first argument is positive infinity and the second - * argument is less than zero, - *
    - * then the result is positive zero. - * - *
  • If - *
      - *
    • the first argument is positive zero and the second argument - * is less than zero, or - *
    • the first argument is positive infinity and the second - * argument is greater than zero, - *
    - * then the result is positive infinity. - * - *
  • If - *
      - *
    • the first argument is negative zero and the second argument - * is greater than zero but not a finite odd integer, or - *
    • the first argument is negative infinity and the second - * argument is less than zero but not a finite odd integer, - *
    - * then the result is positive zero. - * - *
  • If - *
      - *
    • the first argument is negative zero and the second argument - * is a positive finite odd integer, or - *
    • the first argument is negative infinity and the second - * argument is a negative finite odd integer, - *
    - * then the result is negative zero. - * - *
  • If - *
      - *
    • the first argument is negative zero and the second argument - * is less than zero but not a finite odd integer, or - *
    • the first argument is negative infinity and the second - * argument is greater than zero but not a finite odd integer, - *
    - * then the result is positive infinity. - * - *
  • If - *
      - *
    • the first argument is negative zero and the second argument - * is a negative finite odd integer, or - *
    • the first argument is negative infinity and the second - * argument is a positive finite odd integer, - *
    - * then the result is negative infinity. - * - *
  • If the first argument is finite and less than zero - *
      - *
    • if the second argument is a finite even integer, the - * result is equal to the result of raising the absolute value of - * the first argument to the power of the second argument - * - *
    • if the second argument is a finite odd integer, the result - * is equal to the negative of the result of raising the absolute - * value of the first argument to the power of the second - * argument - * - *
    • if the second argument is finite and not an integer, then - * the result is NaN. - *
    - * - *
  • If both arguments are integers, then the result is exactly equal - * to the mathematical result of raising the first argument to the power - * of the second argument if that result can in fact be represented - * exactly as a {@code double} value.
- * - *

(In the foregoing descriptions, a floating-point value is - * considered to be an integer if and only if it is finite and a - * fixed point of the method {@link #ceil ceil} or, - * equivalently, a fixed point of the method {@link #floor - * floor}. A value is a fixed point of a one-argument - * method if and only if the result of applying the method to the - * value is equal to the value.) - * - * @param a base. - * @param b the exponent. - * @return the value {@code a}{@code b}. - */ - public static native double pow(double a, double b); - - /** - * Returns the closest {@code int} to the argument, with ties - * rounding up. - * - *

Special cases: - *

  • If the argument is NaN, the result is 0. - *
  • If the argument is negative infinity or any value less than or - * equal to the value of {@code Integer.MIN_VALUE}, the result is - * equal to the value of {@code Integer.MIN_VALUE}. - *
  • If the argument is positive infinity or any value greater than or - * equal to the value of {@code Integer.MAX_VALUE}, the result is - * equal to the value of {@code Integer.MAX_VALUE}.
- * - * @param a a floating-point value to be rounded to an integer. - * @return the value of the argument rounded to the nearest - * {@code int} value. - * @see java.lang.Integer#MAX_VALUE - * @see java.lang.Integer#MIN_VALUE - */ - public static int round(float a) { - return Math.round(a); - } - - /** - * Returns the closest {@code long} to the argument, with ties - * rounding up. - * - *

Special cases: - *

  • If the argument is NaN, the result is 0. - *
  • If the argument is negative infinity or any value less than or - * equal to the value of {@code Long.MIN_VALUE}, the result is - * equal to the value of {@code Long.MIN_VALUE}. - *
  • If the argument is positive infinity or any value greater than or - * equal to the value of {@code Long.MAX_VALUE}, the result is - * equal to the value of {@code Long.MAX_VALUE}.
- * - * @param a a floating-point value to be rounded to a - * {@code long}. - * @return the value of the argument rounded to the nearest - * {@code long} value. - * @see java.lang.Long#MAX_VALUE - * @see java.lang.Long#MIN_VALUE - */ - public static long round(double a) { - return Math.round(a); - } - - /** - * Returns a {@code double} value with a positive sign, greater - * than or equal to {@code 0.0} and less than {@code 1.0}. - * Returned values are chosen pseudorandomly with (approximately) - * uniform distribution from that range. - * - *

When this method is first called, it creates a single new - * pseudorandom-number generator, exactly as if by the expression - * - *

{@code new java.util.Random()}
- * - * This new pseudorandom-number generator is used thereafter for - * all calls to this method and is used nowhere else. - * - *

This method is properly synchronized to allow correct use by - * more than one thread. However, if many threads need to generate - * pseudorandom numbers at a great rate, it may reduce contention - * for each thread to have its own pseudorandom number generator. - * - * @return a pseudorandom {@code double} greater than or equal - * to {@code 0.0} and less than {@code 1.0}. - * @see Random#nextDouble() - */ - public static double random() { - throw new UnsupportedOperationException(); - } - - /** - * Returns the absolute value of an {@code int} value.. - * If the argument is not negative, the argument is returned. - * If the argument is negative, the negation of the argument is returned. - * - *

Note that if the argument is equal to the value of - * {@link Integer#MIN_VALUE}, the most negative representable - * {@code int} value, the result is that same value, which is - * negative. - * - * @param a the argument whose absolute value is to be determined. - * @return the absolute value of the argument. - */ - public static int abs(int a) { - return (a < 0) ? -a : a; - } - - /** - * Returns the absolute value of a {@code long} value. - * If the argument is not negative, the argument is returned. - * If the argument is negative, the negation of the argument is returned. - * - *

Note that if the argument is equal to the value of - * {@link Long#MIN_VALUE}, the most negative representable - * {@code long} value, the result is that same value, which - * is negative. - * - * @param a the argument whose absolute value is to be determined. - * @return the absolute value of the argument. - */ - public static long abs(long a) { - return (a < 0) ? -a : a; - } - - /** - * Returns the absolute value of a {@code float} value. - * If the argument is not negative, the argument is returned. - * If the argument is negative, the negation of the argument is returned. - * Special cases: - *

  • If the argument is positive zero or negative zero, the - * result is positive zero. - *
  • If the argument is infinite, the result is positive infinity. - *
  • If the argument is NaN, the result is NaN.
- * In other words, the result is the same as the value of the expression: - *

{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))} - * - * @param a the argument whose absolute value is to be determined - * @return the absolute value of the argument. - */ - public static float abs(float a) { - return (a <= 0.0F) ? 0.0F - a : a; - } - - /** - * Returns the absolute value of a {@code double} value. - * If the argument is not negative, the argument is returned. - * If the argument is negative, the negation of the argument is returned. - * Special cases: - *

  • If the argument is positive zero or negative zero, the result - * is positive zero. - *
  • If the argument is infinite, the result is positive infinity. - *
  • If the argument is NaN, the result is NaN.
- * In other words, the result is the same as the value of the expression: - *

{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)} - * - * @param a the argument whose absolute value is to be determined - * @return the absolute value of the argument. - */ - public static double abs(double a) { - return (a <= 0.0D) ? 0.0D - a : a; - } - - /** - * Returns the greater of two {@code int} values. That is, the - * result is the argument closer to the value of - * {@link Integer#MAX_VALUE}. If the arguments have the same value, - * the result is that same value. - * - * @param a an argument. - * @param b another argument. - * @return the larger of {@code a} and {@code b}. - */ - public static int max(int a, int b) { - return (a >= b) ? a : b; - } - - /** - * Returns the greater of two {@code long} values. That is, the - * result is the argument closer to the value of - * {@link Long#MAX_VALUE}. If the arguments have the same value, - * the result is that same value. - * - * @param a an argument. - * @param b another argument. - * @return the larger of {@code a} and {@code b}. - */ - public static long max(long a, long b) { - return (a >= b) ? a : b; - } - - // Use raw bit-wise conversions on guaranteed non-NaN arguments. - private static long negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f); - private static long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d); - - /** - * Returns the greater of two {@code float} values. That is, - * the result is the argument closer to positive infinity. If the - * arguments have the same value, the result is that same - * value. If either value is NaN, then the result is NaN. Unlike - * the numerical comparison operators, this method considers - * negative zero to be strictly smaller than positive zero. If one - * argument is positive zero and the other negative zero, the - * result is positive zero. - * - * @param a an argument. - * @param b another argument. - * @return the larger of {@code a} and {@code b}. - */ - public static float max(float a, float b) { - if (a != a) - return a; // a is NaN - if ((a == 0.0f) && - (b == 0.0f) && - (Float.floatToRawIntBits(a) == negativeZeroFloatBits)) { - // Raw conversion ok since NaN can't map to -0.0. - return b; - } - return (a >= b) ? a : b; - } - - /** - * Returns the greater of two {@code double} values. That - * is, the result is the argument closer to positive infinity. If - * the arguments have the same value, the result is that same - * value. If either value is NaN, then the result is NaN. Unlike - * the numerical comparison operators, this method considers - * negative zero to be strictly smaller than positive zero. If one - * argument is positive zero and the other negative zero, the - * result is positive zero. - * - * @param a an argument. - * @param b another argument. - * @return the larger of {@code a} and {@code b}. - */ - public static double max(double a, double b) { - if (a != a) - return a; // a is NaN - if ((a == 0.0d) && - (b == 0.0d) && - (Double.doubleToRawLongBits(a) == negativeZeroDoubleBits)) { - // Raw conversion ok since NaN can't map to -0.0. - return b; - } - return (a >= b) ? a : b; - } - - /** - * Returns the smaller of two {@code int} values. That is, - * the result the argument closer to the value of - * {@link Integer#MIN_VALUE}. If the arguments have the same - * value, the result is that same value. - * - * @param a an argument. - * @param b another argument. - * @return the smaller of {@code a} and {@code b}. - */ - public static int min(int a, int b) { - return (a <= b) ? a : b; - } - - /** - * Returns the smaller of two {@code long} values. That is, - * the result is the argument closer to the value of - * {@link Long#MIN_VALUE}. If the arguments have the same - * value, the result is that same value. - * - * @param a an argument. - * @param b another argument. - * @return the smaller of {@code a} and {@code b}. - */ - public static long min(long a, long b) { - return (a <= b) ? a : b; - } - - /** - * Returns the smaller of two {@code float} values. That is, - * the result is the value closer to negative infinity. If the - * arguments have the same value, the result is that same - * value. If either value is NaN, then the result is NaN. Unlike - * the numerical comparison operators, this method considers - * negative zero to be strictly smaller than positive zero. If - * one argument is positive zero and the other is negative zero, - * the result is negative zero. - * - * @param a an argument. - * @param b another argument. - * @return the smaller of {@code a} and {@code b.} - */ - public static float min(float a, float b) { - if (a != a) - return a; // a is NaN - if ((a == 0.0f) && - (b == 0.0f) && - (Float.floatToRawIntBits(b) == negativeZeroFloatBits)) { - // Raw conversion ok since NaN can't map to -0.0. - return b; - } - return (a <= b) ? a : b; - } - - /** - * Returns the smaller of two {@code double} values. That - * is, the result is the value closer to negative infinity. If the - * arguments have the same value, the result is that same - * value. If either value is NaN, then the result is NaN. Unlike - * the numerical comparison operators, this method considers - * negative zero to be strictly smaller than positive zero. If one - * argument is positive zero and the other is negative zero, the - * result is negative zero. - * - * @param a an argument. - * @param b another argument. - * @return the smaller of {@code a} and {@code b}. - */ - public static double min(double a, double b) { - if (a != a) - return a; // a is NaN - if ((a == 0.0d) && - (b == 0.0d) && - (Double.doubleToRawLongBits(b) == negativeZeroDoubleBits)) { - // Raw conversion ok since NaN can't map to -0.0. - return b; - } - return (a <= b) ? a : b; - } - - /** - * Returns the size of an ulp of the argument. An ulp of a - * {@code double} value is the positive distance between this - * floating-point value and the {@code double} value next - * larger in magnitude. Note that for non-NaN x, - * ulp(-x) == ulp(x). - * - *

Special Cases: - *

    - *
  • If the argument is NaN, then the result is NaN. - *
  • If the argument is positive or negative infinity, then the - * result is positive infinity. - *
  • If the argument is positive or negative zero, then the result is - * {@code Double.MIN_VALUE}. - *
  • If the argument is ±{@code Double.MAX_VALUE}, then - * the result is equal to 2971. - *
- * - * @param d the floating-point value whose ulp is to be returned - * @return the size of an ulp of the argument - * @author Joseph D. Darcy - * @since 1.5 - */ - public static double ulp(double d) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the size of an ulp of the argument. An ulp of a - * {@code float} value is the positive distance between this - * floating-point value and the {@code float} value next - * larger in magnitude. Note that for non-NaN x, - * ulp(-x) == ulp(x). - * - *

Special Cases: - *

    - *
  • If the argument is NaN, then the result is NaN. - *
  • If the argument is positive or negative infinity, then the - * result is positive infinity. - *
  • If the argument is positive or negative zero, then the result is - * {@code Float.MIN_VALUE}. - *
  • If the argument is ±{@code Float.MAX_VALUE}, then - * the result is equal to 2104. - *
- * - * @param f the floating-point value whose ulp is to be returned - * @return the size of an ulp of the argument - * @author Joseph D. Darcy - * @since 1.5 - */ - public static float ulp(float f) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the signum function of the argument; zero if the argument - * is zero, 1.0 if the argument is greater than zero, -1.0 if the - * argument is less than zero. - * - *

Special Cases: - *

    - *
  • If the argument is NaN, then the result is NaN. - *
  • If the argument is positive zero or negative zero, then the - * result is the same as the argument. - *
- * - * @param d the floating-point value whose signum is to be returned - * @return the signum function of the argument - * @author Joseph D. Darcy - * @since 1.5 - */ - public static double signum(double d) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the signum function of the argument; zero if the argument - * is zero, 1.0f if the argument is greater than zero, -1.0f if the - * argument is less than zero. - * - *

Special Cases: - *

    - *
  • If the argument is NaN, then the result is NaN. - *
  • If the argument is positive zero or negative zero, then the - * result is the same as the argument. - *
- * - * @param f the floating-point value whose signum is to be returned - * @return the signum function of the argument - * @author Joseph D. Darcy - * @since 1.5 - */ - public static float signum(float f) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the hyperbolic sine of a {@code double} value. - * The hyperbolic sine of x is defined to be - * (ex - e-x)/2 - * where e is {@linkplain Math#E Euler's number}. - * - *

Special cases: - *

    - * - *
  • If the argument is NaN, then the result is NaN. - * - *
  • If the argument is infinite, then the result is an infinity - * with the same sign as the argument. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
- * - * @param x The number whose hyperbolic sine is to be returned. - * @return The hyperbolic sine of {@code x}. - * @since 1.5 - */ - public static native double sinh(double x); - - /** - * Returns the hyperbolic cosine of a {@code double} value. - * The hyperbolic cosine of x is defined to be - * (ex + e-x)/2 - * where e is {@linkplain Math#E Euler's number}. - * - *

Special cases: - *

    - * - *
  • If the argument is NaN, then the result is NaN. - * - *
  • If the argument is infinite, then the result is positive - * infinity. - * - *
  • If the argument is zero, then the result is {@code 1.0}. - * - *
- * - * @param x The number whose hyperbolic cosine is to be returned. - * @return The hyperbolic cosine of {@code x}. - * @since 1.5 - */ - public static native double cosh(double x); - - /** - * Returns the hyperbolic tangent of a {@code double} value. - * The hyperbolic tangent of x is defined to be - * (ex - e-x)/(ex + e-x), - * in other words, {@linkplain Math#sinh - * sinh(x)}/{@linkplain Math#cosh cosh(x)}. Note - * that the absolute value of the exact tanh is always less than - * 1. - * - *

Special cases: - *

    - * - *
  • If the argument is NaN, then the result is NaN. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
  • If the argument is positive infinity, then the result is - * {@code +1.0}. - * - *
  • If the argument is negative infinity, then the result is - * {@code -1.0}. - * - *
- * - * @param x The number whose hyperbolic tangent is to be returned. - * @return The hyperbolic tangent of {@code x}. - * @since 1.5 - */ - public static native double tanh(double x); - - /** - * Returns sqrt(x2 +y2) - * without intermediate overflow or underflow. - * - *

Special cases: - *

    - * - *
  • If either argument is infinite, then the result - * is positive infinity. - * - *
  • If either argument is NaN and neither argument is infinite, - * then the result is NaN. - * - *
- * - * @param x a value - * @param y a value - * @return sqrt(x2 +y2) - * without intermediate overflow or underflow - * @since 1.5 - */ - public static native double hypot(double x, double y); - - /** - * Returns ex -1. Note that for values of - * x near 0, the exact sum of - * {@code expm1(x)} + 1 is much closer to the true - * result of ex than {@code exp(x)}. - * - *

Special cases: - *

    - *
  • If the argument is NaN, the result is NaN. - * - *
  • If the argument is positive infinity, then the result is - * positive infinity. - * - *
  • If the argument is negative infinity, then the result is - * -1.0. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
- * - * @param x the exponent to raise e to in the computation of - * e{@code x} -1. - * @return the value e{@code x} - 1. - * @since 1.5 - */ - public static native double expm1(double x); - - /** - * Returns the natural logarithm of the sum of the argument and 1. - * Note that for small values {@code x}, the result of - * {@code log1p(x)} is much closer to the true result of ln(1 - * + {@code x}) than the floating-point evaluation of - * {@code log(1.0+x)}. - * - *

Special cases: - *

    - * - *
  • If the argument is NaN or less than -1, then the result is - * NaN. - * - *
  • If the argument is positive infinity, then the result is - * positive infinity. - * - *
  • If the argument is negative one, then the result is - * negative infinity. - * - *
  • If the argument is zero, then the result is a zero with the - * same sign as the argument. - * - *
- * - * @param x a value - * @return the value ln({@code x} + 1), the natural - * log of {@code x} + 1 - * @since 1.5 - */ - public static native double log1p(double x); - - /** - * Returns the first floating-point argument with the sign of the - * second floating-point argument. For this method, a NaN - * {@code sign} argument is always treated as if it were - * positive. - * - * @param magnitude the parameter providing the magnitude of the result - * @param sign the parameter providing the sign of the result - * @return a value with the magnitude of {@code magnitude} - * and the sign of {@code sign}. - * @since 1.6 - */ - public static double copySign(double magnitude, double sign) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the first floating-point argument with the sign of the - * second floating-point argument. For this method, a NaN - * {@code sign} argument is always treated as if it were - * positive. - * - * @param magnitude the parameter providing the magnitude of the result - * @param sign the parameter providing the sign of the result - * @return a value with the magnitude of {@code magnitude} - * and the sign of {@code sign}. - * @since 1.6 - */ - public static float copySign(float magnitude, float sign) { - throw new UnsupportedOperationException(); - } - /** - * Returns the unbiased exponent used in the representation of a - * {@code float}. Special cases: - * - *
    - *
  • If the argument is NaN or infinite, then the result is - * {@link Float#MAX_EXPONENT} + 1. - *
  • If the argument is zero or subnormal, then the result is - * {@link Float#MIN_EXPONENT} -1. - *
- * @param f a {@code float} value - * @since 1.6 - */ - public static int getExponent(float f) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the unbiased exponent used in the representation of a - * {@code double}. Special cases: - * - *
    - *
  • If the argument is NaN or infinite, then the result is - * {@link Double#MAX_EXPONENT} + 1. - *
  • If the argument is zero or subnormal, then the result is - * {@link Double#MIN_EXPONENT} -1. - *
- * @param d a {@code double} value - * @since 1.6 - */ - public static int getExponent(double d) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the floating-point number adjacent to the first - * argument in the direction of the second argument. If both - * arguments compare as equal the second argument is returned. - * - *

Special cases: - *

    - *
  • If either argument is a NaN, then NaN is returned. - * - *
  • If both arguments are signed zeros, {@code direction} - * is returned unchanged (as implied by the requirement of - * returning the second argument if the arguments compare as - * equal). - * - *
  • If {@code start} is - * ±{@link Double#MIN_VALUE} and {@code direction} - * has a value such that the result should have a smaller - * magnitude, then a zero with the same sign as {@code start} - * is returned. - * - *
  • If {@code start} is infinite and - * {@code direction} has a value such that the result should - * have a smaller magnitude, {@link Double#MAX_VALUE} with the - * same sign as {@code start} is returned. - * - *
  • If {@code start} is equal to ± - * {@link Double#MAX_VALUE} and {@code direction} has a - * value such that the result should have a larger magnitude, an - * infinity with same sign as {@code start} is returned. - *
- * - * @param start starting floating-point value - * @param direction value indicating which of - * {@code start}'s neighbors or {@code start} should - * be returned - * @return The floating-point number adjacent to {@code start} in the - * direction of {@code direction}. - * @since 1.6 - */ - public static double nextAfter(double start, double direction) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the floating-point number adjacent to the first - * argument in the direction of the second argument. If both - * arguments compare as equal a value equivalent to the second argument - * is returned. - * - *

Special cases: - *

    - *
  • If either argument is a NaN, then NaN is returned. - * - *
  • If both arguments are signed zeros, a value equivalent - * to {@code direction} is returned. - * - *
  • If {@code start} is - * ±{@link Float#MIN_VALUE} and {@code direction} - * has a value such that the result should have a smaller - * magnitude, then a zero with the same sign as {@code start} - * is returned. - * - *
  • If {@code start} is infinite and - * {@code direction} has a value such that the result should - * have a smaller magnitude, {@link Float#MAX_VALUE} with the - * same sign as {@code start} is returned. - * - *
  • If {@code start} is equal to ± - * {@link Float#MAX_VALUE} and {@code direction} has a - * value such that the result should have a larger magnitude, an - * infinity with same sign as {@code start} is returned. - *
- * - * @param start starting floating-point value - * @param direction value indicating which of - * {@code start}'s neighbors or {@code start} should - * be returned - * @return The floating-point number adjacent to {@code start} in the - * direction of {@code direction}. - * @since 1.6 - */ - public static float nextAfter(float start, double direction) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the floating-point value adjacent to {@code d} in - * the direction of positive infinity. This method is - * semantically equivalent to {@code nextAfter(d, - * Double.POSITIVE_INFINITY)}; however, a {@code nextUp} - * implementation may run faster than its equivalent - * {@code nextAfter} call. - * - *

Special Cases: - *

    - *
  • If the argument is NaN, the result is NaN. - * - *
  • If the argument is positive infinity, the result is - * positive infinity. - * - *
  • If the argument is zero, the result is - * {@link Double#MIN_VALUE} - * - *
- * - * @param d starting floating-point value - * @return The adjacent floating-point value closer to positive - * infinity. - * @since 1.6 - */ - public static double nextUp(double d) { - throw new UnsupportedOperationException(); - } - - /** - * Returns the floating-point value adjacent to {@code f} in - * the direction of positive infinity. This method is - * semantically equivalent to {@code nextAfter(f, - * Float.POSITIVE_INFINITY)}; however, a {@code nextUp} - * implementation may run faster than its equivalent - * {@code nextAfter} call. - * - *

Special Cases: - *

    - *
  • If the argument is NaN, the result is NaN. - * - *
  • If the argument is positive infinity, the result is - * positive infinity. - * - *
  • If the argument is zero, the result is - * {@link Float#MIN_VALUE} - * - *
- * - * @param f starting floating-point value - * @return The adjacent floating-point value closer to positive - * infinity. - * @since 1.6 - */ - public static float nextUp(float f) { - throw new UnsupportedOperationException(); - } - - - /** - * Return {@code d} × - * 2{@code scaleFactor} rounded as if performed - * by a single correctly rounded floating-point multiply to a - * member of the double value set. See the Java - * Language Specification for a discussion of floating-point - * value sets. If the exponent of the result is between {@link - * Double#MIN_EXPONENT} and {@link Double#MAX_EXPONENT}, the - * answer is calculated exactly. If the exponent of the result - * would be larger than {@code Double.MAX_EXPONENT}, an - * infinity is returned. Note that if the result is subnormal, - * precision may be lost; that is, when {@code scalb(x, n)} - * is subnormal, {@code scalb(scalb(x, n), -n)} may not equal - * x. When the result is non-NaN, the result has the same - * sign as {@code d}. - * - *

Special cases: - *

    - *
  • If the first argument is NaN, NaN is returned. - *
  • If the first argument is infinite, then an infinity of the - * same sign is returned. - *
  • If the first argument is zero, then a zero of the same - * sign is returned. - *
- * - * @param d number to be scaled by a power of two. - * @param scaleFactor power of 2 used to scale {@code d} - * @return {@code d} × 2{@code scaleFactor} - * @since 1.6 - */ - public static double scalb(double d, int scaleFactor) { - throw new UnsupportedOperationException(); - } - - /** - * Return {@code f} × - * 2{@code scaleFactor} rounded as if performed - * by a single correctly rounded floating-point multiply to a - * member of the float value set. See the Java - * Language Specification for a discussion of floating-point - * value sets. If the exponent of the result is between {@link - * Float#MIN_EXPONENT} and {@link Float#MAX_EXPONENT}, the - * answer is calculated exactly. If the exponent of the result - * would be larger than {@code Float.MAX_EXPONENT}, an - * infinity is returned. Note that if the result is subnormal, - * precision may be lost; that is, when {@code scalb(x, n)} - * is subnormal, {@code scalb(scalb(x, n), -n)} may not equal - * x. When the result is non-NaN, the result has the same - * sign as {@code f}. - * - *

Special cases: - *

    - *
  • If the first argument is NaN, NaN is returned. - *
  • If the first argument is infinite, then an infinity of the - * same sign is returned. - *
  • If the first argument is zero, then a zero of the same - * sign is returned. - *
- * - * @param f number to be scaled by a power of two. - * @param scaleFactor power of 2 used to scale {@code f} - * @return {@code f} × 2{@code scaleFactor} - * @since 1.6 - */ - public static float scalb(float f, int scaleFactor) { - throw new UnsupportedOperationException(); - } -} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/String.java --- a/emul/src/main/java/java/lang/String.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/String.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,8 +25,11 @@ package java.lang; +import java.util.Comparator; import org.apidesign.bck2brwsr.core.ExtraJavaScript; -import java.util.Comparator; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.core.JavaScriptOnly; +import org.apidesign.bck2brwsr.core.JavaScriptPrototype; /** * The String class represents character strings. All @@ -99,25 +102,25 @@ @ExtraJavaScript( resource="/org/apidesign/vm4brwsr/emul/java_lang_String.js", - processByteCode=false + processByteCode=true ) +@JavaScriptPrototype(container = "String.prototype", prototype = "new String") public final class String implements java.io.Serializable, Comparable, CharSequence { - /** The value is used for character storage. */ - private final char value[]; - - /** The offset is the first index of the storage that is used. */ - private final int offset; - - /** The count is the number of characters in the String. */ - private final int count; - - /** Cache the hash code for the string */ - private int hash; // Default to 0 + /** real string to delegate to */ + private Object r; /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -6849794470754667710L; + + @JavaScriptOnly(name="toString", value="function() { return this.fld_r; }") + private static void jsToString() { + } + + @JavaScriptOnly(name="valueOf", value="function() { return this.toString().valueOf(); }") + private static void jsValudOf() { + } /** * Class String is special cased within the Serialization Stream Protocol. @@ -140,9 +143,7 @@ * unnecessary since Strings are immutable. */ public String() { - this.offset = 0; - this.count = 0; - this.value = new char[0]; + this.r = ""; } /** @@ -156,23 +157,7 @@ * A {@code String} */ public String(String original) { - int size = original.count; - char[] originalValue = original.value; - char[] v; - if (originalValue.length > size) { - // The array representing the String is bigger than the new - // String itself. Perhaps this constructor is being called - // in order to trim the baggage, so make a copy of the array. - int off = original.offset; - v = copyOfRange(originalValue, off, off+size); - } else { - // The array representing the String is the same - // size as the String, so no point in making a copy. - v = originalValue; - } - this.offset = 0; - this.count = size; - this.value = v; + this.r = original.toString(); } /** @@ -184,11 +169,13 @@ * @param value * The initial value of the string */ + @JavaScriptBody(args = { "charArr" }, body= + "for (var i = 0; i < charArr.length; i++) {\n" + + " if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n" + + "}\n" + + "this.fld_r = charArr.join('');\n" + ) public String(char value[]) { - int size = value.length; - this.offset = 0; - this.count = size; - this.value = copyOf(value, size); } /** @@ -212,20 +199,14 @@ * If the {@code offset} and {@code count} arguments index * characters outside the bounds of the {@code value} array */ + @JavaScriptBody(args = { "charArr", "off", "cnt" }, body = + "var up = off + cnt;\n" + + "for (var i = off; i < up; i++) {\n" + + " if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n" + + "}\n" + + "this.fld_r = charArr.slice(off, up).join(\"\");\n" + ) public String(char value[], int offset, int count) { - if (offset < 0) { - throw new StringIndexOutOfBoundsException(offset); - } - if (count < 0) { - throw new StringIndexOutOfBoundsException(count); - } - // Note: offset or count might be near -1>>>1. - if (offset > value.length - count) { - throw new StringIndexOutOfBoundsException(offset + count); - } - this.offset = 0; - this.count = count; - this.value = copyOfRange(value, offset, offset+count); } /** @@ -292,9 +273,7 @@ Character.toSurrogates(c, v, j++); } - this.value = v; - this.count = n; - this.offset = 0; + this.r = new String(v, 0, n); } /** @@ -351,9 +330,7 @@ value[i] = (char) (hibyte | (ascii[i + offset] & 0xff)); } } - this.offset = 0; - this.count = count; - this.value = value; + this.r = new String(value, 0, count); } /** @@ -578,9 +555,7 @@ for (int i = 0; i < length; i++) { v[i] = (char)bytes[offset++]; } - this.offset = 0; - this.count = v.length; - this.value = v; + this.r = new String(v, 0, v.length); } /** @@ -613,10 +588,7 @@ * A {@code StringBuffer} */ public String(StringBuffer buffer) { - String result = buffer.toString(); - this.value = result.value; - this.count = result.count; - this.offset = result.offset; + this.r = buffer.toString(); } /** @@ -635,18 +607,7 @@ * @since 1.5 */ public String(StringBuilder builder) { - String result = builder.toString(); - this.value = result.value; - this.count = result.count; - this.offset = result.offset; - } - - - // Package private constructor which shares value array for speed. - String(int offset, int count, char value[]) { - this.value = value; - this.offset = offset; - this.count = count; + this.r = builder.toString(); } /** @@ -657,8 +618,9 @@ * @return the length of the sequence of characters represented by this * object. */ + @JavaScriptBody(args = {}, body = "return this.toString().length;") public int length() { - return count; + throw new UnsupportedOperationException(); } /** @@ -669,8 +631,9 @@ * * @since 1.6 */ + @JavaScriptBody(args = {}, body="return this.toString().length === 0;") public boolean isEmpty() { - return count == 0; + return length() == 0; } /** @@ -691,11 +654,11 @@ * argument is negative or not less than the length of this * string. */ + @JavaScriptBody(args = { "index" }, + body = "return this.toString().charCodeAt(index);" + ) public char charAt(int index) { - if ((index < 0) || (index >= count)) { - throw new StringIndexOutOfBoundsException(index); - } - return value[index + offset]; + throw new UnsupportedOperationException(); } /** @@ -721,10 +684,10 @@ * @since 1.5 */ public int codePointAt(int index) { - if ((index < 0) || (index >= count)) { + if ((index < 0) || (index >= length())) { throw new StringIndexOutOfBoundsException(index); } - return Character.codePointAtImpl(value, offset + index, offset + count); + return Character.codePointAtImpl(toCharArray(), offset() + index, offset() + length()); } /** @@ -751,10 +714,10 @@ */ public int codePointBefore(int index) { int i = index - 1; - if ((i < 0) || (i >= count)) { + if ((i < 0) || (i >= length())) { throw new StringIndexOutOfBoundsException(index); } - return Character.codePointBeforeImpl(value, offset + index, offset); + return Character.codePointBeforeImpl(toCharArray(), offset() + index, offset()); } /** @@ -779,10 +742,10 @@ * @since 1.5 */ public int codePointCount(int beginIndex, int endIndex) { - if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { + if (beginIndex < 0 || endIndex > length() || beginIndex > endIndex) { throw new IndexOutOfBoundsException(); } - return Character.codePointCountImpl(value, offset+beginIndex, endIndex-beginIndex); + return Character.codePointCountImpl(toCharArray(), offset()+beginIndex, endIndex-beginIndex); } /** @@ -806,19 +769,25 @@ * @since 1.5 */ public int offsetByCodePoints(int index, int codePointOffset) { - if (index < 0 || index > count) { + if (index < 0 || index > length()) { throw new IndexOutOfBoundsException(); } - return Character.offsetByCodePointsImpl(value, offset, count, - offset+index, codePointOffset) - offset; + return Character.offsetByCodePointsImpl(toCharArray(), offset(), length(), + offset()+index, codePointOffset) - offset(); } /** * Copy characters from this string into dst starting at dstBegin. * This method doesn't perform any range checking. */ + @JavaScriptBody(args = { "arr", "to" }, body = + "var s = this.toString();\n" + + "for (var i = 0; i < s.length; i++) {\n" + + " arr[to++] = s[i];\n" + + "}" + ) void getChars(char dst[], int dstBegin) { - arraycopy(value, offset, dst, dstBegin, count); + AbstractStringBuilder.arraycopy(toCharArray(), offset(), dst, dstBegin, length()); } /** @@ -851,17 +820,23 @@ *
  • dstBegin+(srcEnd-srcBegin) is larger than * dst.length */ + @JavaScriptBody(args = { "beg", "end", "arr", "dst" }, body= + "var s = this.toString();\n" + + "while (beg < end) {\n" + + " arr[dst++] = s[beg++];\n" + + "}\n" + ) public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); } - if (srcEnd > count) { + if (srcEnd > length()) { throw new StringIndexOutOfBoundsException(srcEnd); } if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } - arraycopy(value, offset + srcBegin, dst, dstBegin, + AbstractStringBuilder.arraycopy(toCharArray(), offset() + srcBegin, dst, dstBegin, srcEnd - srcBegin); } @@ -913,16 +888,16 @@ if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); } - if (srcEnd > count) { + if (srcEnd > length()) { throw new StringIndexOutOfBoundsException(srcEnd); } if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } int j = dstBegin; - int n = offset + srcEnd; - int i = offset + srcBegin; - char[] val = value; /* avoid getfield opcode */ + int n = offset() + srcEnd; + int i = offset() + srcBegin; + char[] val = toCharArray(); /* avoid getfield opcode */ while (i < n) { dst[j++] = (byte)val[i++]; @@ -1018,18 +993,22 @@ * @see #compareTo(String) * @see #equalsIgnoreCase(String) */ + @JavaScriptBody(args = { "obj" }, body = + "return obj != null && obj.$instOf_java_lang_String && " + + "this.toString() === obj.toString();" + ) public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; - int n = count; - if (n == anotherString.count) { - char v1[] = value; - char v2[] = anotherString.value; - int i = offset; - int j = anotherString.offset; + int n = length(); + if (n == anotherString.length()) { + char v1[] = toCharArray(); + char v2[] = anotherString.toCharArray(); + int i = offset(); + int j = anotherString.offset(); while (n-- != 0) { if (v1[i++] != v2[j++]) return false; @@ -1075,15 +1054,15 @@ * @since 1.5 */ public boolean contentEquals(CharSequence cs) { - if (count != cs.length()) + if (length() != cs.length()) return false; // Argument is a StringBuffer, StringBuilder if (cs instanceof AbstractStringBuilder) { - char v1[] = value; + char v1[] = toCharArray(); char v2[] = ((AbstractStringBuilder)cs).getValue(); - int i = offset; + int i = offset(); int j = 0; - int n = count; + int n = length(); while (n-- != 0) { if (v1[i++] != v2[j++]) return false; @@ -1094,10 +1073,10 @@ if (cs.equals(this)) return true; // Argument is a generic CharSequence - char v1[] = value; - int i = offset; + char v1[] = toCharArray(); + int i = offset(); int j = 0; - int n = count; + int n = length(); while (n-- != 0) { if (v1[i++] != cs.charAt(j++)) return false; @@ -1135,8 +1114,8 @@ */ public boolean equalsIgnoreCase(String anotherString) { return (this == anotherString) ? true : - (anotherString != null) && (anotherString.count == count) && - regionMatches(true, 0, anotherString, 0, count); + (anotherString != null) && (anotherString.length() == length()) && + regionMatches(true, 0, anotherString, 0, length()); } /** @@ -1181,13 +1160,13 @@ * lexicographically greater than the string argument. */ public int compareTo(String anotherString) { - int len1 = count; - int len2 = anotherString.count; + int len1 = length(); + int len2 = anotherString.length(); int n = Math.min(len1, len2); - char v1[] = value; - char v2[] = anotherString.value; - int i = offset; - int j = anotherString.offset; + char v1[] = toCharArray(); + char v2[] = anotherString.toCharArray(); + int i = offset(); + int j = anotherString.offset(); if (i == j) { int k = i; @@ -1226,6 +1205,11 @@ */ public static final Comparator CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); + + private static int offset() { + return 0; + } + private static class CaseInsensitiveComparator implements Comparator, java.io.Serializable { // use serialVersionUID from JDK 1.2.2 for interoperability @@ -1312,13 +1296,13 @@ */ public boolean regionMatches(int toffset, String other, int ooffset, int len) { - char ta[] = value; - int to = offset + toffset; - char pa[] = other.value; - int po = other.offset + ooffset; + char ta[] = toCharArray(); + int to = offset() + toffset; + char pa[] = other.toCharArray(); + int po = other.offset() + ooffset; // Note: toffset, ooffset, or len might be near -1>>>1. - if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) - || (ooffset > (long)other.count - len)) { + if ((ooffset < 0) || (toffset < 0) || (toffset > (long)length() - len) + || (ooffset > (long)other.length() - len)) { return false; } while (len-- > 0) { @@ -1381,13 +1365,13 @@ */ public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) { - char ta[] = value; - int to = offset + toffset; - char pa[] = other.value; - int po = other.offset + ooffset; + char ta[] = toCharArray(); + int to = offset() + toffset; + char pa[] = other.toCharArray(); + int po = other.offset() + ooffset; // Note: toffset, ooffset, or len might be near -1>>>1. - if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) || - (ooffset > (long)other.count - len)) { + if ((ooffset < 0) || (toffset < 0) || (toffset > (long)length() - len) || + (ooffset > (long)other.length() - len)) { return false; } while (len-- > 0) { @@ -1436,14 +1420,18 @@ * this.substring(toffset).startsWith(prefix) * */ + @JavaScriptBody(args = { "find", "from" }, body= + "find = find.toString();\n" + + "return this.toString().substring(from, from + find.length) === find;\n" + ) public boolean startsWith(String prefix, int toffset) { - char ta[] = value; - int to = offset + toffset; - char pa[] = prefix.value; - int po = prefix.offset; - int pc = prefix.count; + char ta[] = toCharArray(); + int to = offset() + toffset; + char pa[] = prefix.toCharArray(); + int po = prefix.offset(); + int pc = prefix.length(); // Note: toffset might be near -1>>>1. - if ((toffset < 0) || (toffset > count - pc)) { + if ((toffset < 0) || (toffset > length() - pc)) { return false; } while (--pc >= 0) { @@ -1483,7 +1471,7 @@ * as determined by the {@link #equals(Object)} method. */ public boolean endsWith(String suffix) { - return startsWith(suffix, count - suffix.count); + return startsWith(suffix, length() - suffix.length()); } /** @@ -1500,16 +1488,17 @@ * @return a hash code value for this object. */ public int hashCode() { - int h = hash; - if (h == 0 && count > 0) { - int off = offset; - char val[] = value; - int len = count; + return super.hashCode(); + } + int computeHashCode() { + int h = 0; + if (h == 0 && length() > 0) { + int off = offset(); + int len = length(); for (int i = 0; i < len; i++) { - h = 31*h + val[off++]; + h = 31*h + charAt(off++); } - hash = h; } return h; } @@ -1581,10 +1570,14 @@ * than or equal to fromIndex, or -1 * if the character does not occur. */ + @JavaScriptBody(args = { "ch", "from" }, body = + "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" + + "return this.toString().indexOf(ch, from);\n" + ) public int indexOf(int ch, int fromIndex) { if (fromIndex < 0) { fromIndex = 0; - } else if (fromIndex >= count) { + } else if (fromIndex >= length()) { // Note: fromIndex might be near -1>>>1. return -1; } @@ -1592,9 +1585,9 @@ if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { // handle most cases here (ch is a BMP code point or a // negative value (invalid code point)) - final char[] value = this.value; - final int offset = this.offset; - final int max = offset + count; + final char[] value = this.toCharArray(); + final int offset = this.offset(); + final int max = offset + length(); for (int i = offset + fromIndex; i < max ; i++) { if (value[i] == ch) { return i - offset; @@ -1611,11 +1604,11 @@ */ private int indexOfSupplementary(int ch, int fromIndex) { if (Character.isValidCodePoint(ch)) { - final char[] value = this.value; - final int offset = this.offset; + final char[] value = this.toCharArray(); + final int offset = this.offset(); final char hi = Character.highSurrogate(ch); final char lo = Character.lowSurrogate(ch); - final int max = offset + count - 1; + final int max = offset + length() - 1; for (int i = offset + fromIndex; i < max; i++) { if (value[i] == hi && value[i+1] == lo) { return i - offset; @@ -1649,7 +1642,7 @@ * -1 if the character does not occur. */ public int lastIndexOf(int ch) { - return lastIndexOf(ch, count - 1); + return lastIndexOf(ch, length() - 1); } /** @@ -1686,13 +1679,17 @@ * than or equal to fromIndex, or -1 * if the character does not occur before that point. */ + @JavaScriptBody(args = { "ch", "from" }, body = + "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" + + "return this.toString().lastIndexOf(ch, from);" + ) public int lastIndexOf(int ch, int fromIndex) { if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { // handle most cases here (ch is a BMP code point or a // negative value (invalid code point)) - final char[] value = this.value; - final int offset = this.offset; - int i = offset + Math.min(fromIndex, count - 1); + final char[] value = this.toCharArray(); + final int offset = this.offset(); + int i = offset + Math.min(fromIndex, length() - 1); for (; i >= offset ; i--) { if (value[i] == ch) { return i - offset; @@ -1709,11 +1706,11 @@ */ private int lastIndexOfSupplementary(int ch, int fromIndex) { if (Character.isValidCodePoint(ch)) { - final char[] value = this.value; - final int offset = this.offset; + final char[] value = this.toCharArray(); + final int offset = this.offset(); char hi = Character.highSurrogate(ch); char lo = Character.lowSurrogate(ch); - int i = offset + Math.min(fromIndex, count - 2); + int i = offset + Math.min(fromIndex, length() - 2); for (; i >= offset; i--) { if (value[i] == hi && value[i+1] == lo) { return i - offset; @@ -1757,61 +1754,10 @@ * starting at the specified index, * or {@code -1} if there is no such occurrence. */ - public int indexOf(String str, int fromIndex) { - return indexOf(value, offset, count, - str.value, str.offset, str.count, fromIndex); - } - - /** - * Code shared by String and StringBuffer to do searches. The - * source is the character array being searched, and the target - * is the string being searched for. - * - * @param source the characters being searched. - * @param sourceOffset offset of the source string. - * @param sourceCount count of the source string. - * @param target the characters being searched for. - * @param targetOffset offset of the target string. - * @param targetCount count of the target string. - * @param fromIndex the index to begin searching from. - */ - static int indexOf(char[] source, int sourceOffset, int sourceCount, - char[] target, int targetOffset, int targetCount, - int fromIndex) { - if (fromIndex >= sourceCount) { - return (targetCount == 0 ? sourceCount : -1); - } - if (fromIndex < 0) { - fromIndex = 0; - } - if (targetCount == 0) { - return fromIndex; - } - - char first = target[targetOffset]; - int max = sourceOffset + (sourceCount - targetCount); - - for (int i = sourceOffset + fromIndex; i <= max; i++) { - /* Look for first character. */ - if (source[i] != first) { - while (++i <= max && source[i] != first); - } - - /* Found first character, now look at the rest of v2 */ - if (i <= max) { - int j = i + 1; - int end = j + targetCount - 1; - for (int k = targetOffset + 1; j < end && source[j] == - target[k]; j++, k++); - - if (j == end) { - /* Found whole string. */ - return i - sourceOffset; - } - } - } - return -1; - } + @JavaScriptBody(args = { "str", "fromIndex" }, body = + "return this.toString().indexOf(str.toString(), fromIndex);" + ) + public native int indexOf(String str, int fromIndex); /** * Returns the index within this string of the last occurrence of the @@ -1829,7 +1775,7 @@ * or {@code -1} if there is no such occurrence. */ public int lastIndexOf(String str) { - return lastIndexOf(str, count); + return lastIndexOf(str, length()); } /** @@ -1848,9 +1794,11 @@ * searching backward from the specified index, * or {@code -1} if there is no such occurrence. */ + @JavaScriptBody(args = { "s", "from" }, body = + "return this.toString().lastIndexOf(s.toString(), from);" + ) public int lastIndexOf(String str, int fromIndex) { - return lastIndexOf(value, offset, count, - str.value, str.offset, str.count, fromIndex); + return lastIndexOf(toCharArray(), offset(), length(), str.toCharArray(), str.offset(), str.length(), fromIndex); } /** @@ -1930,7 +1878,7 @@ * length of this String object. */ public String substring(int beginIndex) { - return substring(beginIndex, count); + return substring(beginIndex, length()); } /** @@ -1955,18 +1903,21 @@ * beginIndex is larger than * endIndex. */ + @JavaScriptBody(args = { "beginIndex", "endIndex" }, body = + "return this.toString().substring(beginIndex, endIndex);" + ) public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } - if (endIndex > count) { + if (endIndex > length()) { throw new StringIndexOutOfBoundsException(endIndex); } if (beginIndex > endIndex) { throw new StringIndexOutOfBoundsException(endIndex - beginIndex); } - return ((beginIndex == 0) && (endIndex == count)) ? this : - new String(offset + beginIndex, endIndex - beginIndex, value); + return ((beginIndex == 0) && (endIndex == length())) ? this : + new String(toCharArray(), offset() + beginIndex, endIndex - beginIndex); } /** @@ -2026,10 +1977,10 @@ if (otherLen == 0) { return this; } - char buf[] = new char[count + otherLen]; - getChars(0, count, buf, 0); - str.getChars(0, otherLen, buf, count); - return new String(0, count + otherLen, buf); + char buf[] = new char[length() + otherLen]; + getChars(0, length(), buf, 0); + str.getChars(0, otherLen, buf, length()); + return new String(buf, 0, length() + otherLen); } /** @@ -2061,12 +2012,24 @@ * @return a string derived from this string by replacing every * occurrence of oldChar with newChar. */ + @JavaScriptBody(args = { "arg1", "arg2" }, body = + "if (typeof arg1 === 'number') arg1 = String.fromCharCode(arg1);\n" + + "if (typeof arg2 === 'number') arg2 = String.fromCharCode(arg2);\n" + + "var s = this.toString();\n" + + "for (;;) {\n" + + " var ret = s.replace(arg1, arg2);\n" + + " if (ret === s) {\n" + + " return ret;\n" + + " }\n" + + " s = ret;\n" + + "}" + ) public String replace(char oldChar, char newChar) { if (oldChar != newChar) { - int len = count; + int len = length(); int i = -1; - char[] val = value; /* avoid getfield opcode */ - int off = offset; /* avoid getfield opcode */ + char[] val = toCharArray(); /* avoid getfield opcode */ + int off = offset(); /* avoid getfield opcode */ while (++i < len) { if (val[off + i] == oldChar) { @@ -2083,7 +2046,7 @@ buf[i] = (c == oldChar) ? newChar : c; i++; } - return new String(0, len, buf); + return new String(buf, 0, len); } } return this; @@ -2115,6 +2078,12 @@ * @since 1.4 * @spec JSR-51 */ + @JavaScriptBody(args = { "regex" }, body = + "var self = this.toString();\n" + + "var re = new RegExp(regex.toString());\n" + + "var r = re.exec(self);\n" + + "return r != null && r.length > 0 && self.length == r[0].length;" + ) public boolean matches(String regex) { throw new UnsupportedOperationException(); } @@ -2527,6 +2496,7 @@ * @return the String, converted to lowercase. * @see java.lang.String#toLowerCase(Locale) */ + @JavaScriptBody(args = {}, body = "return this.toLowerCase();") public String toLowerCase() { throw new UnsupportedOperationException("Should be supported but without connection to locale"); } @@ -2692,6 +2662,7 @@ * @return the String, converted to uppercase. * @see java.lang.String#toUpperCase(Locale) */ + @JavaScriptBody(args = {}, body = "return this.toUpperCase();") public String toUpperCase() { throw new UnsupportedOperationException(); } @@ -2728,10 +2699,10 @@ * trailing white space. */ public String trim() { - int len = count; + int len = length(); int st = 0; - int off = offset; /* avoid getfield opcode */ - char[] val = value; /* avoid getfield opcode */ + int off = offset(); /* avoid getfield opcode */ + char[] val = toCharArray(); /* avoid getfield opcode */ while ((st < len) && (val[off + st] <= ' ')) { st++; @@ -2739,7 +2710,7 @@ while ((st < len) && (val[off + len - 1] <= ' ')) { len--; } - return ((st > 0) || (len < count)) ? substring(st, len) : this; + return ((st > 0) || (len < length())) ? substring(st, len) : this; } /** @@ -2747,6 +2718,7 @@ * * @return the string itself. */ + @JavaScriptBody(args = {}, body = "return this.toString();") public String toString() { return this; } @@ -2759,8 +2731,8 @@ * the character sequence represented by this string. */ public char[] toCharArray() { - char result[] = new char[count]; - getChars(0, count, result, 0); + char result[] = new char[length()]; + getChars(0, length(), result, 0); return result; } @@ -2951,7 +2923,7 @@ */ public static String valueOf(char c) { char data[] = {c}; - return new String(0, 1, data); + return new String(data, 0, 1); } /** @@ -3034,32 +3006,4 @@ * guaranteed to be from a pool of unique strings. */ public native String intern(); - - static char[] copyOfRange(char[] original, int from, int to) { - int newLength = to - from; - if (newLength < 0) { - throw new IllegalArgumentException(from + " > " + to); - } - char[] copy = new char[newLength]; - arraycopy(original, from, copy, 0, - Math.min(original.length - from, newLength)); - return copy; - } - static char[] copyOf(char[] original, int newLength) { - char[] copy = new char[newLength]; - arraycopy(original, 0, copy, 0, - Math.min(original.length, newLength)); - return copy; - } - static void arraycopy( - char[] value, int srcBegin, char[] dst, int dstBegin, int count - ) { - while (count-- > 0) { - dst[dstBegin++] = value[srcBegin++]; - } - } - // access system property - static String getProperty(String nm) { - return null; - } } diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/StringBuffer.java --- a/emul/src/main/java/java/lang/StringBuffer.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/StringBuffer.java Wed Jan 23 20:16:48 2013 +0100 @@ -527,8 +527,7 @@ * @since 1.4 */ public synchronized int indexOf(String str, int fromIndex) { - return String.indexOf(value, 0, count, - str.toCharArray(), 0, str.length(), fromIndex); + return super.indexOf(str, fromIndex); } /** diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/StringBuilder.java --- a/emul/src/main/java/java/lang/StringBuilder.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/StringBuilder.java Wed Jan 23 20:16:48 2013 +0100 @@ -376,8 +376,7 @@ * @throws NullPointerException {@inheritDoc} */ public int indexOf(String str, int fromIndex) { - return String.indexOf(value, 0, count, - str.toCharArray(), 0, str.length(), fromIndex); + return super.indexOf(str, fromIndex); } /** diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Throwable.java --- a/emul/src/main/java/java/lang/Throwable.java Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/java/java/lang/Throwable.java Wed Jan 23 20:16:48 2013 +0100 @@ -25,6 +25,8 @@ package java.lang; import java.io.*; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.core.JavaScriptOnly; /** * The {@code Throwable} class is the superclass of all errors and @@ -233,6 +235,13 @@ private static final String SELF_SUPPRESSION_MESSAGE = "Self-suppression not permitted"; /** Caption for labeling causative exception stack traces */ + @JavaScriptOnly(name="toString", value="function() { return this.toString__Ljava_lang_String_2().toString(); }") + private static void jsToString() { + } + + @JavaScriptOnly(name="valueOf", value="function() { return this.toString().valueOf(); }") + private static void jsValudOf() { + } private static final String CAUSE_CAPTION = "Caused by: "; /** Caption for labeling suppressed exception stack traces */ @@ -782,6 +791,7 @@ return this; } + @JavaScriptBody(args = { "dummy" }, body = "") private native Throwable fillInStackTrace(int dummy); /** diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/Void.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/Void.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +/** + * The {@code Void} class is an uninstantiable placeholder class to hold a + * reference to the {@code Class} object representing the Java keyword + * void. + * + * @author unascribed + * @since JDK1.1 + */ +public final +class Void { + + /** + * The {@code Class} object representing the pseudo-type corresponding to + * the keyword {@code void}. + */ + public static final Class TYPE = Class.getPrimitiveClass("void"); + + /* + * The Void class cannot be instantiated. + */ + private Void() {} +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/AccessibleObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/AccessibleObject.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; + +/** + * The AccessibleObject class is the base class for Field, Method and + * Constructor objects. It provides the ability to flag a reflected + * object as suppressing default Java language access control checks + * when it is used. The access checks--for public, default (package) + * access, protected, and private members--are performed when Fields, + * Methods or Constructors are used to set or get fields, to invoke + * methods, or to create and initialize new instances of classes, + * respectively. + * + *

    Setting the {@code accessible} flag in a reflected object + * permits sophisticated applications with sufficient privilege, such + * as Java Object Serialization or other persistence mechanisms, to + * manipulate objects in a manner that would normally be prohibited. + * + *

    By default, a reflected object is not accessible. + * + * @see Field + * @see Method + * @see Constructor + * @see ReflectPermission + * + * @since 1.2 + */ +public class AccessibleObject implements AnnotatedElement { + + /** + * Convenience method to set the {@code accessible} flag for an + * array of objects with a single security check (for efficiency). + * + *

    First, if there is a security manager, its + * {@code checkPermission} method is called with a + * {@code ReflectPermission("suppressAccessChecks")} permission. + * + *

    A {@code SecurityException} is raised if {@code flag} is + * {@code true} but accessibility of any of the elements of the input + * {@code array} may not be changed (for example, if the element + * object is a {@link Constructor} object for the class {@link + * java.lang.Class}). In the event of such a SecurityException, the + * accessibility of objects is set to {@code flag} for array elements + * upto (and excluding) the element for which the exception occurred; the + * accessibility of elements beyond (and including) the element for which + * the exception occurred is unchanged. + * + * @param array the array of AccessibleObjects + * @param flag the new value for the {@code accessible} flag + * in each object + * @throws SecurityException if the request is denied. + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + */ + public static void setAccessible(AccessibleObject[] array, boolean flag) + throws SecurityException { + throw new SecurityException(); + } + + /** + * Set the {@code accessible} flag for this object to + * the indicated boolean value. A value of {@code true} indicates that + * the reflected object should suppress Java language access + * checking when it is used. A value of {@code false} indicates + * that the reflected object should enforce Java language access checks. + * + *

    First, if there is a security manager, its + * {@code checkPermission} method is called with a + * {@code ReflectPermission("suppressAccessChecks")} permission. + * + *

    A {@code SecurityException} is raised if {@code flag} is + * {@code true} but accessibility of this object may not be changed + * (for example, if this element object is a {@link Constructor} object for + * the class {@link java.lang.Class}). + * + *

    A {@code SecurityException} is raised if this object is a {@link + * java.lang.reflect.Constructor} object for the class + * {@code java.lang.Class}, and {@code flag} is true. + * + * @param flag the new value for the {@code accessible} flag + * @throws SecurityException if the request is denied. + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + */ + public void setAccessible(boolean flag) throws SecurityException { + throw new SecurityException(); + } + + /** + * Get the value of the {@code accessible} flag for this object. + * + * @return the value of the object's {@code accessible} flag + */ + public boolean isAccessible() { + return override; + } + + /** + * Constructor: only used by the Java Virtual Machine. + */ + protected AccessibleObject() {} + + // Indicates whether language-level access checks are overridden + // by this object. Initializes to "false". This field is used by + // Field, Method, and Constructor. + // + // NOTE: for security purposes, this field must not be visible + // outside this package. + boolean override; + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public T getAnnotation(Class annotationClass) { + throw new AssertionError("All subclasses should override this method"); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public boolean isAnnotationPresent( + Class annotationClass) { + return getAnnotation(annotationClass) != null; + } + + /** + * @since 1.5 + */ + public Annotation[] getAnnotations() { + return getDeclaredAnnotations(); + } + + /** + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + throw new AssertionError("All subclasses should override this method"); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/AnnotatedElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/AnnotatedElement.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; + +/** + * Represents an annotated element of the program currently running in this + * VM. This interface allows annotations to be read reflectively. All + * annotations returned by methods in this interface are immutable and + * serializable. It is permissible for the caller to modify the + * arrays returned by accessors for array-valued enum members; it will + * have no affect on the arrays returned to other callers. + * + *

    If an annotation returned by a method in this interface contains + * (directly or indirectly) a {@link Class}-valued member referring to + * a class that is not accessible in this VM, attempting to read the class + * by calling the relevant Class-returning method on the returned annotation + * will result in a {@link TypeNotPresentException}. + * + *

    Similarly, attempting to read an enum-valued member will result in + * a {@link EnumConstantNotPresentException} if the enum constant in the + * annotation is no longer present in the enum type. + * + *

    Finally, Attempting to read a member whose definition has evolved + * incompatibly will result in a {@link + * java.lang.annotation.AnnotationTypeMismatchException} or an + * {@link java.lang.annotation.IncompleteAnnotationException}. + * + * @see java.lang.EnumConstantNotPresentException + * @see java.lang.TypeNotPresentException + * @see java.lang.annotation.AnnotationFormatError + * @see java.lang.annotation.AnnotationTypeMismatchException + * @see java.lang.annotation.IncompleteAnnotationException + * @since 1.5 + * @author Josh Bloch + */ +public interface AnnotatedElement { + /** + * Returns true if an annotation for the specified type + * is present on this element, else false. This method + * is designed primarily for convenient access to marker annotations. + * + * @param annotationClass the Class object corresponding to the + * annotation type + * @return true if an annotation for the specified annotation + * type is present on this element, else false + * @throws NullPointerException if the given annotation class is null + * @since 1.5 + */ + boolean isAnnotationPresent(Class annotationClass); + + /** + * Returns this element's annotation for the specified type if + * such an annotation is present, else null. + * + * @param annotationClass the Class object corresponding to the + * annotation type + * @return this element's annotation for the specified annotation type if + * present on this element, else null + * @throws NullPointerException if the given annotation class is null + * @since 1.5 + */ + T getAnnotation(Class annotationClass); + + /** + * Returns all annotations present on this element. (Returns an array + * of length zero if this element has no annotations.) The caller of + * this method is free to modify the returned array; it will have no + * effect on the arrays returned to other callers. + * + * @return all annotations present on this element + * @since 1.5 + */ + Annotation[] getAnnotations(); + + /** + * Returns all annotations that are directly present on this + * element. Unlike the other methods in this interface, this method + * ignores inherited annotations. (Returns an array of length zero if + * no annotations are directly present on this element.) The caller of + * this method is free to modify the returned array; it will have no + * effect on the arrays returned to other callers. + * + * @return All annotations directly present on this element + * @since 1.5 + */ + Annotation[] getDeclaredAnnotations(); +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Array.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Array.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,659 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.core.JavaScriptPrototype; + +/** + * The {@code Array} class provides static methods to dynamically create and + * access Java arrays. + * + *

    {@code Array} permits widening conversions to occur during a get or set + * operation, but throws an {@code IllegalArgumentException} if a narrowing + * conversion would occur. + * + * @author Nakul Saraiya + */ +@JavaScriptPrototype(prototype = "new Array", container = "Array.prototype") +public final +class Array { + + /** + * Constructor. Class Array is not instantiable. + */ + private Array() {} + + /** + * Creates a new array with the specified component type and + * length. + * Invoking this method is equivalent to creating an array + * as follows: + *

    + *
    +     * int[] x = {length};
    +     * Array.newInstance(componentType, x);
    +     * 
    + *
    + * + * @param componentType the {@code Class} object representing the + * component type of the new array + * @param length the length of the new array + * @return the new array + * @exception NullPointerException if the specified + * {@code componentType} parameter is null + * @exception IllegalArgumentException if componentType is {@link Void#TYPE} + * @exception NegativeArraySizeException if the specified {@code length} + * is negative + */ + public static Object newInstance(Class componentType, int length) + throws NegativeArraySizeException { + if (length < 0) { + throw new NegativeArraySizeException(); + } + String sig = findSignature(componentType); + return newArray(componentType.isPrimitive(), sig, length); + } + + private static String findSignature(Class type) { + if (type == Integer.TYPE) { + return "[I"; + } + if (type == Long.TYPE) { + return "[J"; + } + if (type == Double.TYPE) { + return "[D"; + } + if (type == Float.TYPE) { + return "[F"; + } + if (type == Byte.TYPE) { + return "[B"; + } + if (type == Boolean.TYPE) { + return "[Z"; + } + if (type == Short.TYPE) { + return "[S"; + } + if (type == Character.TYPE) { + return "[C"; + } + if (type.getName().equals("void")) { + throw new IllegalStateException("Can't create array for " + type); + } + return "[L" + type.getName() + ";"; + } + /** + * Creates a new array + * with the specified component type and dimensions. + * If {@code componentType} + * represents a non-array class or interface, the new array + * has {@code dimensions.length} dimensions and + * {@code componentType} as its component type. If + * {@code componentType} represents an array class, the + * number of dimensions of the new array is equal to the sum + * of {@code dimensions.length} and the number of + * dimensions of {@code componentType}. In this case, the + * component type of the new array is the component type of + * {@code componentType}. + * + *

    The number of dimensions of the new array must not + * exceed the number of array dimensions supported by the + * implementation (typically 255). + * + * @param componentType the {@code Class} object representing the component + * type of the new array + * @param dimensions an array of {@code int} representing the dimensions of + * the new array + * @return the new array + * @exception NullPointerException if the specified + * {@code componentType} argument is null + * @exception IllegalArgumentException if the specified {@code dimensions} + * argument is a zero-dimensional array, or if the number of + * requested dimensions exceeds the limit on the number of array dimensions + * supported by the implementation (typically 255), or if componentType + * is {@link Void#TYPE}. + * @exception NegativeArraySizeException if any of the components in + * the specified {@code dimensions} argument is negative. + */ + public static Object newInstance(Class componentType, int... dimensions) + throws IllegalArgumentException, NegativeArraySizeException { + StringBuilder sig = new StringBuilder(); + for (int i = 1; i < dimensions.length; i++) { + sig.append('['); + } + sig.append(findSignature(componentType)); + return multiNewArray(sig.toString(), dimensions, 0); + } + + /** + * Returns the length of the specified array object, as an {@code int}. + * + * @param array the array + * @return the length of the array + * @exception IllegalArgumentException if the object argument is not + * an array + */ + public static int getLength(Object array) + throws IllegalArgumentException { + if (!array.getClass().isArray()) { + throw new IllegalArgumentException("Argument is not an array"); + } + return length(array); + } + + @JavaScriptBody(args = { "arr" }, body = "return arr.length;") + private static native int length(Object arr); + + /** + * Returns the value of the indexed component in the specified + * array object. The value is automatically wrapped in an object + * if it has a primitive type. + * + * @param array the array + * @param index the index + * @return the (possibly wrapped) value of the indexed component in + * the specified array + * @exception NullPointerException If the specified object is null + * @exception IllegalArgumentException If the specified object is not + * an array + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to the + * length of the specified array + */ + public static Object get(Object array, int index) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + final Class t = array.getClass().getComponentType(); + if (t.isPrimitive()) { + return Array.fromPrimitive(t, array, index); + } else { + return ((Object[])array)[index]; + } + } + + /** + * Returns the value of the indexed component in the specified + * array object, as a {@code boolean}. + * + * @param array the array + * @param index the index + * @return the value of the indexed component in the specified array + * @exception NullPointerException If the specified object is null + * @exception IllegalArgumentException If the specified object is not + * an array, or if the indexed element cannot be converted to the + * return type by an identity or widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to the + * length of the specified array + * @see Array#get + */ + public static native boolean getBoolean(Object array, int index) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException; + + /** + * Returns the value of the indexed component in the specified + * array object, as a {@code byte}. + * + * @param array the array + * @param index the index + * @return the value of the indexed component in the specified array + * @exception NullPointerException If the specified object is null + * @exception IllegalArgumentException If the specified object is not + * an array, or if the indexed element cannot be converted to the + * return type by an identity or widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to the + * length of the specified array + * @see Array#get + */ + public static byte getByte(Object array, int index) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + if (array.getClass().getComponentType() != Byte.TYPE) { + throw new IllegalArgumentException(); + } + byte[] arr = (byte[]) array; + return arr[index]; + } + + /** + * Returns the value of the indexed component in the specified + * array object, as a {@code char}. + * + * @param array the array + * @param index the index + * @return the value of the indexed component in the specified array + * @exception NullPointerException If the specified object is null + * @exception IllegalArgumentException If the specified object is not + * an array, or if the indexed element cannot be converted to the + * return type by an identity or widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to the + * length of the specified array + * @see Array#get + */ + public static native char getChar(Object array, int index) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException; + + /** + * Returns the value of the indexed component in the specified + * array object, as a {@code short}. + * + * @param array the array + * @param index the index + * @return the value of the indexed component in the specified array + * @exception NullPointerException If the specified object is null + * @exception IllegalArgumentException If the specified object is not + * an array, or if the indexed element cannot be converted to the + * return type by an identity or widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to the + * length of the specified array + * @see Array#get + */ + public static short getShort(Object array, int index) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + final Class t = array.getClass().getComponentType(); + if (t == Short.TYPE) { + short[] arr = (short[]) array; + return arr[index]; + } + return getByte(array, index); + } + + /** + * Returns the value of the indexed component in the specified + * array object, as an {@code int}. + * + * @param array the array + * @param index the index + * @return the value of the indexed component in the specified array + * @exception NullPointerException If the specified object is null + * @exception IllegalArgumentException If the specified object is not + * an array, or if the indexed element cannot be converted to the + * return type by an identity or widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to the + * length of the specified array + * @see Array#get + */ + public static int getInt(Object array, int index) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + final Class t = array.getClass().getComponentType(); + if (t == Integer.TYPE) { + int[] arr = (int[]) array; + return arr[index]; + } + return getShort(array, index); + } + + /** + * Returns the value of the indexed component in the specified + * array object, as a {@code long}. + * + * @param array the array + * @param index the index + * @return the value of the indexed component in the specified array + * @exception NullPointerException If the specified object is null + * @exception IllegalArgumentException If the specified object is not + * an array, or if the indexed element cannot be converted to the + * return type by an identity or widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to the + * length of the specified array + * @see Array#get + */ + public static long getLong(Object array, int index) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + final Class t = array.getClass().getComponentType(); + if (t == Long.TYPE) { + long[] arr = (long[]) array; + return arr[index]; + } + return getInt(array, index); + } + + /** + * Returns the value of the indexed component in the specified + * array object, as a {@code float}. + * + * @param array the array + * @param index the index + * @return the value of the indexed component in the specified array + * @exception NullPointerException If the specified object is null + * @exception IllegalArgumentException If the specified object is not + * an array, or if the indexed element cannot be converted to the + * return type by an identity or widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to the + * length of the specified array + * @see Array#get + */ + public static float getFloat(Object array, int index) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + final Class t = array.getClass().getComponentType(); + if (t == Float.TYPE) { + float[] arr = (float[]) array; + return arr[index]; + } + return getLong(array, index); + } + + /** + * Returns the value of the indexed component in the specified + * array object, as a {@code double}. + * + * @param array the array + * @param index the index + * @return the value of the indexed component in the specified array + * @exception NullPointerException If the specified object is null + * @exception IllegalArgumentException If the specified object is not + * an array, or if the indexed element cannot be converted to the + * return type by an identity or widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to the + * length of the specified array + * @see Array#get + */ + public static double getDouble(Object array, int index) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + final Class t = array.getClass().getComponentType(); + if (t == Double.TYPE) { + double[] arr = (double[]) array; + return arr[index]; + } + return getFloat(array, index); + } + + /** + * Sets the value of the indexed component of the specified array + * object to the specified new value. The new value is first + * automatically unwrapped if the array has a primitive component + * type. + * @param array the array + * @param index the index into the array + * @param value the new value of the indexed component + * @exception NullPointerException If the specified object argument + * is null + * @exception IllegalArgumentException If the specified object argument + * is not an array, or if the array component type is primitive and + * an unwrapping conversion fails + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to + * the length of the specified array + */ + public static void set(Object array, int index, Object value) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + if (array.getClass().getComponentType().isPrimitive()) { + throw new IllegalArgumentException(); + } else { + Object[] arr = (Object[])array; + arr[index] = value; + } + } + + /** + * Sets the value of the indexed component of the specified array + * object to the specified {@code boolean} value. + * @param array the array + * @param index the index into the array + * @param z the new value of the indexed component + * @exception NullPointerException If the specified object argument + * is null + * @exception IllegalArgumentException If the specified object argument + * is not an array, or if the specified value cannot be converted + * to the underlying array's component type by an identity or a + * primitive widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to + * the length of the specified array + * @see Array#set + */ + public static native void setBoolean(Object array, int index, boolean z) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException; + + /** + * Sets the value of the indexed component of the specified array + * object to the specified {@code byte} value. + * @param array the array + * @param index the index into the array + * @param b the new value of the indexed component + * @exception NullPointerException If the specified object argument + * is null + * @exception IllegalArgumentException If the specified object argument + * is not an array, or if the specified value cannot be converted + * to the underlying array's component type by an identity or a + * primitive widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to + * the length of the specified array + * @see Array#set + */ + public static void setByte(Object array, int index, byte b) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + Class t = array.getClass().getComponentType(); + if (t == Byte.TYPE) { + byte[] arr = (byte[]) array; + arr[index] = b; + } else { + setShort(array, index, b); + } + } + + /** + * Sets the value of the indexed component of the specified array + * object to the specified {@code char} value. + * @param array the array + * @param index the index into the array + * @param c the new value of the indexed component + * @exception NullPointerException If the specified object argument + * is null + * @exception IllegalArgumentException If the specified object argument + * is not an array, or if the specified value cannot be converted + * to the underlying array's component type by an identity or a + * primitive widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to + * the length of the specified array + * @see Array#set + */ + public static native void setChar(Object array, int index, char c) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException; + + /** + * Sets the value of the indexed component of the specified array + * object to the specified {@code short} value. + * @param array the array + * @param index the index into the array + * @param s the new value of the indexed component + * @exception NullPointerException If the specified object argument + * is null + * @exception IllegalArgumentException If the specified object argument + * is not an array, or if the specified value cannot be converted + * to the underlying array's component type by an identity or a + * primitive widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to + * the length of the specified array + * @see Array#set + */ + public static void setShort(Object array, int index, short s) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + Class t = array.getClass().getComponentType(); + if (t == Short.TYPE) { + short[] arr = (short[]) array; + arr[index] = s; + } else { + setInt(array, index, s); + } + + } + + /** + * Sets the value of the indexed component of the specified array + * object to the specified {@code int} value. + * @param array the array + * @param index the index into the array + * @param i the new value of the indexed component + * @exception NullPointerException If the specified object argument + * is null + * @exception IllegalArgumentException If the specified object argument + * is not an array, or if the specified value cannot be converted + * to the underlying array's component type by an identity or a + * primitive widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to + * the length of the specified array + * @see Array#set + */ + public static void setInt(Object array, int index, int i) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + Class t = array.getClass().getComponentType(); + if (t == Integer.TYPE) { + long[] arr = (long[]) array; + arr[index] = i; + } else { + setLong(array, index, i); + } + } + + /** + * Sets the value of the indexed component of the specified array + * object to the specified {@code long} value. + * @param array the array + * @param index the index into the array + * @param l the new value of the indexed component + * @exception NullPointerException If the specified object argument + * is null + * @exception IllegalArgumentException If the specified object argument + * is not an array, or if the specified value cannot be converted + * to the underlying array's component type by an identity or a + * primitive widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to + * the length of the specified array + * @see Array#set + */ + public static void setLong(Object array, int index, long l) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + Class t = array.getClass().getComponentType(); + if (t == Long.TYPE) { + long[] arr = (long[]) array; + arr[index] = l; + } else { + setFloat(array, index, l); + } + } + + /** + * Sets the value of the indexed component of the specified array + * object to the specified {@code float} value. + * @param array the array + * @param index the index into the array + * @param f the new value of the indexed component + * @exception NullPointerException If the specified object argument + * is null + * @exception IllegalArgumentException If the specified object argument + * is not an array, or if the specified value cannot be converted + * to the underlying array's component type by an identity or a + * primitive widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to + * the length of the specified array + * @see Array#set + */ + public static void setFloat(Object array, int index, float f) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + Class t = array.getClass().getComponentType(); + if (t == Float.TYPE) { + float[] arr = (float[])array; + arr[index] = f; + } else { + setDouble(array, index, f); + } + } + + /** + * Sets the value of the indexed component of the specified array + * object to the specified {@code double} value. + * @param array the array + * @param index the index into the array + * @param d the new value of the indexed component + * @exception NullPointerException If the specified object argument + * is null + * @exception IllegalArgumentException If the specified object argument + * is not an array, or if the specified value cannot be converted + * to the underlying array's component type by an identity or a + * primitive widening conversion + * @exception ArrayIndexOutOfBoundsException If the specified {@code index} + * argument is negative, or if it is greater than or equal to + * the length of the specified array + * @see Array#set + */ + public static void setDouble(Object array, int index, double d) + throws IllegalArgumentException, ArrayIndexOutOfBoundsException { + Class t = array.getClass().getComponentType(); + if (t == Double.TYPE) { + double[] arr = (double[])array; + arr[index] = d; + } else { + throw new IllegalArgumentException("argument type mismatch"); + } + } + + /* + * Private + */ + + @JavaScriptBody(args = { "primitive", "sig", "length" }, body = + "var arr = new Array(length);\n" + + "var value = primitive ? 0 : null;\n" + + "for(var i = 0; i < length; i++) arr[i] = value;\n" + + "arr.jvmName = sig;\n" + + "return arr;" + ) + private static native Object newArray(boolean primitive, String sig, int length); + + private static Object multiNewArray(String sig, int[] dims, int index) + throws IllegalArgumentException, NegativeArraySizeException { + if (dims.length == index + 1) { + return newArray(sig.length() == 2, sig, dims[index]); + } + Object[] arr = (Object[]) newArray(false, sig, dims[index]); + String compsig = sig.substring(1); + for (int i = 0; i < arr.length; i++) { + arr[i] = multiNewArray(compsig, dims, index + 1); + } + return arr; + } + private static Object fromPrimitive(Class t, Object array, int index) { + return Method.fromPrimitive(t, atArray(array, index)); + } + + @JavaScriptBody(args = { "array", "index" }, body = "return array[index]") + private static native Object atArray(Object array, int index); +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Field.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Field.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,953 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; + + +/** + * A {@code Field} provides information about, and dynamic access to, a + * single field of a class or an interface. The reflected field may + * be a class (static) field or an instance field. + * + *

    A {@code Field} permits widening conversions to occur during a get or + * set access operation, but throws an {@code IllegalArgumentException} if a + * narrowing conversion would occur. + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getFields() + * @see java.lang.Class#getField(String) + * @see java.lang.Class#getDeclaredFields() + * @see java.lang.Class#getDeclaredField(String) + * + * @author Kenneth Russell + * @author Nakul Saraiya + */ +public final +class Field extends AccessibleObject implements Member { + + private Class clazz; + private int slot; + // This is guaranteed to be interned by the VM in the 1.4 + // reflection implementation + private String name; + private Class type; + private int modifiers; + // Generics and annotations support + private transient String signature; + private byte[] annotations; + // For sharing of FieldAccessors. This branching structure is + // currently only two levels deep (i.e., one root Field and + // potentially many Field objects pointing to it.) + private Field root; + + // Generics infrastructure + + private String getGenericSignature() {return signature;} + + + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + Field(Class declaringClass, + String name, + Class type, + int modifiers, + int slot, + String signature, + byte[] annotations) + { + this.clazz = declaringClass; + this.name = name; + this.type = type; + this.modifiers = modifiers; + this.slot = slot; + this.signature = signature; + this.annotations = annotations; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Field. The copy's + * "root" field points to this Field. + */ + Field copy() { + // This routine enables sharing of FieldAccessor objects + // among Field objects which refer to the same underlying + // method in the VM. (All of this contortion is only necessary + // because of the "accessibility" bit in AccessibleObject, + // which implicitly requires that new java.lang.reflect + // objects be fabricated for each reflective call on Class + // objects.) + Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations); + res.root = this; + return res; + } + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the field represented by this {@code Field} object. + */ + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of the field represented by this {@code Field} object. + */ + public String getName() { + return name; + } + + /** + * Returns the Java language modifiers for the field represented + * by this {@code Field} object, as an integer. The {@code Modifier} class should + * be used to decode the modifiers. + * + * @see Modifier + */ + public int getModifiers() { + return modifiers; + } + + /** + * Returns {@code true} if this field represents an element of + * an enumerated type; returns {@code false} otherwise. + * + * @return {@code true} if and only if this field represents an element of + * an enumerated type. + * @since 1.5 + */ + public boolean isEnumConstant() { + return (getModifiers() & Modifier.ENUM) != 0; + } + + /** + * Returns {@code true} if this field is a synthetic + * field; returns {@code false} otherwise. + * + * @return true if and only if this field is a synthetic + * field as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + /** + * Returns a {@code Class} object that identifies the + * declared type for the field represented by this + * {@code Field} object. + * + * @return a {@code Class} object identifying the declared + * type of the field represented by this object + */ + public Class getType() { + return type; + } + + /** + * Returns a {@code Type} object that represents the declared type for + * the field represented by this {@code Field} object. + * + *

    If the {@code Type} is a parameterized type, the + * {@code Type} object returned must accurately reflect the + * actual type parameters used in the source code. + * + *

    If the type of the underlying field is a type variable or a + * parameterized type, it is created. Otherwise, it is resolved. + * + * @return a {@code Type} object that represents the declared type for + * the field represented by this {@code Field} object + * @throws GenericSignatureFormatError if the generic field + * signature does not conform to the format specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the generic type + * signature of the underlying field refers to a non-existent + * type declaration + * @throws MalformedParameterizedTypeException if the generic + * signature of the underlying field refers to a parameterized type + * that cannot be instantiated for any reason + * @since 1.5 + */ + public Type getGenericType() { + throw new UnsupportedOperationException(); + } + + + /** + * Compares this {@code Field} against the specified object. Returns + * true if the objects are the same. Two {@code Field} objects are the same if + * they were declared by the same class and have the same name + * and type. + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Field) { + Field other = (Field)obj; + return (getDeclaringClass() == other.getDeclaringClass()) + && (getName() == other.getName()) + && (getType() == other.getType()); + } + return false; + } + + /** + * Returns a hashcode for this {@code Field}. This is computed as the + * exclusive-or of the hashcodes for the underlying field's + * declaring class name and its name. + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Returns a string describing this {@code Field}. The format is + * the access modifiers for the field, if any, followed + * by the field type, followed by a space, followed by + * the fully-qualified name of the class declaring the field, + * followed by a period, followed by the name of the field. + * For example: + *

    +     *    public static final int java.lang.Thread.MIN_PRIORITY
    +     *    private int java.io.FileDescriptor.fd
    +     * 
    + * + *

    The modifiers are placed in canonical order as specified by + * "The Java Language Specification". This is {@code public}, + * {@code protected} or {@code private} first, and then other + * modifiers in the following order: {@code static}, {@code final}, + * {@code transient}, {@code volatile}. + */ + public String toString() { + int mod = getModifiers(); + return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) + + getTypeName(getType()) + " " + + getTypeName(getDeclaringClass()) + "." + + getName()); + } + + /** + * Returns a string describing this {@code Field}, including + * its generic type. The format is the access modifiers for the + * field, if any, followed by the generic field type, followed by + * a space, followed by the fully-qualified name of the class + * declaring the field, followed by a period, followed by the name + * of the field. + * + *

    The modifiers are placed in canonical order as specified by + * "The Java Language Specification". This is {@code public}, + * {@code protected} or {@code private} first, and then other + * modifiers in the following order: {@code static}, {@code final}, + * {@code transient}, {@code volatile}. + * + * @return a string describing this {@code Field}, including + * its generic type + * + * @since 1.5 + */ + public String toGenericString() { + int mod = getModifiers(); + Type fieldType = getGenericType(); + return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) + + ((fieldType instanceof Class) ? + getTypeName((Class)fieldType): fieldType.toString())+ " " + + getTypeName(getDeclaringClass()) + "." + + getName()); + } + + /** + * Returns the value of the field represented by this {@code Field}, on + * the specified object. The value is automatically wrapped in an + * object if it has a primitive type. + * + *

    The underlying field's value is obtained as follows: + * + *

    If the underlying field is a static field, the {@code obj} argument + * is ignored; it may be null. + * + *

    Otherwise, the underlying field is an instance field. If the + * specified {@code obj} argument is null, the method throws a + * {@code NullPointerException}. If the specified object is not an + * instance of the class or interface declaring the underlying + * field, the method throws an {@code IllegalArgumentException}. + * + *

    If this {@code Field} object is enforcing Java language access control, and + * the underlying field is inaccessible, the method throws an + * {@code IllegalAccessException}. + * If the underlying field is static, the class that declared the + * field is initialized if it has not already been initialized. + * + *

    Otherwise, the value is retrieved from the underlying instance + * or static field. If the field has a primitive type, the value + * is wrapped in an object before being returned, otherwise it is + * returned as is. + * + *

    If the field is hidden in the type of {@code obj}, + * the field's value is obtained according to the preceding rules. + * + * @param obj object from which the represented field's value is + * to be extracted + * @return the value of the represented field in object + * {@code obj}; primitive values are wrapped in an appropriate + * object before being returned + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof). + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + */ + public Object get(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).get(obj); + } + + /** + * Gets the value of a static or instance {@code boolean} field. + * + * @param obj the object to extract the {@code boolean} value + * from + * @return the value of the {@code boolean} field + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code boolean} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public boolean getBoolean(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getBoolean(obj); + } + + /** + * Gets the value of a static or instance {@code byte} field. + * + * @param obj the object to extract the {@code byte} value + * from + * @return the value of the {@code byte} field + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code byte} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public byte getByte(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getByte(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code char} or of another primitive type convertible to + * type {@code char} via a widening conversion. + * + * @param obj the object to extract the {@code char} value + * from + * @return the value of the field converted to type {@code char} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code char} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public char getChar(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getChar(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code short} or of another primitive type convertible to + * type {@code short} via a widening conversion. + * + * @param obj the object to extract the {@code short} value + * from + * @return the value of the field converted to type {@code short} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code short} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public short getShort(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getShort(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code int} or of another primitive type convertible to + * type {@code int} via a widening conversion. + * + * @param obj the object to extract the {@code int} value + * from + * @return the value of the field converted to type {@code int} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code int} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public int getInt(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getInt(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code long} or of another primitive type convertible to + * type {@code long} via a widening conversion. + * + * @param obj the object to extract the {@code long} value + * from + * @return the value of the field converted to type {@code long} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code long} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public long getLong(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getLong(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code float} or of another primitive type convertible to + * type {@code float} via a widening conversion. + * + * @param obj the object to extract the {@code float} value + * from + * @return the value of the field converted to type {@code float} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code float} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public float getFloat(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getFloat(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code double} or of another primitive type convertible to + * type {@code double} via a widening conversion. + * + * @param obj the object to extract the {@code double} value + * from + * @return the value of the field converted to type {@code double} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code double} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public double getDouble(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getDouble(obj); + } + + /** + * Sets the field represented by this {@code Field} object on the + * specified object argument to the specified new value. The new + * value is automatically unwrapped if the underlying field has a + * primitive type. + * + *

    The operation proceeds as follows: + * + *

    If the underlying field is static, the {@code obj} argument is + * ignored; it may be null. + * + *

    Otherwise the underlying field is an instance field. If the + * specified object argument is null, the method throws a + * {@code NullPointerException}. If the specified object argument is not + * an instance of the class or interface declaring the underlying + * field, the method throws an {@code IllegalArgumentException}. + * + *

    If this {@code Field} object is enforcing Java language access control, and + * the underlying field is inaccessible, the method throws an + * {@code IllegalAccessException}. + * + *

    If the underlying field is final, the method throws an + * {@code IllegalAccessException} unless {@code setAccessible(true)} + * has succeeded for this {@code Field} object + * and the field is non-static. Setting a final field in this way + * is meaningful only during deserialization or reconstruction of + * instances of classes with blank final fields, before they are + * made available for access by other parts of a program. Use in + * any other context may have unpredictable effects, including cases + * in which other parts of a program continue to use the original + * value of this field. + * + *

    If the underlying field is of a primitive type, an unwrapping + * conversion is attempted to convert the new value to a value of + * a primitive type. If this attempt fails, the method throws an + * {@code IllegalArgumentException}. + * + *

    If, after possible unwrapping, the new value cannot be + * converted to the type of the underlying field by an identity or + * widening conversion, the method throws an + * {@code IllegalArgumentException}. + * + *

    If the underlying field is static, the class that declared the + * field is initialized if it has not already been initialized. + * + *

    The field is set to the possibly unwrapped and widened new value. + * + *

    If the field is hidden in the type of {@code obj}, + * the field's value is set according to the preceding rules. + * + * @param obj the object whose field should be modified + * @param value the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + */ + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).set(obj, value); + } + + /** + * Sets the value of a field as a {@code boolean} on the specified object. + * This method is equivalent to + * {@code set(obj, zObj)}, + * where {@code zObj} is a {@code Boolean} object and + * {@code zObj.booleanValue() == z}. + * + * @param obj the object whose field should be modified + * @param z the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setBoolean(obj, z); + } + + /** + * Sets the value of a field as a {@code byte} on the specified object. + * This method is equivalent to + * {@code set(obj, bObj)}, + * where {@code bObj} is a {@code Byte} object and + * {@code bObj.byteValue() == b}. + * + * @param obj the object whose field should be modified + * @param b the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setByte(obj, b); + } + + /** + * Sets the value of a field as a {@code char} on the specified object. + * This method is equivalent to + * {@code set(obj, cObj)}, + * where {@code cObj} is a {@code Character} object and + * {@code cObj.charValue() == c}. + * + * @param obj the object whose field should be modified + * @param c the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setChar(obj, c); + } + + /** + * Sets the value of a field as a {@code short} on the specified object. + * This method is equivalent to + * {@code set(obj, sObj)}, + * where {@code sObj} is a {@code Short} object and + * {@code sObj.shortValue() == s}. + * + * @param obj the object whose field should be modified + * @param s the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setShort(obj, s); + } + + /** + * Sets the value of a field as an {@code int} on the specified object. + * This method is equivalent to + * {@code set(obj, iObj)}, + * where {@code iObj} is a {@code Integer} object and + * {@code iObj.intValue() == i}. + * + * @param obj the object whose field should be modified + * @param i the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setInt(obj, i); + } + + /** + * Sets the value of a field as a {@code long} on the specified object. + * This method is equivalent to + * {@code set(obj, lObj)}, + * where {@code lObj} is a {@code Long} object and + * {@code lObj.longValue() == l}. + * + * @param obj the object whose field should be modified + * @param l the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setLong(obj, l); + } + + /** + * Sets the value of a field as a {@code float} on the specified object. + * This method is equivalent to + * {@code set(obj, fObj)}, + * where {@code fObj} is a {@code Float} object and + * {@code fObj.floatValue() == f}. + * + * @param obj the object whose field should be modified + * @param f the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setFloat(obj, f); + } + + /** + * Sets the value of a field as a {@code double} on the specified object. + * This method is equivalent to + * {@code set(obj, dObj)}, + * where {@code dObj} is a {@code Double} object and + * {@code dObj.doubleValue() == d}. + * + * @param obj the object whose field should be modified + * @param d the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setDouble(obj, d); + } + + // Convenience routine which performs security checks + private FieldAccessor getFieldAccessor(Object obj) + throws IllegalAccessException + { + throw new SecurityException(); + } + + private static abstract class FieldAccessor { + abstract void setShort(Object obj, short s); + abstract void setInt(Object obj, int i); + abstract void setChar(Object obj, char c); + abstract void setByte(Object obj, byte b); + abstract void setBoolean(Object obj, boolean z); + abstract void set(Object obj, Object value); + abstract double getDouble(Object obj); + abstract void setLong(Object obj, long l); + abstract void setFloat(Object obj, float f); + abstract void setDouble(Object obj, double d); + abstract long getLong(Object obj); + abstract int getInt(Object obj); + abstract short getShort(Object obj); + abstract char getChar(Object obj); + abstract byte getByte(Object obj); + abstract boolean getBoolean(Object obj); + abstract Object get(Object obj); + abstract float getFloat(Object obj); + } + + /* + * Utility routine to paper over array type names + */ + static String getTypeName(Class type) { + if (type.isArray()) { + try { + Class cl = type; + int dimensions = 0; + while (cl.isArray()) { + dimensions++; + cl = cl.getComponentType(); + } + StringBuffer sb = new StringBuffer(); + sb.append(cl.getName()); + for (int i = 0; i < dimensions; i++) { + sb.append("[]"); + } + return sb.toString(); + } catch (Throwable e) { /*FALLTHRU*/ } + } + return type.getName(); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public T getAnnotation(Class annotationClass) { + if (annotationClass == null) + throw new NullPointerException(); + + throw new UnsupportedOperationException(); + } + + /** + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + throw new UnsupportedOperationException(); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/GenericDeclaration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/GenericDeclaration.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * A common interface for all entities that declare type variables. + * + * @since 1.5 + */ +public interface GenericDeclaration { + /** + * Returns an array of {@code TypeVariable} objects that + * represent the type variables declared by the generic + * declaration represented by this {@code GenericDeclaration} + * object, in declaration order. Returns an array of length 0 if + * the underlying generic declaration declares no type variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * The Java™ Virtual Machine Specification + */ + public TypeVariable[] getTypeParameters(); +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/InvocationTargetException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/InvocationTargetException.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * InvocationTargetException is a checked exception that wraps + * an exception thrown by an invoked method or constructor. + * + *

    As of release 1.4, this exception has been retrofitted to conform to + * the general purpose exception-chaining mechanism. The "target exception" + * that is provided at construction time and accessed via the + * {@link #getTargetException()} method is now known as the cause, + * and may be accessed via the {@link Throwable#getCause()} method, + * as well as the aforementioned "legacy method." + * + * @see Method + * @see Constructor + */ +public class InvocationTargetException extends ReflectiveOperationException { + /** + * Use serialVersionUID from JDK 1.1.X for interoperability + */ + private static final long serialVersionUID = 4085088731926701167L; + + /** + * This field holds the target if the + * InvocationTargetException(Throwable target) constructor was + * used to instantiate the object + * + * @serial + * + */ + private Throwable target; + + /** + * Constructs an {@code InvocationTargetException} with + * {@code null} as the target exception. + */ + protected InvocationTargetException() { + super((Throwable)null); // Disallow initCause + } + + /** + * Constructs a InvocationTargetException with a target exception. + * + * @param target the target exception + */ + public InvocationTargetException(Throwable target) { + super((Throwable)null); // Disallow initCause + this.target = target; + } + + /** + * Constructs a InvocationTargetException with a target exception + * and a detail message. + * + * @param target the target exception + * @param s the detail message + */ + public InvocationTargetException(Throwable target, String s) { + super(s, null); // Disallow initCause + this.target = target; + } + + /** + * Get the thrown target exception. + * + *

    This method predates the general-purpose exception chaining facility. + * The {@link Throwable#getCause()} method is now the preferred means of + * obtaining this information. + * + * @return the thrown target exception (cause of this exception). + */ + public Throwable getTargetException() { + return target; + } + + /** + * Returns the cause of this exception (the thrown target exception, + * which may be {@code null}). + * + * @return the cause of this exception. + * @since 1.4 + */ + public Throwable getCause() { + return target; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Member.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Member.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * Member is an interface that reflects identifying information about + * a single member (a field or a method) or a constructor. + * + * @see java.lang.Class + * @see Field + * @see Method + * @see Constructor + * + * @author Nakul Saraiya + */ +public +interface Member { + + /** + * Identifies the set of all public members of a class or interface, + * including inherited members. + * @see java.lang.SecurityManager#checkMemberAccess + */ + public static final int PUBLIC = 0; + + /** + * Identifies the set of declared members of a class or interface. + * Inherited members are not included. + * @see java.lang.SecurityManager#checkMemberAccess + */ + public static final int DECLARED = 1; + + /** + * Returns the Class object representing the class or interface + * that declares the member or constructor represented by this Member. + * + * @return an object representing the declaring class of the + * underlying member + */ + public Class getDeclaringClass(); + + /** + * Returns the simple name of the underlying member or constructor + * represented by this Member. + * + * @return the simple name of the underlying member + */ + public String getName(); + + /** + * Returns the Java language modifiers for the member or + * constructor represented by this Member, as an integer. The + * Modifier class should be used to decode the modifiers in + * the integer. + * + * @return the Java language modifiers for the underlying member + * @see Modifier + */ + public int getModifiers(); + + /** + * Returns {@code true} if this member was introduced by + * the compiler; returns {@code false} otherwise. + * + * @return true if and only if this member was introduced by + * the compiler. + * @since 1.5 + */ + public boolean isSynthetic(); +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Method.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Method.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,720 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; +import java.util.Enumeration; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.emul.AnnotationImpl; +import org.apidesign.bck2brwsr.emul.MethodImpl; + +/** + * A {@code Method} provides information about, and access to, a single method + * on a class or interface. The reflected method may be a class method + * or an instance method (including an abstract method). + * + *

    A {@code Method} permits widening conversions to occur when matching the + * actual parameters to invoke with the underlying method's formal + * parameters, but it throws an {@code IllegalArgumentException} if a + * narrowing conversion would occur. + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getMethods() + * @see java.lang.Class#getMethod(String, Class[]) + * @see java.lang.Class#getDeclaredMethods() + * @see java.lang.Class#getDeclaredMethod(String, Class[]) + * + * @author Kenneth Russell + * @author Nakul Saraiya + */ +public final + class Method extends AccessibleObject implements GenericDeclaration, + Member { + private final Class clazz; + private final String name; + private final Object data; + private final String sig; + + // Generics infrastructure + + private String getGenericSignature() {return null;} + + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + Method(Class declaringClass, String name, Object data, String sig) + { + this.clazz = declaringClass; + this.name = name; + this.data = data; + this.sig = sig; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Method. The copy's + * "root" field points to this Method. + */ + Method copy() { + return this; + } + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the method represented by this {@code Method} object. + */ + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of the method represented by this {@code Method} + * object, as a {@code String}. + */ + public String getName() { + return name; + } + + /** + * Returns the Java language modifiers for the method represented + * by this {@code Method} object, as an integer. The {@code Modifier} class should + * be used to decode the modifiers. + * + * @see Modifier + */ + public int getModifiers() { + return getAccess(data); + } + + @JavaScriptBody(args = "self", body = "return self.access;") + private static native int getAccess(Object self); + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * The Java™ Virtual Machine Specification + * @since 1.5 + */ + public TypeVariable[] getTypeParameters() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a {@code Class} object that represents the formal return type + * of the method represented by this {@code Method} object. + * + * @return the return type for the method this object represents + */ + public Class getReturnType() { + return MethodImpl.signatureParser(sig).nextElement(); + } + + /** + * Returns a {@code Type} object that represents the formal return + * type of the method represented by this {@code Method} object. + * + *

    If the return type is a parameterized type, + * the {@code Type} object returned must accurately reflect + * the actual type parameters used in the source code. + * + *

    If the return type is a type variable or a parameterized type, it + * is created. Otherwise, it is resolved. + * + * @return a {@code Type} object that represents the formal return + * type of the underlying method + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the underlying method's + * return type refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if the + * underlying method's return typed refers to a parameterized + * type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type getGenericReturnType() { + throw new UnsupportedOperationException(); + } + + + /** + * Returns an array of {@code Class} objects that represent the formal + * parameter types, in declaration order, of the method + * represented by this {@code Method} object. Returns an array of length + * 0 if the underlying method takes no parameters. + * + * @return the parameter types for the method this object + * represents + */ + public Class[] getParameterTypes() { + Class[] arr = new Class[MethodImpl.signatureElements(sig) - 1]; + Enumeration en = MethodImpl.signatureParser(sig); + en.nextElement(); // return type + for (int i = 0; i < arr.length; i++) { + arr[i] = en.nextElement(); + } + return arr; + } + + /** + * Returns an array of {@code Type} objects that represent the formal + * parameter types, in declaration order, of the method represented by + * this {@code Method} object. Returns an array of length 0 if the + * underlying method takes no parameters. + * + *

    If a formal parameter type is a parameterized type, + * the {@code Type} object returned for it must accurately reflect + * the actual type parameters used in the source code. + * + *

    If a formal parameter type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the formal + * parameter types of the underlying method, in declaration order + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if any of the parameter + * types of the underlying method refers to a non-existent type + * declaration + * @throws MalformedParameterizedTypeException if any of + * the underlying method's parameter types refer to a parameterized + * type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type[] getGenericParameterTypes() { + throw new UnsupportedOperationException(); + } + + + /** + * Returns an array of {@code Class} objects that represent + * the types of the exceptions declared to be thrown + * by the underlying method + * represented by this {@code Method} object. Returns an array of length + * 0 if the method declares no exceptions in its {@code throws} clause. + * + * @return the exception types declared as being thrown by the + * method this object represents + */ + public Class[] getExceptionTypes() { + throw new UnsupportedOperationException(); + //return (Class[]) exceptionTypes.clone(); + } + + /** + * Returns an array of {@code Type} objects that represent the + * exceptions declared to be thrown by this {@code Method} object. + * Returns an array of length 0 if the underlying method declares + * no exceptions in its {@code throws} clause. + * + *

    If an exception type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the exception types + * thrown by the underlying method + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the underlying method's + * {@code throws} clause refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if + * the underlying method's {@code throws} clause refers to a + * parameterized type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type[] getGenericExceptionTypes() { + throw new UnsupportedOperationException(); + } + + /** + * Compares this {@code Method} against the specified object. Returns + * true if the objects are the same. Two {@code Methods} are the same if + * they were declared by the same class and have the same name + * and formal parameter types and return type. + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Method) { + Method other = (Method)obj; + return data == other.data; + } + return false; + } + + /** + * Returns a hashcode for this {@code Method}. The hashcode is computed + * as the exclusive-or of the hashcodes for the underlying + * method's declaring class name and the method's name. + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Returns a string describing this {@code Method}. The string is + * formatted as the method access modifiers, if any, followed by + * the method return type, followed by a space, followed by the + * class declaring the method, followed by a period, followed by + * the method name, followed by a parenthesized, comma-separated + * list of the method's formal parameter types. If the method + * throws checked exceptions, the parameter list is followed by a + * space, followed by the word throws followed by a + * comma-separated list of the thrown exception types. + * For example: + *

    +     *    public boolean java.lang.Object.equals(java.lang.Object)
    +     * 
    + * + *

    The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code static}, {@code final}, + * {@code synchronized}, {@code native}, {@code strictfp}. + */ + public String toString() { + try { + StringBuilder sb = new StringBuilder(); + int mod = getModifiers() & Modifier.methodModifiers(); + if (mod != 0) { + sb.append(Modifier.toString(mod)).append(' '); + } + sb.append(Field.getTypeName(getReturnType())).append(' '); + sb.append(Field.getTypeName(getDeclaringClass())).append('.'); + sb.append(getName()).append('('); + Class[] params = getParameterTypes(); // avoid clone + for (int j = 0; j < params.length; j++) { + sb.append(Field.getTypeName(params[j])); + if (j < (params.length - 1)) + sb.append(','); + } + sb.append(')'); + /* + Class[] exceptions = exceptionTypes; // avoid clone + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append(exceptions[k].getName()); + if (k < (exceptions.length - 1)) + sb.append(','); + } + } + */ + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Returns a string describing this {@code Method}, including + * type parameters. The string is formatted as the method access + * modifiers, if any, followed by an angle-bracketed + * comma-separated list of the method's type parameters, if any, + * followed by the method's generic return type, followed by a + * space, followed by the class declaring the method, followed by + * a period, followed by the method name, followed by a + * parenthesized, comma-separated list of the method's generic + * formal parameter types. + * + * If this method was declared to take a variable number of + * arguments, instead of denoting the last parameter as + * "Type[]", it is denoted as + * "Type...". + * + * A space is used to separate access modifiers from one another + * and from the type parameters or return type. If there are no + * type parameters, the type parameter list is elided; if the type + * parameter list is present, a space separates the list from the + * class name. If the method is declared to throw exceptions, the + * parameter list is followed by a space, followed by the word + * throws followed by a comma-separated list of the generic thrown + * exception types. If there are no type parameters, the type + * parameter list is elided. + * + *

    The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code static}, {@code final}, + * {@code synchronized}, {@code native}, {@code strictfp}. + * + * @return a string describing this {@code Method}, + * include type parameters + * + * @since 1.5 + */ + public String toGenericString() { + try { + StringBuilder sb = new StringBuilder(); + int mod = getModifiers() & Modifier.methodModifiers(); + if (mod != 0) { + sb.append(Modifier.toString(mod)).append(' '); + } + TypeVariable[] typeparms = getTypeParameters(); + if (typeparms.length > 0) { + boolean first = true; + sb.append('<'); + for(TypeVariable typeparm: typeparms) { + if (!first) + sb.append(','); + // Class objects can't occur here; no need to test + // and call Class.getName(). + sb.append(typeparm.toString()); + first = false; + } + sb.append("> "); + } + + Type genRetType = getGenericReturnType(); + sb.append( ((genRetType instanceof Class)? + Field.getTypeName((Class)genRetType):genRetType.toString())) + .append(' '); + + sb.append(Field.getTypeName(getDeclaringClass())).append('.'); + sb.append(getName()).append('('); + Type[] params = getGenericParameterTypes(); + for (int j = 0; j < params.length; j++) { + String param = (params[j] instanceof Class)? + Field.getTypeName((Class)params[j]): + (params[j].toString()); + if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... + param = param.replaceFirst("\\[\\]$", "..."); + sb.append(param); + if (j < (params.length - 1)) + sb.append(','); + } + sb.append(')'); + Type[] exceptions = getGenericExceptionTypes(); + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append((exceptions[k] instanceof Class)? + ((Class)exceptions[k]).getName(): + exceptions[k].toString()); + if (k < (exceptions.length - 1)) + sb.append(','); + } + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Invokes the underlying method represented by this {@code Method} + * object, on the specified object with the specified parameters. + * Individual parameters are automatically unwrapped to match + * primitive formal parameters, and both primitive and reference + * parameters are subject to method invocation conversions as + * necessary. + * + *

    If the underlying method is static, then the specified {@code obj} + * argument is ignored. It may be null. + * + *

    If the number of formal parameters required by the underlying method is + * 0, the supplied {@code args} array may be of length 0 or null. + * + *

    If the underlying method is an instance method, it is invoked + * using dynamic method lookup as documented in The Java Language + * Specification, Second Edition, section 15.12.4.4; in particular, + * overriding based on the runtime type of the target object will occur. + * + *

    If the underlying method is static, the class that declared + * the method is initialized if it has not already been initialized. + * + *

    If the method completes normally, the value it returns is + * returned to the caller of invoke; if the value has a primitive + * type, it is first appropriately wrapped in an object. However, + * if the value has the type of an array of a primitive type, the + * elements of the array are not wrapped in objects; in + * other words, an array of primitive type is returned. If the + * underlying method return type is void, the invocation returns + * null. + * + * @param obj the object the underlying method is invoked from + * @param args the arguments used for the method call + * @return the result of dispatching the method represented by + * this object on {@code obj} with parameters + * {@code args} + * + * @exception IllegalAccessException if this {@code Method} object + * is enforcing Java language access control and the underlying + * method is inaccessible. + * @exception IllegalArgumentException if the method is an + * instance method and the specified object argument + * is not an instance of the class or interface + * declaring the underlying method (or of a subclass + * or implementor thereof); if the number of actual + * and formal parameters differ; if an unwrapping + * conversion for primitive arguments fails; or if, + * after possible unwrapping, a parameter value + * cannot be converted to the corresponding formal + * parameter type by a method invocation conversion. + * @exception InvocationTargetException if the underlying method + * throws an exception. + * @exception NullPointerException if the specified object is null + * and the method is an instance method. + * @exception ExceptionInInitializerError if the initialization + * provoked by this method fails. + */ + public Object invoke(Object obj, Object... args) + throws IllegalAccessException, IllegalArgumentException, + InvocationTargetException + { + final boolean isStatic = (getModifiers() & Modifier.STATIC) == 0; + if (isStatic && obj == null) { + throw new NullPointerException(); + } + Class[] types = getParameterTypes(); + if (types.length != args.length) { + throw new IllegalArgumentException("Types len " + types.length + " args: " + args.length); + } else { + args = args.clone(); + for (int i = 0; i < types.length; i++) { + Class c = types[i]; + if (c.isPrimitive()) { + args[i] = toPrimitive(c, args[i]); + } + } + } + Object res = invoke0(isStatic, this, obj, args); + if (getReturnType().isPrimitive()) { + res = fromPrimitive(getReturnType(), res); + } + return res; + } + + @JavaScriptBody(args = { "st", "method", "self", "args" }, body = + "var p;\n" + + "if (st) {\n" + + " p = new Array(1);\n" + + " p[0] = self;\n" + + " p = p.concat(args);\n" + + "} else {\n" + + " p = args;\n" + + "}\n" + + "return method.fld_data.apply(self, p);\n" + ) + private static native Object invoke0(boolean isStatic, Method m, Object self, Object[] args); + + static Object fromPrimitive(Class type, Object o) { + if (type == Integer.TYPE) { + return fromRaw(Integer.class, "valueOf__Ljava_lang_Integer_2I", o); + } + if (type == Long.TYPE) { + return fromRaw(Long.class, "valueOf__Ljava_lang_Long_2J", o); + } + if (type == Double.TYPE) { + return fromRaw(Double.class, "valueOf__Ljava_lang_Double_2D", o); + } + if (type == Float.TYPE) { + return fromRaw(Float.class, "valueOf__Ljava_lang_Float_2F", o); + } + if (type == Byte.TYPE) { + return fromRaw(Byte.class, "valueOf__Ljava_lang_Byte_2B", o); + } + if (type == Boolean.TYPE) { + return fromRaw(Boolean.class, "valueOf__Ljava_lang_Boolean_2Z", o); + } + if (type == Short.TYPE) { + return fromRaw(Short.class, "valueOf__Ljava_lang_Short_2S", o); + } + if (type == Character.TYPE) { + return fromRaw(Character.class, "valueOf__Ljava_lang_Character_2C", o); + } + if (type.getName().equals("void")) { + return null; + } + throw new IllegalStateException("Can't convert " + o); + } + + @JavaScriptBody(args = { "cls", "m", "o" }, + body = "return cls.cnstr(false)[m](o);" + ) + private static native Integer fromRaw(Class cls, String m, Object o); + + private static Object toPrimitive(Class type, Object o) { + if (type == Integer.TYPE) { + return toRaw("intValue__I", o); + } + if (type == Long.TYPE) { + return toRaw("longValue__J", o); + } + if (type == Double.TYPE) { + return toRaw("doubleValue__D", o); + } + if (type == Float.TYPE) { + return toRaw("floatValue__F", o); + } + if (type == Byte.TYPE) { + return toRaw("byteValue__B", o); + } + if (type == Boolean.TYPE) { + return toRaw("booleanValue__Z", o); + } + if (type == Short.TYPE) { + return toRaw("shortValue__S", o); + } + if (type == Character.TYPE) { + return toRaw("charValue__C", o); + } + if (type.getName().equals("void")) { + return o; + } + throw new IllegalStateException("Can't convert " + o); + } + + @JavaScriptBody(args = { "m", "o" }, + body = "return o[m](o);" + ) + private static native Object toRaw(String m, Object o); + + /** + * Returns {@code true} if this method is a bridge + * method; returns {@code false} otherwise. + * + * @return true if and only if this method is a bridge + * method as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isBridge() { + return (getModifiers() & Modifier.BRIDGE) != 0; + } + + /** + * Returns {@code true} if this method was declared to take + * a variable number of arguments; returns {@code false} + * otherwise. + * + * @return {@code true} if an only if this method was declared to + * take a variable number of arguments. + * @since 1.5 + */ + public boolean isVarArgs() { + return (getModifiers() & Modifier.VARARGS) != 0; + } + + /** + * Returns {@code true} if this method is a synthetic + * method; returns {@code false} otherwise. + * + * @return true if and only if this method is a synthetic + * method as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + @JavaScriptBody(args = { "ac" }, + body = + "if (this.fld_data.anno) {" + + " return this.fld_data.anno['L' + ac.jvmName + ';'];" + + "} else return null;" + ) + private Object getAnnotationData(Class annotationClass) { + throw new UnsupportedOperationException(); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public T getAnnotation(Class annotationClass) { + Object data = getAnnotationData(annotationClass); + return data == null ? null : AnnotationImpl.create(annotationClass, data); + } + + /** + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + throw new UnsupportedOperationException(); + } + + /** + * Returns the default value for the annotation member represented by + * this {@code Method} instance. If the member is of a primitive type, + * an instance of the corresponding wrapper type is returned. Returns + * null if no default is associated with the member, or if the method + * instance does not represent a declared member of an annotation type. + * + * @return the default value for the annotation member represented + * by this {@code Method} instance. + * @throws TypeNotPresentException if the annotation is of type + * {@link Class} and no definition can be found for the + * default class value. + * @since 1.5 + */ + public Object getDefaultValue() { + throw new UnsupportedOperationException(); + } + + /** + * Returns an array of arrays that represent the annotations on the formal + * parameters, in declaration order, of the method represented by + * this {@code Method} object. (Returns an array of length zero if the + * underlying method is parameterless. If the method has one or more + * parameters, a nested array of length zero is returned for each parameter + * with no annotations.) The annotation objects contained in the returned + * arrays are serializable. The caller of this method is free to modify + * the returned arrays; it will have no effect on the arrays returned to + * other callers. + * + * @return an array of arrays that represent the annotations on the formal + * parameters, in declaration order, of the method represented by this + * Method object + * @since 1.5 + */ + public Annotation[][] getParameterAnnotations() { + throw new UnsupportedOperationException(); + } + + static { + MethodImpl.INSTANCE = new MethodImpl() { + protected Method create(Class declaringClass, String name, Object data, String sig) { + return new Method(declaringClass, name, data, sig); + } + }; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Modifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Modifier.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,437 @@ +/* + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * The Modifier class provides {@code static} methods and + * constants to decode class and member access modifiers. The sets of + * modifiers are represented as integers with distinct bit positions + * representing different modifiers. The values for the constants + * representing the modifiers are taken from the tables in sections 4.1, 4.4, 4.5, and 4.7 of + * The Java™ Virtual Machine Specification. + * + * @see Class#getModifiers() + * @see Member#getModifiers() + * + * @author Nakul Saraiya + * @author Kenneth Russell + */ +public +class Modifier { + + /** + * Return {@code true} if the integer argument includes the + * {@code public} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code public} modifier; {@code false} otherwise. + */ + public static boolean isPublic(int mod) { + return (mod & PUBLIC) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code private} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code private} modifier; {@code false} otherwise. + */ + public static boolean isPrivate(int mod) { + return (mod & PRIVATE) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code protected} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code protected} modifier; {@code false} otherwise. + */ + public static boolean isProtected(int mod) { + return (mod & PROTECTED) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code static} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code static} modifier; {@code false} otherwise. + */ + public static boolean isStatic(int mod) { + return (mod & STATIC) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code final} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code final} modifier; {@code false} otherwise. + */ + public static boolean isFinal(int mod) { + return (mod & FINAL) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code synchronized} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code synchronized} modifier; {@code false} otherwise. + */ + public static boolean isSynchronized(int mod) { + return (mod & SYNCHRONIZED) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code volatile} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code volatile} modifier; {@code false} otherwise. + */ + public static boolean isVolatile(int mod) { + return (mod & VOLATILE) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code transient} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code transient} modifier; {@code false} otherwise. + */ + public static boolean isTransient(int mod) { + return (mod & TRANSIENT) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code native} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code native} modifier; {@code false} otherwise. + */ + public static boolean isNative(int mod) { + return (mod & NATIVE) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code interface} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code interface} modifier; {@code false} otherwise. + */ + public static boolean isInterface(int mod) { + return (mod & INTERFACE) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code abstract} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code abstract} modifier; {@code false} otherwise. + */ + public static boolean isAbstract(int mod) { + return (mod & ABSTRACT) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code strictfp} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code strictfp} modifier; {@code false} otherwise. + */ + public static boolean isStrict(int mod) { + return (mod & STRICT) != 0; + } + + /** + * Return a string describing the access modifier flags in + * the specified modifier. For example: + *

    +     *    public final synchronized strictfp
    +     * 
    + * The modifier names are returned in an order consistent with the + * suggested modifier orderings given in sections 8.1.1, 8.3.1, 8.4.3, 8.8.3, and 9.1.1 of + * The Java™ Language Specification. + * The full modifier ordering used by this method is: + *
    {@code + * public protected private abstract static final transient + * volatile synchronized native strictfp + * interface }
    + * The {@code interface} modifier discussed in this class is + * not a true modifier in the Java language and it appears after + * all other modifiers listed by this method. This method may + * return a string of modifiers that are not valid modifiers of a + * Java entity; in other words, no checking is done on the + * possible validity of the combination of modifiers represented + * by the input. + * + * Note that to perform such checking for a known kind of entity, + * such as a constructor or method, first AND the argument of + * {@code toString} with the appropriate mask from a method like + * {@link #constructorModifiers} or {@link #methodModifiers}. + * + * @param mod a set of modifiers + * @return a string representation of the set of modifiers + * represented by {@code mod} + */ + public static String toString(int mod) { + StringBuffer sb = new StringBuffer(); + int len; + + if ((mod & PUBLIC) != 0) sb.append("public "); + if ((mod & PROTECTED) != 0) sb.append("protected "); + if ((mod & PRIVATE) != 0) sb.append("private "); + + /* Canonical order */ + if ((mod & ABSTRACT) != 0) sb.append("abstract "); + if ((mod & STATIC) != 0) sb.append("static "); + if ((mod & FINAL) != 0) sb.append("final "); + if ((mod & TRANSIENT) != 0) sb.append("transient "); + if ((mod & VOLATILE) != 0) sb.append("volatile "); + if ((mod & SYNCHRONIZED) != 0) sb.append("synchronized "); + if ((mod & NATIVE) != 0) sb.append("native "); + if ((mod & STRICT) != 0) sb.append("strictfp "); + if ((mod & INTERFACE) != 0) sb.append("interface "); + + if ((len = sb.length()) > 0) /* trim trailing space */ + return sb.toString().substring(0, len-1); + return ""; + } + + /* + * Access modifier flag constants from tables 4.1, 4.4, 4.5, and 4.7 of + * The Java™ Virtual Machine Specification + */ + + /** + * The {@code int} value representing the {@code public} + * modifier. + */ + public static final int PUBLIC = 0x00000001; + + /** + * The {@code int} value representing the {@code private} + * modifier. + */ + public static final int PRIVATE = 0x00000002; + + /** + * The {@code int} value representing the {@code protected} + * modifier. + */ + public static final int PROTECTED = 0x00000004; + + /** + * The {@code int} value representing the {@code static} + * modifier. + */ + public static final int STATIC = 0x00000008; + + /** + * The {@code int} value representing the {@code final} + * modifier. + */ + public static final int FINAL = 0x00000010; + + /** + * The {@code int} value representing the {@code synchronized} + * modifier. + */ + public static final int SYNCHRONIZED = 0x00000020; + + /** + * The {@code int} value representing the {@code volatile} + * modifier. + */ + public static final int VOLATILE = 0x00000040; + + /** + * The {@code int} value representing the {@code transient} + * modifier. + */ + public static final int TRANSIENT = 0x00000080; + + /** + * The {@code int} value representing the {@code native} + * modifier. + */ + public static final int NATIVE = 0x00000100; + + /** + * The {@code int} value representing the {@code interface} + * modifier. + */ + public static final int INTERFACE = 0x00000200; + + /** + * The {@code int} value representing the {@code abstract} + * modifier. + */ + public static final int ABSTRACT = 0x00000400; + + /** + * The {@code int} value representing the {@code strictfp} + * modifier. + */ + public static final int STRICT = 0x00000800; + + // Bits not (yet) exposed in the public API either because they + // have different meanings for fields and methods and there is no + // way to distinguish between the two in this class, or because + // they are not Java programming language keywords + static final int BRIDGE = 0x00000040; + static final int VARARGS = 0x00000080; + static final int SYNTHETIC = 0x00001000; + static final int ANNOTATION= 0x00002000; + static final int ENUM = 0x00004000; + static boolean isSynthetic(int mod) { + return (mod & SYNTHETIC) != 0; + } + + /** + * See JLSv3 section 8.1.1. + */ + private static final int CLASS_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | + Modifier.STRICT; + + /** + * See JLSv3 section 9.1.1. + */ + private static final int INTERFACE_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.ABSTRACT | Modifier.STATIC | Modifier.STRICT; + + + /** + * See JLSv3 section 8.8.3. + */ + private static final int CONSTRUCTOR_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE; + + /** + * See JLSv3 section 8.4.3. + */ + private static final int METHOD_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | + Modifier.SYNCHRONIZED | Modifier.NATIVE | Modifier.STRICT; + + /** + * See JLSv3 section 8.3.1. + */ + private static final int FIELD_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | + Modifier.VOLATILE; + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a class. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a class. + * + * @jls 8.1.1 Class Modifiers + * @since 1.7 + */ + public static int classModifiers() { + return CLASS_MODIFIERS; + } + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to an interface. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to an inteface. + * + * @jls 9.1.1 Interface Modifiers + * @since 1.7 + */ + public static int interfaceModifiers() { + return INTERFACE_MODIFIERS; + } + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a constructor. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a constructor. + * + * @jls 8.8.3 Constructor Modifiers + * @since 1.7 + */ + public static int constructorModifiers() { + return CONSTRUCTOR_MODIFIERS; + } + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a method. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a method. + * + * @jls 8.4.3 Method Modifiers + * @since 1.7 + */ + public static int methodModifiers() { + return METHOD_MODIFIERS; + } + + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a field. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a field. + * + * @jls 8.3.1 Field Modifiers + * @since 1.7 + */ + public static int fieldModifiers() { + return FIELD_MODIFIERS; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/Type.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Type.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * Type is the common superinterface for all types in the Java + * programming language. These include raw types, parameterized types, + * array types, type variables and primitive types. + * + * @since 1.5 + */ + +public interface Type { +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/TypeVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/TypeVariable.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * TypeVariable is the common superinterface for type variables of kinds. + * A type variable is created the first time it is needed by a reflective + * method, as specified in this package. If a type variable t is referenced + * by a type (i.e, class, interface or annotation type) T, and T is declared + * by the nth enclosing class of T (see JLS 8.1.2), then the creation of t + * requires the resolution (see JVMS 5) of the ith enclosing class of T, + * for i = 0 to n, inclusive. Creating a type variable must not cause the + * creation of its bounds. Repeated creation of a type variable has no effect. + * + *

    Multiple objects may be instantiated at run-time to + * represent a given type variable. Even though a type variable is + * created only once, this does not imply any requirement to cache + * instances representing the type variable. However, all instances + * representing a type variable must be equal() to each other. + * As a consequence, users of type variables must not rely on the identity + * of instances of classes implementing this interface. + * + * @param the type of generic declaration that declared the + * underlying type variable. + * + * @since 1.5 + */ +public interface TypeVariable extends Type { + /** + * Returns an array of {@code Type} objects representing the + * upper bound(s) of this type variable. Note that if no upper bound is + * explicitly declared, the upper bound is {@code Object}. + * + *

    For each upper bound B:

    • if B is a parameterized + * type or a type variable, it is created, (see {@link + * java.lang.reflect.ParameterizedType ParameterizedType} for the + * details of the creation process for parameterized types). + *
    • Otherwise, B is resolved.
    + * + * @throws TypeNotPresentException if any of the + * bounds refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if any of the + * bounds refer to a parameterized type that cannot be instantiated + * for any reason + * @return an array of {@code Type}s representing the upper + * bound(s) of this type variable + */ + Type[] getBounds(); + + /** + * Returns the {@code GenericDeclaration} object representing the + * generic declaration declared this type variable. + * + * @return the generic declaration declared for this type variable. + * + * @since 1.5 + */ + D getGenericDeclaration(); + + /** + * Returns the name of this type variable, as it occurs in the source code. + * + * @return the name of this type variable, as it appears in the source code + */ + String getName(); +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/lang/reflect/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/package-info.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Provides classes and interfaces for obtaining reflective + * information about classes and objects. Reflection allows + * programmatic access to information about the fields, methods and + * constructors of loaded classes, and the use of reflected fields, + * methods, and constructors to operate on their underlying + * counterparts, within security restrictions. + * + *

    {@code AccessibleObject} allows suppression of access checks if + * the necessary {@code ReflectPermission} is available. + * + *

    {@code Array} provides static methods to dynamically create and + * access arrays. + * + *

    Classes in this package, along with {@code java.lang.Class} + * accommodate applications such as debuggers, interpreters, object + * inspectors, class browsers, and services such as Object + * Serialization and JavaBeans that need access to either the public + * members of a target object (based on its runtime class) or the + * members declared by a given class. + * + * @since JDK1.1 + */ +package java.lang.reflect; diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/net/MalformedURLException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/net/MalformedURLException.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net; + +import java.io.IOException; + +/** + * Thrown to indicate that a malformed URL has occurred. Either no + * legal protocol could be found in a specification string or the + * string could not be parsed. + * + * @author Arthur van Hoff + * @since JDK1.0 + */ +public class MalformedURLException extends IOException { + private static final long serialVersionUID = -182787522200415866L; + + /** + * Constructs a MalformedURLException with no detail message. + */ + public MalformedURLException() { + } + + /** + * Constructs a MalformedURLException with the + * specified detail message. + * + * @param msg the detail message. + */ + public MalformedURLException(String msg) { + super(msg); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/net/URL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/net/URL.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,1037 @@ +/* + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net; + +import java.io.IOException; +import java.io.InputStream; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * Class URL represents a Uniform Resource + * Locator, a pointer to a "resource" on the World + * Wide Web. A resource can be something as simple as a file or a + * directory, or it can be a reference to a more complicated object, + * such as a query to a database or to a search engine. More + * information on the types of URLs and their formats can be found at: + *

    + * + * http://www.socs.uts.edu.au/MosaicDocs-old/url-primer.html + *
    + *

    + * In general, a URL can be broken into several parts. The previous + * example of a URL indicates that the protocol to use is + * http (HyperText Transfer Protocol) and that the + * information resides on a host machine named + * www.socs.uts.edu.au. The information on that host + * machine is named /MosaicDocs-old/url-primer.html. The exact + * meaning of this name on the host machine is both protocol + * dependent and host dependent. The information normally resides in + * a file, but it could be generated on the fly. This component of + * the URL is called the path component. + *

    + * A URL can optionally specify a "port", which is the + * port number to which the TCP connection is made on the remote host + * machine. If the port is not specified, the default port for + * the protocol is used instead. For example, the default port for + * http is 80. An alternative port could be + * specified as: + *

    + *     http://www.socs.uts.edu.au:80/MosaicDocs-old/url-primer.html
    + * 
    + *

    + * The syntax of URL is defined by RFC 2396: Uniform + * Resource Identifiers (URI): Generic Syntax, amended by RFC 2732: Format for + * Literal IPv6 Addresses in URLs. The Literal IPv6 address format + * also supports scope_ids. The syntax and usage of scope_ids is described + * here. + *

    + * A URL may have appended to it a "fragment", also known + * as a "ref" or a "reference". The fragment is indicated by the sharp + * sign character "#" followed by more characters. For example, + *

    + *     http://java.sun.com/index.html#chapter1
    + * 
    + *

    + * This fragment is not technically part of the URL. Rather, it + * indicates that after the specified resource is retrieved, the + * application is specifically interested in that part of the + * document that has the tag chapter1 attached to it. The + * meaning of a tag is resource specific. + *

    + * An application can also specify a "relative URL", + * which contains only enough information to reach the resource + * relative to another URL. Relative URLs are frequently used within + * HTML pages. For example, if the contents of the URL: + *

    + *     http://java.sun.com/index.html
    + * 
    + * contained within it the relative URL: + *
    + *     FAQ.html
    + * 
    + * it would be a shorthand for: + *
    + *     http://java.sun.com/FAQ.html
    + * 
    + *

    + * The relative URL need not specify all the components of a URL. If + * the protocol, host name, or port number is missing, the value is + * inherited from the fully specified URL. The file component must be + * specified. The optional fragment is not inherited. + *

    + * The URL class does not itself encode or decode any URL components + * according to the escaping mechanism defined in RFC2396. It is the + * responsibility of the caller to encode any fields, which need to be + * escaped prior to calling URL, and also to decode any escaped fields, + * that are returned from URL. Furthermore, because URL has no knowledge + * of URL escaping, it does not recognise equivalence between the encoded + * or decoded form of the same URL. For example, the two URLs:
    + *

        http://foo.com/hello world/ and http://foo.com/hello%20world
    + * would be considered not equal to each other. + *

    + * Note, the {@link java.net.URI} class does perform escaping of its + * component fields in certain circumstances. The recommended way + * to manage the encoding and decoding of URLs is to use {@link java.net.URI}, + * and to convert between these two classes using {@link #toURI()} and + * {@link URI#toURL()}. + *

    + * The {@link URLEncoder} and {@link URLDecoder} classes can also be + * used, but only for HTML form encoding, which is not the same + * as the encoding scheme defined in RFC2396. + * + * @author James Gosling + * @since JDK1.0 + */ +public final class URL implements java.io.Serializable { + + static final long serialVersionUID = -7627629688361524110L; + + /** + * The property which specifies the package prefix list to be scanned + * for protocol handlers. The value of this property (if any) should + * be a vertical bar delimited list of package names to search through + * for a protocol handler to load. The policy of this class is that + * all protocol handlers will be in a class called .Handler, + * and each package in the list is examined in turn for a matching + * handler. If none are found (or the property is not specified), the + * default package prefix, sun.net.www.protocol, is used. The search + * proceeds from the first package in the list to the last and stops + * when a match is found. + */ + private static final String protocolPathProp = "java.protocol.handler.pkgs"; + + /** + * The protocol to use (ftp, http, nntp, ... etc.) . + * @serial + */ + private String protocol; + + /** + * The host name to connect to. + * @serial + */ + private String host; + + /** + * The protocol port to connect to. + * @serial + */ + private int port = -1; + + /** + * The specified file name on that host. file is + * defined as path[?query] + * @serial + */ + private String file; + + /** + * The query part of this URL. + */ + private transient String query; + + /** + * The authority part of this URL. + * @serial + */ + private String authority; + + /** + * The path part of this URL. + */ + private transient String path; + + /** + * The userinfo part of this URL. + */ + private transient String userInfo; + + /** + * # reference. + * @serial + */ + private String ref; + + /** + * The host's IP address, used in equals and hashCode. + * Computed on demand. An uninitialized or unknown hostAddress is null. + */ + transient Object hostAddress; + + /** + * The URLStreamHandler for this URL. + */ + transient URLStreamHandler handler; + + /* Our hash code. + * @serial + */ + private int hashCode = -1; + + /** + * Creates a URL object from the specified + * protocol, host, port + * number, and file.

    + * + * host can be expressed as a host name or a literal + * IP address. If IPv6 literal address is used, it should be + * enclosed in square brackets ('[' and ']'), as + * specified by RFC 2732; + * However, the literal IPv6 address format defined in RFC 2373: IP + * Version 6 Addressing Architecture is also accepted.

    + * + * Specifying a port number of -1 + * indicates that the URL should use the default port for the + * protocol.

    + * + * If this is the first URL object being created with the specified + * protocol, a stream protocol handler object, an instance of + * class URLStreamHandler, is created for that protocol: + *

      + *
    1. If the application has previously set up an instance of + * URLStreamHandlerFactory as the stream handler factory, + * then the createURLStreamHandler method of that instance + * is called with the protocol string as an argument to create the + * stream protocol handler. + *
    2. If no URLStreamHandlerFactory has yet been set up, + * or if the factory's createURLStreamHandler method + * returns null, then the constructor finds the + * value of the system property: + *
      +     *         java.protocol.handler.pkgs
      +     *     
      + * If the value of that system property is not null, + * it is interpreted as a list of packages separated by a vertical + * slash character '|'. The constructor tries to load + * the class named: + *
      +     *         <package>.<protocol>.Handler
      +     *     
      + * where <package> is replaced by the name of the package + * and <protocol> is replaced by the name of the protocol. + * If this class does not exist, or if the class exists but it is not + * a subclass of URLStreamHandler, then the next package + * in the list is tried. + *
    3. If the previous step fails to find a protocol handler, then the + * constructor tries to load from a system default package. + *
      +     *         <system default package>.<protocol>.Handler
      +     *     
      + * If this class does not exist, or if the class exists but it is not a + * subclass of URLStreamHandler, then a + * MalformedURLException is thrown. + *
    + * + *

    Protocol handlers for the following protocols are guaranteed + * to exist on the search path :- + *

    +     *     http, https, ftp, file, and jar
    +     * 
    + * Protocol handlers for additional protocols may also be + * available. + * + *

    No validation of the inputs is performed by this constructor. + * + * @param protocol the name of the protocol to use. + * @param host the name of the host. + * @param port the port number on the host. + * @param file the file on the host + * @exception MalformedURLException if an unknown protocol is specified. + * @see java.lang.System#getProperty(java.lang.String) + * @see java.net.URL#setURLStreamHandlerFactory( + * java.net.URLStreamHandlerFactory) + * @see java.net.URLStreamHandler + * @see java.net.URLStreamHandlerFactory#createURLStreamHandler( + * java.lang.String) + */ + public URL(String protocol, String host, int port, String file) + throws MalformedURLException + { + this(protocol, host, port, file, null); + } + + /** + * Creates a URL from the specified protocol + * name, host name, and file name. The + * default port for the specified protocol is used. + *

    + * This method is equivalent to calling the four-argument + * constructor with the arguments being protocol, + * host, -1, and file. + * + * No validation of the inputs is performed by this constructor. + * + * @param protocol the name of the protocol to use. + * @param host the name of the host. + * @param file the file on the host. + * @exception MalformedURLException if an unknown protocol is specified. + * @see java.net.URL#URL(java.lang.String, java.lang.String, + * int, java.lang.String) + */ + public URL(String protocol, String host, String file) + throws MalformedURLException { + this(protocol, host, -1, file); + } + + /** + * Creates a URL object from the specified + * protocol, host, port + * number, file, and handler. Specifying + * a port number of -1 indicates that + * the URL should use the default port for the protocol. Specifying + * a handler of null indicates that the URL + * should use a default stream handler for the protocol, as outlined + * for: + * java.net.URL#URL(java.lang.String, java.lang.String, int, + * java.lang.String) + * + *

    If the handler is not null and there is a security manager, + * the security manager's checkPermission + * method is called with a + * NetPermission("specifyStreamHandler") permission. + * This may result in a SecurityException. + * + * No validation of the inputs is performed by this constructor. + * + * @param protocol the name of the protocol to use. + * @param host the name of the host. + * @param port the port number on the host. + * @param file the file on the host + * @param handler the stream handler for the URL. + * @exception MalformedURLException if an unknown protocol is specified. + * @exception SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * specifying a stream handler explicitly. + * @see java.lang.System#getProperty(java.lang.String) + * @see java.net.URL#setURLStreamHandlerFactory( + * java.net.URLStreamHandlerFactory) + * @see java.net.URLStreamHandler + * @see java.net.URLStreamHandlerFactory#createURLStreamHandler( + * java.lang.String) + * @see SecurityManager#checkPermission + * @see java.net.NetPermission + */ + public URL(String protocol, String host, int port, String file, + URLStreamHandler handler) throws MalformedURLException { + if (handler != null) { + throw new SecurityException(); + } + + protocol = protocol.toLowerCase(); + this.protocol = protocol; + if (host != null) { + + /** + * if host is a literal IPv6 address, + * we will make it conform to RFC 2732 + */ + if (host.indexOf(':') >= 0 && !host.startsWith("[")) { + host = "["+host+"]"; + } + this.host = host; + + if (port < -1) { + throw new MalformedURLException("Invalid port number :" + + port); + } + this.port = port; + authority = (port == -1) ? host : host + ":" + port; + } + + Parts parts = new Parts(file); + path = parts.getPath(); + query = parts.getQuery(); + + if (query != null) { + this.file = path + "?" + query; + } else { + this.file = path; + } + ref = parts.getRef(); + + // Note: we don't do validation of the URL here. Too risky to change + // right now, but worth considering for future reference. -br + if (handler == null && + (handler = getURLStreamHandler(protocol)) == null) { + throw new MalformedURLException("unknown protocol: " + protocol); + } + this.handler = handler; + } + + /** + * Creates a URL object from the String + * representation. + *

    + * This constructor is equivalent to a call to the two-argument + * constructor with a null first argument. + * + * @param spec the String to parse as a URL. + * @exception MalformedURLException if no protocol is specified, or an + * unknown protocol is found, or spec is null. + * @see java.net.URL#URL(java.net.URL, java.lang.String) + */ + public URL(String spec) throws MalformedURLException { + this(null, spec); + } + + /** + * Creates a URL by parsing the given spec within a specified context. + * + * The new URL is created from the given context URL and the spec + * argument as described in + * RFC2396 "Uniform Resource Identifiers : Generic * Syntax" : + *

    +     *          <scheme>://<authority><path>?<query>#<fragment>
    +     * 
    + * The reference is parsed into the scheme, authority, path, query and + * fragment parts. If the path component is empty and the scheme, + * authority, and query components are undefined, then the new URL is a + * reference to the current document. Otherwise, the fragment and query + * parts present in the spec are used in the new URL. + *

    + * If the scheme component is defined in the given spec and does not match + * the scheme of the context, then the new URL is created as an absolute + * URL based on the spec alone. Otherwise the scheme component is inherited + * from the context URL. + *

    + * If the authority component is present in the spec then the spec is + * treated as absolute and the spec authority and path will replace the + * context authority and path. If the authority component is absent in the + * spec then the authority of the new URL will be inherited from the + * context. + *

    + * If the spec's path component begins with a slash character + * "/" then the + * path is treated as absolute and the spec path replaces the context path. + *

    + * Otherwise, the path is treated as a relative path and is appended to the + * context path, as described in RFC2396. Also, in this case, + * the path is canonicalized through the removal of directory + * changes made by occurences of ".." and ".". + *

    + * For a more detailed description of URL parsing, refer to RFC2396. + * + * @param context the context in which to parse the specification. + * @param spec the String to parse as a URL. + * @exception MalformedURLException if no protocol is specified, or an + * unknown protocol is found, or spec is null. + * @see java.net.URL#URL(java.lang.String, java.lang.String, + * int, java.lang.String) + * @see java.net.URLStreamHandler + * @see java.net.URLStreamHandler#parseURL(java.net.URL, + * java.lang.String, int, int) + */ + public URL(URL context, String spec) throws MalformedURLException { + this(context, spec, null); + } + + /** + * Creates a URL by parsing the given spec with the specified handler + * within a specified context. If the handler is null, the parsing + * occurs as with the two argument constructor. + * + * @param context the context in which to parse the specification. + * @param spec the String to parse as a URL. + * @param handler the stream handler for the URL. + * @exception MalformedURLException if no protocol is specified, or an + * unknown protocol is found, or spec is null. + * @exception SecurityException + * if a security manager exists and its + * checkPermission method doesn't allow + * specifying a stream handler. + * @see java.net.URL#URL(java.lang.String, java.lang.String, + * int, java.lang.String) + * @see java.net.URLStreamHandler + * @see java.net.URLStreamHandler#parseURL(java.net.URL, + * java.lang.String, int, int) + */ + public URL(URL context, String spec, URLStreamHandler handler) + throws MalformedURLException + { + String original = spec; + int i, limit, c; + int start = 0; + String newProtocol = null; + boolean aRef=false; + boolean isRelative = false; + + // Check for permission to specify a handler + if (handler != null) { + throw new SecurityException(); + } + + try { + limit = spec.length(); + while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) { + limit--; //eliminate trailing whitespace + } + while ((start < limit) && (spec.charAt(start) <= ' ')) { + start++; // eliminate leading whitespace + } + + if (spec.regionMatches(true, start, "url:", 0, 4)) { + start += 4; + } + if (start < spec.length() && spec.charAt(start) == '#') { + /* we're assuming this is a ref relative to the context URL. + * This means protocols cannot start w/ '#', but we must parse + * ref URL's like: "hello:there" w/ a ':' in them. + */ + aRef=true; + } + for (i = start ; !aRef && (i < limit) && + ((c = spec.charAt(i)) != '/') ; i++) { + if (c == ':') { + + String s = spec.substring(start, i).toLowerCase(); + if (isValidProtocol(s)) { + newProtocol = s; + start = i + 1; + } + break; + } + } + + // Only use our context if the protocols match. + protocol = newProtocol; + if ((context != null) && ((newProtocol == null) || + newProtocol.equalsIgnoreCase(context.protocol))) { + // inherit the protocol handler from the context + // if not specified to the constructor + if (handler == null) { + handler = context.handler; + } + + // If the context is a hierarchical URL scheme and the spec + // contains a matching scheme then maintain backwards + // compatibility and treat it as if the spec didn't contain + // the scheme; see 5.2.3 of RFC2396 + if (context.path != null && context.path.startsWith("/")) + newProtocol = null; + + if (newProtocol == null) { + protocol = context.protocol; + authority = context.authority; + userInfo = context.userInfo; + host = context.host; + port = context.port; + file = context.file; + path = context.path; + isRelative = true; + } + } + + if (protocol == null) { + throw new MalformedURLException("no protocol: "+original); + } + + // Get the protocol handler if not specified or the protocol + // of the context could not be used + if (handler == null && + (handler = getURLStreamHandler(protocol)) == null) { + throw new MalformedURLException("unknown protocol: "+protocol); + } + this.handler = handler; + + i = spec.indexOf('#', start); + if (i >= 0) { +//thrw(protocol + " hnd: " + handler.getClass().getName() + " i: " + i); + ref = spec.substring(i + 1, limit); + limit = i; + } + + /* + * Handle special case inheritance of query and fragment + * implied by RFC2396 section 5.2.2. + */ + if (isRelative && start == limit) { + query = context.query; + if (ref == null) { + ref = context.ref; + } + } + + handler.parseURL(this, spec, start, limit); + + } catch(MalformedURLException e) { + throw e; + } catch(Exception e) { + MalformedURLException exception = new MalformedURLException(e.getMessage()); + exception.initCause(e); + throw exception; + } + } + + /* + * Returns true if specified string is a valid protocol name. + */ + private boolean isValidProtocol(String protocol) { + int len = protocol.length(); + if (len < 1) + return false; + char c = protocol.charAt(0); + if (!Character.isLetter(c)) + return false; + for (int i = 1; i < len; i++) { + c = protocol.charAt(i); + if (!Character.isLetterOrDigit(c) && c != '.' && c != '+' && + c != '-') { + return false; + } + } + return true; + } + + /** + * Sets the fields of the URL. This is not a public method so that + * only URLStreamHandlers can modify URL fields. URLs are + * otherwise constant. + * + * @param protocol the name of the protocol to use + * @param host the name of the host + @param port the port number on the host + * @param file the file on the host + * @param ref the internal reference in the URL + */ + protected void set(String protocol, String host, + int port, String file, String ref) { + synchronized (this) { + this.protocol = protocol; + this.host = host; + authority = port == -1 ? host : host + ":" + port; + this.port = port; + this.file = file; + this.ref = ref; + /* This is very important. We must recompute this after the + * URL has been changed. */ + hashCode = -1; + hostAddress = null; + int q = file.lastIndexOf('?'); + if (q != -1) { + query = file.substring(q+1); + path = file.substring(0, q); + } else + path = file; + } + } + + /** + * Sets the specified 8 fields of the URL. This is not a public method so + * that only URLStreamHandlers can modify URL fields. URLs are otherwise + * constant. + * + * @param protocol the name of the protocol to use + * @param host the name of the host + * @param port the port number on the host + * @param authority the authority part for the url + * @param userInfo the username and password + * @param path the file on the host + * @param ref the internal reference in the URL + * @param query the query part of this URL + * @since 1.3 + */ + protected void set(String protocol, String host, int port, + String authority, String userInfo, String path, + String query, String ref) { + synchronized (this) { + this.protocol = protocol; + this.host = host; + this.port = port; + this.file = query == null ? path : path + "?" + query; + this.userInfo = userInfo; + this.path = path; + this.ref = ref; + /* This is very important. We must recompute this after the + * URL has been changed. */ + hashCode = -1; + hostAddress = null; + this.query = query; + this.authority = authority; + } + } + + /** + * Gets the query part of this URL. + * + * @return the query part of this URL, + * or null if one does not exist + * @since 1.3 + */ + public String getQuery() { + return query; + } + + /** + * Gets the path part of this URL. + * + * @return the path part of this URL, or an + * empty string if one does not exist + * @since 1.3 + */ + public String getPath() { + return path; + } + + /** + * Gets the userInfo part of this URL. + * + * @return the userInfo part of this URL, or + * null if one does not exist + * @since 1.3 + */ + public String getUserInfo() { + return userInfo; + } + + /** + * Gets the authority part of this URL. + * + * @return the authority part of this URL + * @since 1.3 + */ + public String getAuthority() { + return authority; + } + + /** + * Gets the port number of this URL. + * + * @return the port number, or -1 if the port is not set + */ + public int getPort() { + return port; + } + + /** + * Gets the default port number of the protocol associated + * with this URL. If the URL scheme or the URLStreamHandler + * for the URL do not define a default port number, + * then -1 is returned. + * + * @return the port number + * @since 1.4 + */ + public int getDefaultPort() { + return handler.getDefaultPort(); + } + + /** + * Gets the protocol name of this URL. + * + * @return the protocol of this URL. + */ + public String getProtocol() { + return protocol; + } + + /** + * Gets the host name of this URL, if applicable. + * The format of the host conforms to RFC 2732, i.e. for a + * literal IPv6 address, this method will return the IPv6 address + * enclosed in square brackets ('[' and ']'). + * + * @return the host name of this URL. + */ + public String getHost() { + return host; + } + + /** + * Gets the file name of this URL. + * The returned file portion will be + * the same as getPath(), plus the concatenation of + * the value of getQuery(), if any. If there is + * no query portion, this method and getPath() will + * return identical results. + * + * @return the file name of this URL, + * or an empty string if one does not exist + */ + public String getFile() { + return file; + } + + /** + * Gets the anchor (also known as the "reference") of this + * URL. + * + * @return the anchor (also known as the "reference") of this + * URL, or null if one does not exist + */ + public String getRef() { + return ref; + } + + /** + * Compares this URL for equality with another object.

    + * + * If the given object is not a URL then this method immediately returns + * false.

    + * + * Two URL objects are equal if they have the same protocol, reference + * equivalent hosts, have the same port number on the host, and the same + * file and fragment of the file.

    + * + * Two hosts are considered equivalent if both host names can be resolved + * into the same IP addresses; else if either host name can't be + * resolved, the host names must be equal without regard to case; or both + * host names equal to null.

    + * + * Since hosts comparison requires name resolution, this operation is a + * blocking operation.

    + * + * Note: The defined behavior for equals is known to + * be inconsistent with virtual hosting in HTTP. + * + * @param obj the URL to compare against. + * @return true if the objects are the same; + * false otherwise. + */ + public boolean equals(Object obj) { + if (!(obj instanceof URL)) + return false; + URL u2 = (URL)obj; + + return handler.equals(this, u2); + } + + /** + * Creates an integer suitable for hash table indexing.

    + * + * The hash code is based upon all the URL components relevant for URL + * comparison. As such, this operation is a blocking operation.

    + * + * @return a hash code for this URL. + */ + public synchronized int hashCode() { + if (hashCode != -1) + return hashCode; + + hashCode = handler.hashCode(this); + return hashCode; + } + + /** + * Compares two URLs, excluding the fragment component.

    + * + * Returns true if this URL and the + * other argument are equal without taking the + * fragment component into consideration. + * + * @param other the URL to compare against. + * @return true if they reference the same remote object; + * false otherwise. + */ + public boolean sameFile(URL other) { + return handler.sameFile(this, other); + } + + /** + * Constructs a string representation of this URL. The + * string is created by calling the toExternalForm + * method of the stream protocol handler for this object. + * + * @return a string representation of this object. + * @see java.net.URL#URL(java.lang.String, java.lang.String, int, + * java.lang.String) + * @see java.net.URLStreamHandler#toExternalForm(java.net.URL) + */ + public String toString() { + return toExternalForm(); + } + + /** + * Constructs a string representation of this URL. The + * string is created by calling the toExternalForm + * method of the stream protocol handler for this object. + * + * @return a string representation of this object. + * @see java.net.URL#URL(java.lang.String, java.lang.String, + * int, java.lang.String) + * @see java.net.URLStreamHandler#toExternalForm(java.net.URL) + */ + public String toExternalForm() { + return handler.toExternalForm(this); + } + + /** + * Returns a {@link java.net.URLConnection URLConnection} instance that + * represents a connection to the remote object referred to by the + * {@code URL}. + * + *

    A new instance of {@linkplain java.net.URLConnection URLConnection} is + * created every time when invoking the + * {@linkplain java.net.URLStreamHandler#openConnection(URL) + * URLStreamHandler.openConnection(URL)} method of the protocol handler for + * this URL.

    + * + *

    It should be noted that a URLConnection instance does not establish + * the actual network connection on creation. This will happen only when + * calling {@linkplain java.net.URLConnection#connect() URLConnection.connect()}.

    + * + *

    If for the URL's protocol (such as HTTP or JAR), there + * exists a public, specialized URLConnection subclass belonging + * to one of the following packages or one of their subpackages: + * java.lang, java.io, java.util, java.net, the connection + * returned will be of that subclass. For example, for HTTP an + * HttpURLConnection will be returned, and for JAR a + * JarURLConnection will be returned.

    + * + * @return a {@link java.net.URLConnection URLConnection} linking + * to the URL. + * @exception IOException if an I/O exception occurs. + * @see java.net.URL#URL(java.lang.String, java.lang.String, + * int, java.lang.String) + */ +// public URLConnection openConnection() throws java.io.IOException { +// return handler.openConnection(this); +// } + + + /** + * Opens a connection to this URL and returns an + * InputStream for reading from that connection. This + * method is a shorthand for: + *
    +     *     openConnection().getInputStream()
    +     * 
    + * + * @return an input stream for reading from the URL connection. + * @exception IOException if an I/O exception occurs. + * @see java.net.URL#openConnection() + * @see java.net.URLConnection#getInputStream() + */ + public final InputStream openStream() throws java.io.IOException { + throw new IOException(); +// return openConnection().getInputStream(); + } + + /** + * Gets the contents of this URL. This method is a shorthand for: + *
    +     *     openConnection().getContent()
    +     * 
    + * + * @return the contents of this URL. + * @exception IOException if an I/O exception occurs. + * @see java.net.URLConnection#getContent() + */ + public final Object getContent() throws java.io.IOException { + return loadText(toExternalForm()); + } + + @JavaScriptBody(args = "url", body = "" + + "var request = new XMLHttpRequest();\n" + + "request.open('GET', url, false);\n" + + "request.send();\n" + + "return request.responseText;\n" + ) + private static native String loadText(String url) throws IOException; + + /** + * Gets the contents of this URL. This method is a shorthand for: + *
    +     *     openConnection().getContent(Class[])
    +     * 
    + * + * @param classes an array of Java types + * @return the content object of this URL that is the first match of + * the types specified in the classes array. + * null if none of the requested types are supported. + * @exception IOException if an I/O exception occurs. + * @see java.net.URLConnection#getContent(Class[]) + * @since 1.3 + */ + public final Object getContent(Class[] classes) + throws java.io.IOException { + for (Class c : classes) { + if (c == String.class) { + return getContent(); + } + } + return null; + } + + static URLStreamHandler getURLStreamHandler(String protocol) { + URLStreamHandler universal = new URLStreamHandler() {}; + return universal; + } + +} + +class Parts { + String path, query, ref; + + Parts(String file) { + int ind = file.indexOf('#'); + ref = ind < 0 ? null: file.substring(ind + 1); + file = ind < 0 ? file: file.substring(0, ind); + int q = file.lastIndexOf('?'); + if (q != -1) { + query = file.substring(q+1); + path = file.substring(0, q); + } else { + path = file; + } + } + + String getPath() { + return path; + } + + String getQuery() { + return query; + } + + String getRef() { + return ref; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/net/URLStreamHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/net/URLStreamHandler.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,568 @@ +/* + * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net; + + +/** + * The abstract class URLStreamHandler is the common + * superclass for all stream protocol handlers. A stream protocol + * handler knows how to make a connection for a particular protocol + * type, such as http, ftp, or + * gopher. + *

    + * In most cases, an instance of a URLStreamHandler + * subclass is not created directly by an application. Rather, the + * first time a protocol name is encountered when constructing a + * URL, the appropriate stream protocol handler is + * automatically loaded. + * + * @author James Gosling + * @see java.net.URL#URL(java.lang.String, java.lang.String, int, java.lang.String) + * @since JDK1.0 + */ +public abstract class URLStreamHandler { + /** + * Opens a connection to the object referenced by the + * URL argument. + * This method should be overridden by a subclass. + * + *

    If for the handler's protocol (such as HTTP or JAR), there + * exists a public, specialized URLConnection subclass belonging + * to one of the following packages or one of their subpackages: + * java.lang, java.io, java.util, java.net, the connection + * returned will be of that subclass. For example, for HTTP an + * HttpURLConnection will be returned, and for JAR a + * JarURLConnection will be returned. + * + * @param u the URL that this connects to. + * @return a URLConnection object for the URL. + * @exception IOException if an I/O error occurs while opening the + * connection. + */ +// abstract protected URLConnection openConnection(URL u) throws IOException; + + /** + * Same as openConnection(URL), except that the connection will be + * made through the specified proxy; Protocol handlers that do not + * support proxying will ignore the proxy parameter and make a + * normal connection. + * + * Calling this method preempts the system's default ProxySelector + * settings. + * + * @param u the URL that this connects to. + * @param p the proxy through which the connection will be made. + * If direct connection is desired, Proxy.NO_PROXY + * should be specified. + * @return a URLConnection object for the URL. + * @exception IOException if an I/O error occurs while opening the + * connection. + * @exception IllegalArgumentException if either u or p is null, + * or p has the wrong type. + * @exception UnsupportedOperationException if the subclass that + * implements the protocol doesn't support this method. + * @since 1.5 + */ +// protected URLConnection openConnection(URL u, Proxy p) throws IOException { +// throw new UnsupportedOperationException("Method not implemented."); +// } + + /** + * Parses the string representation of a URL into a + * URL object. + *

    + * If there is any inherited context, then it has already been + * copied into the URL argument. + *

    + * The parseURL method of URLStreamHandler + * parses the string representation as if it were an + * http specification. Most URL protocol families have a + * similar parsing. A stream protocol handler for a protocol that has + * a different syntax must override this routine. + * + * @param u the URL to receive the result of parsing + * the spec. + * @param spec the String representing the URL that + * must be parsed. + * @param start the character index at which to begin parsing. This is + * just past the ':' (if there is one) that + * specifies the determination of the protocol name. + * @param limit the character position to stop parsing at. This is the + * end of the string or the position of the + * "#" character, if present. All information + * after the sharp sign indicates an anchor. + */ + protected void parseURL(URL u, String spec, int start, int limit) { + // These fields may receive context content if this was relative URL + String protocol = u.getProtocol(); + String authority = u.getAuthority(); + String userInfo = u.getUserInfo(); + String host = u.getHost(); + int port = u.getPort(); + String path = u.getPath(); + String query = u.getQuery(); + + // This field has already been parsed + String ref = u.getRef(); + + boolean isRelPath = false; + boolean queryOnly = false; + +// FIX: should not assume query if opaque + // Strip off the query part + if (start < limit) { + int queryStart = spec.indexOf('?'); + queryOnly = queryStart == start; + if ((queryStart != -1) && (queryStart < limit)) { + query = spec.substring(queryStart+1, limit); + if (limit > queryStart) + limit = queryStart; + spec = spec.substring(0, queryStart); + } + } + + int i = 0; + // Parse the authority part if any + boolean isUNCName = (start <= limit - 4) && + (spec.charAt(start) == '/') && + (spec.charAt(start + 1) == '/') && + (spec.charAt(start + 2) == '/') && + (spec.charAt(start + 3) == '/'); + if (!isUNCName && (start <= limit - 2) && (spec.charAt(start) == '/') && + (spec.charAt(start + 1) == '/')) { + start += 2; + i = spec.indexOf('/', start); + if (i < 0) { + i = spec.indexOf('?', start); + if (i < 0) + i = limit; + } + + host = authority = spec.substring(start, i); + + int ind = authority.indexOf('@'); + if (ind != -1) { + userInfo = authority.substring(0, ind); + host = authority.substring(ind+1); + } else { + userInfo = null; + } + if (host != null) { + // If the host is surrounded by [ and ] then its an IPv6 + // literal address as specified in RFC2732 + if (host.length()>0 && (host.charAt(0) == '[')) { + if ((ind = host.indexOf(']')) > 2) { + + String nhost = host ; + host = nhost.substring(0,ind+1); +// if (!IPAddressUtil. +// isIPv6LiteralAddress(host.substring(1, ind))) { +// throw new IllegalArgumentException( +// "Invalid host: "+ host); +// } + + port = -1 ; + if (nhost.length() > ind+1) { + if (nhost.charAt(ind+1) == ':') { + ++ind ; + // port can be null according to RFC2396 + if (nhost.length() > (ind + 1)) { + port = Integer.parseInt(nhost.substring(ind+1)); + } + } else { + throw new IllegalArgumentException( + "Invalid authority field: " + authority); + } + } + } else { + throw new IllegalArgumentException( + "Invalid authority field: " + authority); + } + } else { + ind = host.indexOf(':'); + port = -1; + if (ind >= 0) { + // port can be null according to RFC2396 + if (host.length() > (ind + 1)) { + port = Integer.parseInt(host.substring(ind + 1)); + } + host = host.substring(0, ind); + } + } + } else { + host = ""; + } + if (port < -1) + throw new IllegalArgumentException("Invalid port number :" + + port); + start = i; + // If the authority is defined then the path is defined by the + // spec only; See RFC 2396 Section 5.2.4. + if (authority != null && authority.length() > 0) + path = ""; + } + + if (host == null) { + host = ""; + } + + // Parse the file path if any + if (start < limit) { + if (spec.charAt(start) == '/') { + path = spec.substring(start, limit); + } else if (path != null && path.length() > 0) { + isRelPath = true; + int ind = path.lastIndexOf('/'); + String seperator = ""; + if (ind == -1 && authority != null) + seperator = "/"; + path = path.substring(0, ind + 1) + seperator + + spec.substring(start, limit); + + } else { + String seperator = (authority != null) ? "/" : ""; + path = seperator + spec.substring(start, limit); + } + } else if (queryOnly && path != null) { + int ind = path.lastIndexOf('/'); + if (ind < 0) + ind = 0; + path = path.substring(0, ind) + "/"; + } + if (path == null) + path = ""; + + if (isRelPath) { + // Remove embedded /./ + while ((i = path.indexOf("/./")) >= 0) { + path = path.substring(0, i) + path.substring(i + 2); + } + // Remove embedded /../ if possible + i = 0; + while ((i = path.indexOf("/../", i)) >= 0) { + /* + * A "/../" will cancel the previous segment and itself, + * unless that segment is a "/../" itself + * i.e. "/a/b/../c" becomes "/a/c" + * but "/../../a" should stay unchanged + */ + if (i > 0 && (limit = path.lastIndexOf('/', i - 1)) >= 0 && + (path.indexOf("/../", limit) != 0)) { + path = path.substring(0, limit) + path.substring(i + 3); + i = 0; + } else { + i = i + 3; + } + } + // Remove trailing .. if possible + while (path.endsWith("/..")) { + i = path.indexOf("/.."); + if ((limit = path.lastIndexOf('/', i - 1)) >= 0) { + path = path.substring(0, limit+1); + } else { + break; + } + } + // Remove starting . + if (path.startsWith("./") && path.length() > 2) + path = path.substring(2); + + // Remove trailing . + if (path.endsWith("/.")) + path = path.substring(0, path.length() -1); + } + + setURL(u, protocol, host, port, authority, userInfo, path, query, ref); + } + + /** + * Returns the default port for a URL parsed by this handler. This method + * is meant to be overidden by handlers with default port numbers. + * @return the default port for a URL parsed by this handler. + * @since 1.3 + */ + protected int getDefaultPort() { + return -1; + } + + /** + * Provides the default equals calculation. May be overidden by handlers + * for other protocols that have different requirements for equals(). + * This method requires that none of its arguments is null. This is + * guaranteed by the fact that it is only called by java.net.URL class. + * @param u1 a URL object + * @param u2 a URL object + * @return true if the two urls are + * considered equal, ie. they refer to the same + * fragment in the same file. + * @since 1.3 + */ + protected boolean equals(URL u1, URL u2) { + String ref1 = u1.getRef(); + String ref2 = u2.getRef(); + return (ref1 == ref2 || (ref1 != null && ref1.equals(ref2))) && + sameFile(u1, u2); + } + + /** + * Provides the default hash calculation. May be overidden by handlers for + * other protocols that have different requirements for hashCode + * calculation. + * @param u a URL object + * @return an int suitable for hash table indexing + * @since 1.3 + */ + protected int hashCode(URL u) { + int h = 0; + + // Generate the protocol part. + String protocol = u.getProtocol(); + if (protocol != null) + h += protocol.hashCode(); + + // Generate the host part. + Object addr = getHostAddress(u); + if (addr != null) { + h += addr.hashCode(); + } else { + String host = u.getHost(); + if (host != null) + h += host.toLowerCase().hashCode(); + } + + // Generate the file part. + String file = u.getFile(); + if (file != null) + h += file.hashCode(); + + // Generate the port part. + if (u.getPort() == -1) + h += getDefaultPort(); + else + h += u.getPort(); + + // Generate the ref part. + String ref = u.getRef(); + if (ref != null) + h += ref.hashCode(); + + return h; + } + + /** + * Compare two urls to see whether they refer to the same file, + * i.e., having the same protocol, host, port, and path. + * This method requires that none of its arguments is null. This is + * guaranteed by the fact that it is only called indirectly + * by java.net.URL class. + * @param u1 a URL object + * @param u2 a URL object + * @return true if u1 and u2 refer to the same file + * @since 1.3 + */ + protected boolean sameFile(URL u1, URL u2) { + // Compare the protocols. + if (!((u1.getProtocol() == u2.getProtocol()) || + (u1.getProtocol() != null && + u1.getProtocol().equalsIgnoreCase(u2.getProtocol())))) + return false; + + // Compare the files. + if (!(u1.getFile() == u2.getFile() || + (u1.getFile() != null && u1.getFile().equals(u2.getFile())))) + return false; + + // Compare the ports. + int port1, port2; + port1 = (u1.getPort() != -1) ? u1.getPort() : u1.handler.getDefaultPort(); + port2 = (u2.getPort() != -1) ? u2.getPort() : u2.handler.getDefaultPort(); + if (port1 != port2) + return false; + + // Compare the hosts. + if (!hostsEqual(u1, u2)) + return false; + + return true; + } + + /** + * Get the IP address of our host. An empty host field or a DNS failure + * will result in a null return. + * + * @param u a URL object + * @return an InetAddress representing the host + * IP address. + * @since 1.3 + */ + private synchronized Object getHostAddress(URL u) { + return u.hostAddress; + } + + /** + * Compares the host components of two URLs. + * @param u1 the URL of the first host to compare + * @param u2 the URL of the second host to compare + * @return true if and only if they + * are equal, false otherwise. + * @since 1.3 + */ + protected boolean hostsEqual(URL u1, URL u2) { + Object a1 = getHostAddress(u1); + Object a2 = getHostAddress(u2); + // if we have internet address for both, compare them + if (a1 != null && a2 != null) { + return a1.equals(a2); + // else, if both have host names, compare them + } else if (u1.getHost() != null && u2.getHost() != null) + return u1.getHost().equalsIgnoreCase(u2.getHost()); + else + return u1.getHost() == null && u2.getHost() == null; + } + + /** + * Converts a URL of a specific protocol to a + * String. + * + * @param u the URL. + * @return a string representation of the URL argument. + */ + protected String toExternalForm(URL u) { + + // pre-compute length of StringBuffer + int len = u.getProtocol().length() + 1; + if (u.getAuthority() != null && u.getAuthority().length() > 0) + len += 2 + u.getAuthority().length(); + if (u.getPath() != null) { + len += u.getPath().length(); + } + if (u.getQuery() != null) { + len += 1 + u.getQuery().length(); + } + if (u.getRef() != null) + len += 1 + u.getRef().length(); + + StringBuffer result = new StringBuffer(len); + result.append(u.getProtocol()); + result.append(":"); + if (u.getAuthority() != null && u.getAuthority().length() > 0) { + result.append("//"); + result.append(u.getAuthority()); + } + if (u.getPath() != null) { + result.append(u.getPath()); + } + if (u.getQuery() != null) { + result.append('?'); + result.append(u.getQuery()); + } + if (u.getRef() != null) { + result.append("#"); + result.append(u.getRef()); + } + return result.toString(); + } + + /** + * Sets the fields of the URL argument to the indicated values. + * Only classes derived from URLStreamHandler are supposed to be able + * to call the set method on a URL. + * + * @param u the URL to modify. + * @param protocol the protocol name. + * @param host the remote host value for the URL. + * @param port the port on the remote machine. + * @param authority the authority part for the URL. + * @param userInfo the userInfo part of the URL. + * @param path the path component of the URL. + * @param query the query part for the URL. + * @param ref the reference. + * @exception SecurityException if the protocol handler of the URL is + * different from this one + * @see java.net.URL#set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String) + * @since 1.3 + */ + protected void setURL(URL u, String protocol, String host, int port, + String authority, String userInfo, String path, + String query, String ref) { + if (this != u.handler) { + throw new SecurityException("handler for url different from " + + "this handler"); + } + // ensure that no one can reset the protocol on a given URL. + u.set(u.getProtocol(), host, port, authority, userInfo, path, query, ref); + } + + /** + * Sets the fields of the URL argument to the indicated values. + * Only classes derived from URLStreamHandler are supposed to be able + * to call the set method on a URL. + * + * @param u the URL to modify. + * @param protocol the protocol name. This value is ignored since 1.2. + * @param host the remote host value for the URL. + * @param port the port on the remote machine. + * @param file the file. + * @param ref the reference. + * @exception SecurityException if the protocol handler of the URL is + * different from this one + * @deprecated Use setURL(URL, String, String, int, String, String, String, + * String); + */ + @Deprecated + protected void setURL(URL u, String protocol, String host, int port, + String file, String ref) { + /* + * Only old URL handlers call this, so assume that the host + * field might contain "user:passwd@host". Fix as necessary. + */ + String authority = null; + String userInfo = null; + if (host != null && host.length() != 0) { + authority = (port == -1) ? host : host + ":" + port; + int at = host.lastIndexOf('@'); + if (at != -1) { + userInfo = host.substring(0, at); + host = host.substring(at+1); + } + } + + /* + * Assume file might contain query part. Fix as necessary. + */ + String path = null; + String query = null; + if (file != null) { + int q = file.lastIndexOf('?'); + if (q != -1) { + query = file.substring(q+1); + path = file.substring(0, q); + } else + path = file; + } + setURL(u, protocol, host, port, authority, userInfo, path, query, ref); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/util/Enumeration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/util/Enumeration.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util; + +/** + * An object that implements the Enumeration interface generates a + * series of elements, one at a time. Successive calls to the + * nextElement method return successive elements of the + * series. + *

    + * For example, to print all elements of a Vector<E> v: + *

    + *   for (Enumeration<E> e = v.elements(); e.hasMoreElements();)
    + *       System.out.println(e.nextElement());
    + *

    + * Methods are provided to enumerate through the elements of a + * vector, the keys of a hashtable, and the values in a hashtable. + * Enumerations are also used to specify the input streams to a + * SequenceInputStream. + *

    + * NOTE: The functionality of this interface is duplicated by the Iterator + * interface. In addition, Iterator adds an optional remove operation, and + * has shorter method names. New implementations should consider using + * Iterator in preference to Enumeration. + * + * @see java.util.Iterator + * @see java.io.SequenceInputStream + * @see java.util.Enumeration#nextElement() + * @see java.util.Hashtable + * @see java.util.Hashtable#elements() + * @see java.util.Hashtable#keys() + * @see java.util.Vector + * @see java.util.Vector#elements() + * + * @author Lee Boynton + * @since JDK1.0 + */ +public interface Enumeration { + /** + * Tests if this enumeration contains more elements. + * + * @return true if and only if this enumeration object + * contains at least one more element to provide; + * false otherwise. + */ + boolean hasMoreElements(); + + /** + * Returns the next element of this enumeration if this enumeration + * object has at least one more element to provide. + * + * @return the next element of this enumeration. + * @exception NoSuchElementException if no more elements exist. + */ + E nextElement(); +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/java/util/NoSuchElementException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/util/NoSuchElementException.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util; + +/** + * Thrown by the nextElement method of an + * Enumeration to indicate that there are no more + * elements in the enumeration. + * + * @author unascribed + * @see java.util.Enumeration + * @see java.util.Enumeration#nextElement() + * @since JDK1.0 + */ +public +class NoSuchElementException extends RuntimeException { + private static final long serialVersionUID = 6769829250639411880L; + + /** + * Constructs a NoSuchElementException with null + * as its error message string. + */ + public NoSuchElementException() { + super(); + } + + /** + * Constructs a NoSuchElementException, saving a reference + * to the error message string s for later retrieval by the + * getMessage method. + * + * @param s the detail message. + */ + public NoSuchElementException(String s) { + super(s); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/org/apidesign/bck2brwsr/emul/AnnotationImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/org/apidesign/bck2brwsr/emul/AnnotationImpl.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,81 @@ +/** + * 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.bck2brwsr.emul; + +import java.lang.annotation.Annotation; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Jaroslav Tulach + */ +public final class AnnotationImpl implements Annotation { + public Class annotationType() { + return getClass(); + } + + @JavaScriptBody(args = { "a", "n", "values" }, body = "" + + "function f(v, p) {\n" + + " var val = v;\n" + + " var prop = p;\n" + + " return function() {\n" + + " return val[prop];\n" + + " };\n" + + "}\n" + + "var props = Object.getOwnPropertyNames(values);\n" + + "for (var i = 0; i < props.length; i++) {\n" + + " var p = props[i];\n" + + " a[p] = new f(values, p);\n" + + "}\n" + + "a['$instOf_' + n] = true;\n" + + "return a;" + ) + private static T create(AnnotationImpl a, String n, Object values) { + return null; + } + public static T create(Class annoClass, Object values) { + return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values); + } + + public static Annotation[] create(Object anno) { + String[] names = findNames(anno); + Annotation[] ret = new Annotation[names.length]; + for (int i = 0; i < names.length; i++) { + String n = names[i].substring(1, names[i].length() - 1).replace('/', '_'); + ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i])); + } + return ret; + } + @JavaScriptBody(args = "anno", body = + "var arr = new Array();" + + "var props = Object.getOwnPropertyNames(anno);\n" + + "for (var i = 0; i < props.length; i++) {\n" + + " var p = props[i];\n" + + " arr.push(p);" + + "}" + + "return arr;" + ) + private static String[] findNames(Object anno) { + throw new UnsupportedOperationException(); + } + + @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];") + private static Object findData(Object anno, String p) { + throw new UnsupportedOperationException(); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/java/org/apidesign/bck2brwsr/emul/MethodImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/org/apidesign/bck2brwsr/emul/MethodImpl.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,164 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.apidesign.bck2brwsr.emul; + +import java.lang.reflect.Method; +import java.util.Enumeration; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** Utilities to work on methods. + * + * @author Jaroslav Tulach + */ +public abstract class MethodImpl { + public static MethodImpl INSTANCE; + static { + try { + Class.forName(Method.class.getName()); + } catch (ClassNotFoundException ex) { + throw new IllegalStateException(ex); + } + } + + protected abstract Method create(Class declaringClass, String name, Object data, String sig); + + + // + // bck2brwsr implementation + // + + @JavaScriptBody(args = {"clazz", "prefix"}, + body = "" + + "var c = clazz.cnstr.prototype;" + + "var arr = new Array();\n" + + "for (m in c) {\n" + + " if (m.indexOf(prefix) === 0) {\n" + + " arr.push(m);\n" + + " arr.push(c[m]);\n" + + " }" + + "}\n" + + "return arr;") + private static native Object[] findMethodData( + Class clazz, String prefix); + + public static Method findMethod( + Class clazz, String name, Class... parameterTypes) { + Object[] data = findMethodData(clazz, name + "__"); + BIG: for (int i = 0; i < data.length; i += 2) { + String sig = ((String) data[0]).substring(name.length() + 2); + Method tmp = INSTANCE.create(clazz, name, data[1], sig); + Class[] tmpParms = tmp.getParameterTypes(); + if (parameterTypes.length != tmpParms.length) { + continue; + } + for (int j = 0; j < tmpParms.length; j++) { + if (!parameterTypes[j].equals(tmpParms[j])) { + continue BIG; + } + } + return tmp; + } + return null; + } + + public static Method[] findMethods(Class clazz, int mask) { + Object[] namesAndData = findMethodData(clazz, ""); + int cnt = 0; + for (int i = 0; i < namesAndData.length; i += 2) { + String sig = (String) namesAndData[i]; + Object data = namesAndData[i + 1]; + int middle = sig.indexOf("__"); + if (middle == -1) { + continue; + } + String name = sig.substring(0, middle); + sig = sig.substring(middle + 2); + final Method m = INSTANCE.create(clazz, name, data, sig); + if ((m.getModifiers() & mask) == 0) { + continue; + } + namesAndData[cnt++] = m; + } + Method[] arr = new Method[cnt]; + for (int i = 0; i < cnt; i++) { + arr[i] = (Method) namesAndData[i]; + } + return arr; + } + + public static int signatureElements(String sig) { + Enumeration en = signatureParser(sig); + int cnt = 0; + while (en.hasMoreElements()) { + en.nextElement(); + cnt++; + } + return cnt; + } + + public static Enumeration signatureParser(final String sig) { + class E implements Enumeration { + int pos; + + public boolean hasMoreElements() { + return pos < sig.length(); + } + + public Class nextElement() { + switch (sig.charAt(pos++)) { + case 'I': + return Integer.TYPE; + case 'J': + return Long.TYPE; + case 'D': + return Double.TYPE; + case 'F': + return Float.TYPE; + case 'B': + return Byte.TYPE; + case 'Z': + return Boolean.TYPE; + case 'S': + return Short.TYPE; + case 'V': + return Void.TYPE; + case 'C': + return Character.TYPE; + case 'L': + try { + int up = sig.indexOf("_2"); + String type = sig.substring(1, up); + pos = up + 2; + return Class.forName(type); + } catch (ClassNotFoundException ex) { + // should not happen + } + } + throw new UnsupportedOperationException(sig + " at " + pos); + } + } + return new E(); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_Number.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_Number.js Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,9 @@ +// empty line needed here +Number.prototype.add32 = function(x) { return (this + x) | 0; }; +Number.prototype.sub32 = function(x) { return (this - x) | 0; }; +Number.prototype.mul32 = function(x) { + return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0; +}; + +Number.prototype.toInt8 = function() { return (this << 24) >> 24; }; +Number.prototype.toInt16 = function() { return (this << 16) >> 16; }; \ No newline at end of file diff -r 029e6eed60e9 -r 388e48c0a37a emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js --- a/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Thu Oct 11 06:15:22 2012 -0700 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Wed Jan 23 20:16:48 2013 +0100 @@ -1,2658 +1,26 @@ -/* */ +// initialize methods on arrays and String constants +vm.java_lang_reflect_Array(false); +vm.java_lang_String(false); - -function java_lang_String_consVAC(arg0,arg1) { - arg0.r = arg1.join(""); -} - -function java_lang_String_consVACII(self, charArr, off, cnt) { - self.r = charArr.slice(off, off + cnt).join(""); -} - -function java_lang_String_charAtCI(arg0,arg1) { - return arg0.toString().charAt(arg1); -} -function java_lang_String_lengthI(arg0) { - return arg0.toString().length; -} -function java_lang_String_isEmptyZ(arg0) { - return arg0.toString().length === 0; -} - -/* -function java_lang_String_codePointAtII(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() < 0) { gt = 12; continue; } // 155 0 11 - case 4: stack.push(arg1); // 27 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: if (stack.pop() > stack.pop()) { gt = 21; continue; } // 161 0 12 - case 12: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 15: stack.push(stack[stack.length - 1]); // 89 - case 16: stack.push(arg1); // 27 - case 17: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 20: // 191 - case 21: stack.push(arg0); // 42 - case 22: stack.push(stack.pop().value); // 180 1 100 - case 25: stack.push(arg0); // 42 - case 26: stack.push(stack.pop().offset); // 180 1 99 - case 29: stack.push(arg1); // 27 - case 30: stack.push(stack.pop() + stack.pop()); // 96 - case 31: stack.push(arg0); // 42 - case 32: stack.push(stack.pop().offset); // 180 1 99 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().count); // 180 1 97 - case 39: stack.push(stack.pop() + stack.pop()); // 96 - case 40: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointAtImplAIACAIAI(v0, v1, v2)); } // 184 1 113 - case 43: return stack.pop(); // 172 +Array.prototype.at = function(indx, value) { + if (indx < 0 || indx > this.length) { + var e = vm.java_lang_ArrayIndexOutOfBoundsException(true); + e.constructor.cons__VLjava_lang_String_2.call(e, indx.toString()); + throw e; } -} -function java_lang_String_codePointBeforeII(arg0,arg1) { - var arg2; - var arg3; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: stack.push(1); // 4 - case 2: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 3: arg2 = stack.pop(); // 61 - case 4: stack.push(arg2); // 28 - case 5: if (stack.pop() < 0) { gt = 16; continue; } // 155 0 11 - case 8: stack.push(arg2); // 28 - case 9: stack.push(arg0); // 42 - case 10: stack.push(stack.pop().count); // 180 1 97 - case 13: if (stack.pop() > stack.pop()) { gt = 25; continue; } // 161 0 12 - case 16: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 19: stack.push(stack[stack.length - 1]); // 89 - case 20: stack.push(arg1); // 27 - case 21: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 24: // 191 - case 25: stack.push(arg0); // 42 - case 26: stack.push(stack.pop().value); // 180 1 100 - case 29: stack.push(arg0); // 42 - case 30: stack.push(stack.pop().offset); // 180 1 99 - case 33: stack.push(arg1); // 27 - case 34: stack.push(stack.pop() + stack.pop()); // 96 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().offset); // 180 1 99 - case 39: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointBeforeImplAIACAIAI(v0, v1, v2)); } // 184 1 114 - case 42: return stack.pop(); // 172 + if (arguments.length === 2) { + this[indx] = value; } -} -function java_lang_String_codePointCountIII(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() < 0) { gt = 17; continue; } // 155 0 16 - case 4: stack.push(arg2); // 28 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: if (stack.pop() < stack.pop()) { gt = 17; continue; } // 163 0 8 - case 12: stack.push(arg1); // 27 - case 13: stack.push(arg2); // 28 - case 14: if (stack.pop() >= stack.pop()) { gt = 25; continue; } // 164 0 11 - case 17: stack.push(new java_lang_IndexOutOfBoundsException); // 187 0 194 - case 20: stack.push(stack[stack.length - 1]); // 89 - case 21: { java_lang_IndexOutOfBoundsException_consV(stack.pop()); } // 183 1 124 - case 24: // 191 - case 25: stack.push(arg0); // 42 - case 26: stack.push(stack.pop().value); // 180 1 100 - case 29: stack.push(arg0); // 42 - case 30: stack.push(stack.pop().offset); // 180 1 99 - case 33: stack.push(arg1); // 27 - case 34: stack.push(stack.pop() + stack.pop()); // 96 - case 35: stack.push(arg2); // 28 - case 36: stack.push(arg1); // 27 - case 37: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 38: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointCountImplAIACAIAI(v0, v1, v2)); } // 184 1 115 - case 41: return stack.pop(); // 172 + return this[indx]; +}; +Array.prototype.getClass__Ljava_lang_Class_2 = function() { + return vm.java_lang_Class(false).defineArray__Ljava_lang_Class_2Ljava_lang_String_2(this.jvmName); +}; +Array.prototype.clone__Ljava_lang_Object_2 = function() { + var s = this.length; + var ret = new Array(s); + for (var i = 0; i < s; i++) { + ret[i] = this[i]; } -} -function java_lang_String_offsetByCodePointsIII(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() < 0) { gt = 12; continue; } // 155 0 11 - case 4: stack.push(arg1); // 27 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: if (stack.pop() >= stack.pop()) { gt = 20; continue; } // 164 0 11 - case 12: stack.push(new java_lang_IndexOutOfBoundsException); // 187 0 194 - case 15: stack.push(stack[stack.length - 1]); // 89 - case 16: { java_lang_IndexOutOfBoundsException_consV(stack.pop()); } // 183 1 124 - case 19: // 191 - case 20: stack.push(arg0); // 42 - case 21: stack.push(stack.pop().value); // 180 1 100 - case 24: stack.push(arg0); // 42 - case 25: stack.push(stack.pop().offset); // 180 1 99 - case 28: stack.push(arg0); // 42 - case 29: stack.push(stack.pop().count); // 180 1 97 - case 32: stack.push(arg0); // 42 - case 33: stack.push(stack.pop().offset); // 180 1 99 - case 36: stack.push(arg1); // 27 - case 37: stack.push(stack.pop() + stack.pop()); // 96 - case 38: stack.push(arg2); // 28 - case 39: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_offsetByCodePointsImplAIACAIAIAIAI(v0, v1, v2, v3, v4)); } // 184 1 116 - case 42: stack.push(arg0); // 42 - case 43: stack.push(stack.pop().offset); // 180 1 99 - case 46: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 47: return stack.pop(); // 172 - } -} -*/ - -// public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { -function java_lang_String_getCharsVIIACAI(arg0,arg1,arg2,arg3,arg4) { - var s = arg0.toString(); - while (arg1 < arg2) { - arg3[arg4++] = s[arg1++]; - } -} - -/* -function java_lang_String_getBytesVIIABI(arg0,arg1,arg2,arg3,arg4) { - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12 - case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: stack.push(arg1); // 27 - case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 12: // 191 - case 13: stack.push(arg2); // 28 - case 14: stack.push(arg0); // 42 - case 15: stack.push(stack.pop().count); // 180 1 97 - case 18: if (stack.pop() >= stack.pop()) { gt = 30; continue; } // 164 0 12 - case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 24: stack.push(stack[stack.length - 1]); // 89 - case 25: stack.push(arg2); // 28 - case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 29: // 191 - case 30: stack.push(arg1); // 27 - case 31: stack.push(arg2); // 28 - case 32: if (stack.pop() >= stack.pop()) { gt = 46; continue; } // 164 0 14 - case 35: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 38: stack.push(stack[stack.length - 1]); // 89 - case 39: stack.push(arg2); // 28 - case 40: stack.push(arg1); // 27 - case 41: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 42: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 45: // 191 - case 46: stack.push(arg4); // 21 4 - case 48: arg5 = stack.pop() // 54 5 - case 50: stack.push(arg0); // 42 - case 51: stack.push(stack.pop().offset); // 180 1 99 - case 54: stack.push(arg2); // 28 - case 55: stack.push(stack.pop() + stack.pop()); // 96 - case 56: arg6 = stack.pop() // 54 6 - case 58: stack.push(arg0); // 42 - case 59: stack.push(stack.pop().offset); // 180 1 99 - case 62: stack.push(arg1); // 27 - case 63: stack.push(stack.pop() + stack.pop()); // 96 - case 64: arg7 = stack.pop() // 54 7 - case 66: stack.push(arg0); // 42 - case 67: stack.push(stack.pop().value); // 180 1 100 - case 70: arg8 = stack.pop() // 58 8 - case 72: stack.push(arg7); // 21 7 - case 74: stack.push(arg6); // 21 6 - case 76: if (stack.pop() <= stack.pop()) { gt = 98; continue; } // 162 0 22 - case 79: stack.push(arg3); // 45 - case 80: stack.push(arg5); // 21 5 - case 82: arg5++; // 132 5 1 - case 85: stack.push(arg8); // 25 8 - case 87: stack.push(arg7); // 21 7 - case 89: arg7++; // 132 7 1 - case 92: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 93: // number conversion // 145 - case 94: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 84 - case 95: gt = 72; continue; // 167 255 233 - case 98: return; // 177 - } -} -function java_lang_String_getBytesABLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11 - case 4: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128 - case 11: // 191 - case 12: stack.push(arg1); // 43 - case 13: stack.push(arg0); // 42 - case 14: stack.push(stack.pop().value); // 180 1 100 - case 17: stack.push(arg0); // 42 - case 18: stack.push(stack.pop().offset); // 180 1 99 - case 21: stack.push(arg0); // 42 - case 22: stack.push(stack.pop().count); // 180 1 97 - case 25: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABLjava_lang_StringACAIAI(v0, v1, v2, v3)); } // 184 1 166 - case 28: return stack.pop(); // 176 - } -} -function java_lang_String_getBytesABLjava_nio_charset_Charset(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11 - case 4: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128 - case 11: // 191 - case 12: stack.push(arg1); // 43 - case 13: stack.push(arg0); // 42 - case 14: stack.push(stack.pop().value); // 180 1 100 - case 17: stack.push(arg0); // 42 - case 18: stack.push(stack.pop().offset); // 180 1 99 - case 21: stack.push(arg0); // 42 - case 22: stack.push(stack.pop().count); // 180 1 97 - case 25: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABLjava_nio_charset_CharsetACAIAI(v0, v1, v2, v3)); } // 184 1 168 - case 28: return stack.pop(); // 176 - } -} -function java_lang_String_getBytesAB(arg0) { - var arg1; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: stack.push(arg0); // 42 - case 5: stack.push(stack.pop().offset); // 180 1 99 - case 8: stack.push(arg0); // 42 - case 9: stack.push(stack.pop().count); // 180 1 97 - case 12: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABACAIAI(v0, v1, v2)); } // 184 1 164 - case 15: return stack.pop(); // 176 - } -} -function java_lang_String_equalsZLjava_lang_Object(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: // 166 - case 3: // 0 - case 4: stack.push(2); // 5 - case 5: stack.push(1); // 4 - case 6: return stack.pop(); // 172 - case 7: stack.push(arg1); // 43 - case 8: stack.push(stack.pop().$instOf_java_lang_String ? 1 : 0); // 193 0 200 - case 11: if (stack.pop() == 0) { gt = 86; continue; } // 153 0 75 - case 14: stack.push(arg1); // 43 - case 15: if(stack[stack.length - 1].$instOf_java_lang_String != 1) throw {}; // 192 0 200 - case 18: arg2 = stack.pop(); // 77 - case 19: stack.push(arg0); // 42 - case 20: stack.push(stack.pop().count); // 180 1 97 - case 23: arg3 = stack.pop(); // 62 - case 24: stack.push(arg3); // 29 - case 25: stack.push(arg2); // 44 - case 26: stack.push(stack.pop().count); // 180 1 97 - case 29: if (stack.pop() != stack.pop()) { gt = 86; continue; } // 160 0 57 - case 32: stack.push(arg0); // 42 - case 33: stack.push(stack.pop().value); // 180 1 100 - case 36: arg4 = stack.pop() // 58 4 - case 38: stack.push(arg2); // 44 - case 39: stack.push(stack.pop().value); // 180 1 100 - case 42: arg5 = stack.pop() // 58 5 - case 44: stack.push(arg0); // 42 - case 45: stack.push(stack.pop().offset); // 180 1 99 - case 48: arg6 = stack.pop() // 54 6 - case 50: stack.push(arg2); // 44 - case 51: stack.push(stack.pop().offset); // 180 1 99 - case 54: arg7 = stack.pop() // 54 7 - case 56: stack.push(arg3); // 29 - case 57: arg3 += 255; // 132 3 255 - case 60: if (stack.pop() == 0) { gt = 84; continue; } // 153 0 24 - case 63: stack.push(arg4); // 25 4 - case 65: stack.push(arg6); // 21 6 - case 67: arg6++; // 132 6 1 - case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 71: stack.push(arg5); // 25 5 - case 73: stack.push(arg7); // 21 7 - case 75: arg7++; // 132 7 1 - case 78: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 79: if (stack.pop() == stack.pop()) { gt = 56; continue; } // 159 255 233 - case 82: stack.push(0); // 3 - case 83: return stack.pop(); // 172 - case 84: stack.push(1); // 4 - case 85: return stack.pop(); // 172 - case 86: stack.push(0); // 3 - case 87: return stack.pop(); // 172 - } -} -function java_lang_String_contentEqualsZLjava_lang_StringBuffer(arg0,arg1) { - var arg2; - var arg3; - var arg4; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: stack.push(stack[stack.length - 1]); // 89 - case 2: arg2 = stack.pop(); // 77 - case 3: // 194 - case 4: stack.push(arg0); // 42 - case 5: stack.push(arg1); // 43 - case 6: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.contentEqualsZLjava_lang_CharSequence(self, v0)); } // 182 1 146 - case 9: stack.push(arg2); // 44 - case 10: // 195 - case 11: return stack.pop(); // 172 - case 12: arg3 = stack.pop(); // 78 - case 13: stack.push(arg2); // 44 - case 14: // 195 - case 15: stack.push(arg3); // 45 - case 16: // 191 - } -} -function java_lang_String_contentEqualsZLjava_lang_CharSequence(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().count); // 180 1 97 - case 4: stack.push(arg1); // 43 - case 5: { var self = stack.pop(); stack.push(self.lengthI(self)); } // 185 1 188 - case 8: // 1 - case 9: // 0 - case 10: if (stack.pop() == stack.pop()) { gt = 15; continue; } // 159 0 5 - case 13: stack.push(0); // 3 - case 14: return stack.pop(); // 172 - case 15: stack.push(arg1); // 43 - case 16: stack.push(stack.pop().$instOf_java_lang_AbstractStringBuilder ? 1 : 0); // 193 0 186 - case 19: if (stack.pop() == 0) { gt = 77; continue; } // 153 0 58 - case 22: stack.push(arg0); // 42 - case 23: stack.push(stack.pop().value); // 180 1 100 - case 26: arg2 = stack.pop(); // 77 - case 27: stack.push(arg1); // 43 - case 28: if(stack[stack.length - 1].$instOf_java_lang_AbstractStringBuilder != 1) throw {}; // 192 0 186 - case 31: { var self = stack.pop(); stack.push(self.getValueAC(self)); } // 182 1 103 - case 34: arg3 = stack.pop(); // 78 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().offset); // 180 1 99 - case 39: arg4 = stack.pop() // 54 4 - case 41: stack.push(0); // 3 - case 42: arg5 = stack.pop() // 54 5 - case 44: stack.push(arg0); // 42 - case 45: stack.push(stack.pop().count); // 180 1 97 - case 48: arg6 = stack.pop() // 54 6 - case 50: stack.push(arg6); // 21 6 - case 52: arg6 += 255; // 132 6 255 - case 55: if (stack.pop() == 0) { gt = 77; continue; } // 153 0 22 - case 58: stack.push(arg2); // 44 - case 59: stack.push(arg4); // 21 4 - case 61: arg4++; // 132 4 1 - case 64: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 65: stack.push(arg3); // 45 - case 66: stack.push(arg5); // 21 5 - case 68: arg5++; // 132 5 1 - case 71: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 72: if (stack.pop() == stack.pop()) { gt = 50; continue; } // 159 255 234 - case 75: stack.push(0); // 3 - case 76: return stack.pop(); // 172 - case 77: stack.push(arg1); // 43 - case 78: stack.push(arg0); // 42 - case 79: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.equalsZLjava_lang_Object(self, v0)); } // 182 1 131 - case 82: if (stack.pop() == 0) { gt = 87; continue; } // 153 0 5 - case 85: stack.push(1); // 4 - case 86: return stack.pop(); // 172 - case 87: stack.push(arg0); // 42 - case 88: stack.push(stack.pop().value); // 180 1 100 - case 91: arg2 = stack.pop(); // 77 - case 92: stack.push(arg0); // 42 - case 93: stack.push(stack.pop().offset); // 180 1 99 - case 96: arg3 = stack.pop(); // 62 - case 97: stack.push(0); // 3 - case 98: arg4 = stack.pop() // 54 4 - case 100: stack.push(arg0); // 42 - case 101: stack.push(stack.pop().count); // 180 1 97 - case 104: arg5 = stack.pop() // 54 5 - case 106: stack.push(arg5); // 21 5 - case 108: arg5 += 255; // 132 5 255 - case 111: if (stack.pop() == 0) { gt = 136; continue; } // 153 0 25 - case 114: stack.push(arg2); // 44 - case 115: stack.push(arg3); // 29 - case 116: arg3++; // 132 3 1 - case 119: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 120: stack.push(arg1); // 43 - case 121: stack.push(arg4); // 21 4 - case 123: arg4++; // 132 4 1 - case 126: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.charAtCI(self, v0)); } // 185 1 189 - case 129: // 2 - case 130: // 0 - case 131: if (stack.pop() == stack.pop()) { gt = 106; continue; } // 159 255 231 - case 134: stack.push(0); // 3 - case 135: return stack.pop(); // 172 - case 136: stack.push(1); // 4 - case 137: return stack.pop(); // 172 - } -} -function java_lang_String_equalsIgnoreCaseZLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: // 166 - case 3: // 0 - case 4: stack.push(4); // 7 - case 5: stack.push(1); // 4 - case 6: gt = 44; continue; // 167 0 38 - case 9: stack.push(arg1); // 43 - case 10: if (!stack.pop()) { gt = 43; continue; } // 198 0 33 - case 13: stack.push(arg1); // 43 - case 14: stack.push(stack.pop().count); // 180 1 97 - case 17: stack.push(arg0); // 42 - case 18: stack.push(stack.pop().count); // 180 1 97 - case 21: if (stack.pop() != stack.pop()) { gt = 43; continue; } // 160 0 22 - case 24: stack.push(arg0); // 42 - case 25: stack.push(1); // 4 - case 26: stack.push(0); // 3 - case 27: stack.push(arg1); // 43 - case 28: stack.push(0); // 3 - case 29: stack.push(arg0); // 42 - case 30: stack.push(stack.pop().count); // 180 1 97 - case 33: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.regionMatchesZZILjava_lang_StringII(self, v0, v1, v2, v3, v4)); } // 182 1 153 - case 36: if (stack.pop() == 0) { gt = 43; continue; } // 153 0 7 - case 39: stack.push(1); // 4 - case 40: gt = 44; continue; // 167 0 4 - case 43: stack.push(0); // 3 - case 44: return stack.pop(); // 172 - } -} -function java_lang_String_compareToILjava_lang_String(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().count); // 180 1 97 - case 4: arg2 = stack.pop(); // 61 - case 5: stack.push(arg1); // 43 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: arg3 = stack.pop(); // 62 - case 10: stack.push(arg2); // 28 - case 11: stack.push(arg3); // 29 - case 12: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Math_minIII(v0, v1)); } // 184 1 127 - case 15: arg4 = stack.pop() // 54 4 - case 17: stack.push(arg0); // 42 - case 18: stack.push(stack.pop().value); // 180 1 100 - case 21: arg5 = stack.pop() // 58 5 - case 23: stack.push(arg1); // 43 - case 24: stack.push(stack.pop().value); // 180 1 100 - case 27: arg6 = stack.pop() // 58 6 - case 29: stack.push(arg0); // 42 - case 30: stack.push(stack.pop().offset); // 180 1 99 - case 33: arg7 = stack.pop() // 54 7 - case 35: stack.push(arg1); // 43 - case 36: stack.push(stack.pop().offset); // 180 1 99 - case 39: arg8 = stack.pop() // 54 8 - case 41: stack.push(arg7); // 21 7 - case 43: stack.push(arg8); // 21 8 - case 45: if (stack.pop() != stack.pop()) { gt = 102; continue; } // 160 0 57 - case 48: stack.push(arg7); // 21 7 - case 50: arg9 = stack.pop() // 54 9 - case 52: stack.push(arg4); // 21 4 - case 54: stack.push(arg7); // 21 7 - case 56: stack.push(stack.pop() + stack.pop()); // 96 - case 57: arg10 = stack.pop() // 54 10 - case 59: stack.push(arg9); // 21 9 - case 61: stack.push(arg10); // 21 10 - case 63: if (stack.pop() <= stack.pop()) { gt = 99; continue; } // 162 0 36 - case 66: stack.push(arg5); // 25 5 - case 68: stack.push(arg9); // 21 9 - case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 71: arg11 = stack.pop() // 54 11 - case 73: stack.push(arg6); // 25 6 - case 75: stack.push(arg9); // 21 9 - case 77: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 78: arg12 = stack.pop() // 54 12 - case 80: stack.push(arg11); // 21 11 - case 82: stack.push(arg12); // 21 12 - case 84: if (stack.pop() == stack.pop()) { gt = 93; continue; } // 159 0 9 - case 87: stack.push(arg11); // 21 11 - case 89: stack.push(arg12); // 21 12 - case 91: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 92: return stack.pop(); // 172 - case 93: arg9++; // 132 9 1 - case 96: gt = 59; continue; // 167 255 219 - case 99: gt = 146; continue; // 167 0 47 - case 102: stack.push(arg4); // 21 4 - case 104: arg4 += 255; // 132 4 255 - case 107: if (stack.pop() == 0) { gt = 146; continue; } // 153 0 39 - case 110: stack.push(arg5); // 25 5 - case 112: stack.push(arg7); // 21 7 - case 114: arg7++; // 132 7 1 - case 117: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 118: arg9 = stack.pop() // 54 9 - case 120: stack.push(arg6); // 25 6 - case 122: stack.push(arg8); // 21 8 - case 124: arg8++; // 132 8 1 - case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 128: arg10 = stack.pop() // 54 10 - case 130: stack.push(arg9); // 21 9 - case 132: stack.push(arg10); // 21 10 - case 134: if (stack.pop() == stack.pop()) { gt = 143; continue; } // 159 0 9 - case 137: stack.push(arg9); // 21 9 - case 139: stack.push(arg10); // 21 10 - case 141: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 142: return stack.pop(); // 172 - case 143: gt = 102; continue; // 167 255 215 - case 146: stack.push(arg2); // 28 - case 147: stack.push(arg3); // 29 - case 148: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 149: return stack.pop(); // 172 - } -} -function java_lang_String_compareToIgnoreCaseILjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(java_lang_String_CASE_INSENSITIVE_ORDER); // 178 1 102 - case 3: stack.push(arg0); // 42 - case 4: stack.push(arg1); // 43 - case 5: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.compareILjava_lang_ObjectLjava_lang_Object(self, v0, v1)); } // 185 1 190 - case 8: stack.push(0); // 3 - case 9: // 0 - case 10: return stack.pop(); // 172 - } -} -function java_lang_String_regionMatchesZILjava_lang_StringII(arg0,arg1,arg2,arg3,arg4) { - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: arg5 = stack.pop() // 58 5 - case 6: stack.push(arg0); // 42 - case 7: stack.push(stack.pop().offset); // 180 1 99 - case 10: stack.push(arg1); // 27 - case 11: stack.push(stack.pop() + stack.pop()); // 96 - case 12: arg6 = stack.pop() // 54 6 - case 14: stack.push(arg2); // 44 - case 15: stack.push(stack.pop().value); // 180 1 100 - case 18: arg7 = stack.pop() // 58 7 - case 20: stack.push(arg2); // 44 - case 21: stack.push(stack.pop().offset); // 180 1 99 - case 24: stack.push(arg3); // 29 - case 25: stack.push(stack.pop() + stack.pop()); // 96 - case 26: arg8 = stack.pop() // 54 8 - case 28: stack.push(arg3); // 29 - case 29: if (stack.pop() < 0) { gt = 66; continue; } // 155 0 37 - case 32: stack.push(arg1); // 27 - case 33: if (stack.pop() < 0) { gt = 66; continue; } // 155 0 33 - case 36: stack.push(arg1); // 27 - case 37: // number conversion // 133 - case 38: stack.push(arg0); // 42 - case 39: stack.push(stack.pop().count); // 180 1 97 - case 42: // number conversion // 133 - case 43: stack.push(arg4); // 21 4 - case 45: // number conversion // 133 - case 46: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101 - case 47: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148 - case 48: if (stack.pop() > 0) { gt = 66; continue; } // 157 0 18 - case 51: stack.push(arg3); // 29 - case 52: // number conversion // 133 - case 53: stack.push(arg2); // 44 - case 54: stack.push(stack.pop().count); // 180 1 97 - case 57: // number conversion // 133 - case 58: stack.push(arg4); // 21 4 - case 60: // number conversion // 133 - case 61: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101 - case 62: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148 - case 63: if (stack.pop() <= 0) { gt = 68; continue; } // 158 0 5 - case 66: stack.push(0); // 3 - case 67: return stack.pop(); // 172 - case 68: stack.push(arg4); // 21 4 - case 70: arg4 += 255; // 132 4 255 - case 73: if (stack.pop() <= 0) { gt = 97; continue; } // 158 0 24 - case 76: stack.push(arg5); // 25 5 - case 78: stack.push(arg6); // 21 6 - case 80: arg6++; // 132 6 1 - case 83: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 84: stack.push(arg7); // 25 7 - case 86: stack.push(arg8); // 21 8 - case 88: arg8++; // 132 8 1 - case 91: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 92: if (stack.pop() == stack.pop()) { gt = 68; continue; } // 159 255 232 - case 95: stack.push(0); // 3 - case 96: return stack.pop(); // 172 - case 97: stack.push(1); // 4 - case 98: return stack.pop(); // 172 - } -} -function java_lang_String_regionMatchesZZILjava_lang_StringII(arg0,arg1,arg2,arg3,arg4,arg5) { - var arg6; - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; - var arg14; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: arg6 = stack.pop() // 58 6 - case 6: stack.push(arg0); // 42 - case 7: stack.push(stack.pop().offset); // 180 1 99 - case 10: stack.push(arg2); // 28 - case 11: stack.push(stack.pop() + stack.pop()); // 96 - case 12: arg7 = stack.pop() // 54 7 - case 14: stack.push(arg3); // 45 - case 15: stack.push(stack.pop().value); // 180 1 100 - case 18: arg8 = stack.pop() // 58 8 - case 20: stack.push(arg3); // 45 - case 21: stack.push(stack.pop().offset); // 180 1 99 - case 24: stack.push(arg4); // 21 4 - case 26: stack.push(stack.pop() + stack.pop()); // 96 - case 27: arg9 = stack.pop() // 54 9 - case 29: stack.push(arg4); // 21 4 - case 31: if (stack.pop() < 0) { gt = 69; continue; } // 155 0 38 - case 34: stack.push(arg2); // 28 - case 35: if (stack.pop() < 0) { gt = 69; continue; } // 155 0 34 - case 38: stack.push(arg2); // 28 - case 39: // number conversion // 133 - case 40: stack.push(arg0); // 42 - case 41: stack.push(stack.pop().count); // 180 1 97 - case 44: // number conversion // 133 - case 45: stack.push(arg5); // 21 5 - case 47: // number conversion // 133 - case 48: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101 - case 49: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148 - case 50: if (stack.pop() > 0) { gt = 69; continue; } // 157 0 19 - case 53: stack.push(arg4); // 21 4 - case 55: // number conversion // 133 - case 56: stack.push(arg3); // 45 - case 57: stack.push(stack.pop().count); // 180 1 97 - case 60: // number conversion // 133 - case 61: stack.push(arg5); // 21 5 - case 63: // number conversion // 133 - case 64: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101 - case 65: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148 - case 66: if (stack.pop() <= 0) { gt = 71; continue; } // 158 0 5 - case 69: stack.push(0); // 3 - case 70: return stack.pop(); // 172 - case 71: stack.push(arg5); // 21 5 - case 73: arg5 += 255; // 132 5 255 - case 76: if (stack.pop() <= 0) { gt = 155; continue; } // 158 0 79 - case 79: stack.push(arg6); // 25 6 - case 81: stack.push(arg7); // 21 7 - case 83: arg7++; // 132 7 1 - case 86: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 87: arg10 = stack.pop() // 54 10 - case 89: stack.push(arg8); // 25 8 - case 91: stack.push(arg9); // 21 9 - case 93: arg9++; // 132 9 1 - case 96: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 97: arg11 = stack.pop() // 54 11 - case 99: stack.push(arg10); // 21 10 - case 101: stack.push(arg11); // 21 11 - case 103: if (stack.pop() != stack.pop()) { gt = 109; continue; } // 160 0 6 - case 106: gt = 71; continue; // 167 255 221 - case 109: stack.push(arg1); // 27 - case 110: if (stack.pop() == 0) { gt = 153; continue; } // 153 0 43 - case 113: stack.push(arg10); // 21 10 - case 115: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCC(v0)); } // 184 1 105 - case 118: arg12 = stack.pop() // 54 12 - case 120: stack.push(arg11); // 21 11 - case 122: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCC(v0)); } // 184 1 105 - case 125: arg13 = stack.pop() // 54 13 - case 127: stack.push(arg12); // 21 12 - case 129: stack.push(arg13); // 21 13 - case 131: if (stack.pop() != stack.pop()) { gt = 137; continue; } // 160 0 6 - case 134: gt = 71; continue; // 167 255 193 - case 137: stack.push(arg12); // 21 12 - case 139: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104 - case 142: stack.push(arg13); // 21 13 - case 144: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104 - case 147: if (stack.pop() != stack.pop()) { gt = 153; continue; } // 160 0 6 - case 150: gt = 71; continue; // 167 255 177 - case 153: stack.push(0); // 3 - case 154: return stack.pop(); // 172 - case 155: stack.push(1); // 4 - case 156: return stack.pop(); // 172 - } -} -function java_lang_String_startsWithZLjava_lang_StringI(arg0,arg1,arg2) { - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: arg3 = stack.pop(); // 78 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().offset); // 180 1 99 - case 9: stack.push(arg2); // 28 - case 10: stack.push(stack.pop() + stack.pop()); // 96 - case 11: arg4 = stack.pop() // 54 4 - case 13: stack.push(arg1); // 43 - case 14: stack.push(stack.pop().value); // 180 1 100 - case 17: arg5 = stack.pop() // 58 5 - case 19: stack.push(arg1); // 43 - case 20: stack.push(stack.pop().offset); // 180 1 99 - case 23: arg6 = stack.pop() // 54 6 - case 25: stack.push(arg1); // 43 - case 26: stack.push(stack.pop().count); // 180 1 97 - case 29: arg7 = stack.pop() // 54 7 - case 31: stack.push(arg2); // 28 - case 32: if (stack.pop() < 0) { gt = 46; continue; } // 155 0 14 - case 35: stack.push(arg2); // 28 - case 36: stack.push(arg0); // 42 - case 37: stack.push(stack.pop().count); // 180 1 97 - case 40: stack.push(arg7); // 21 7 - case 42: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 43: if (stack.pop() >= stack.pop()) { gt = 48; continue; } // 164 0 5 - case 46: stack.push(0); // 3 - case 47: return stack.pop(); // 172 - case 48: arg7 += 255; // 132 7 255 - case 51: stack.push(arg7); // 21 7 - case 53: if (stack.pop() < 0) { gt = 76; continue; } // 155 0 23 - case 56: stack.push(arg3); // 45 - case 57: stack.push(arg4); // 21 4 - case 59: arg4++; // 132 4 1 - case 62: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 63: stack.push(arg5); // 25 5 - case 65: stack.push(arg6); // 21 6 - case 67: arg6++; // 132 6 1 - case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 71: if (stack.pop() == stack.pop()) { gt = 48; continue; } // 159 255 233 - case 74: stack.push(0); // 3 - case 75: return stack.pop(); // 172 - case 76: stack.push(1); // 4 - case 77: return stack.pop(); // 172 - } -} -function java_lang_String_startsWithZLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(0); // 3 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.startsWithZLjava_lang_StringI(self, v0, v1)); } // 182 1 152 - case 6: return stack.pop(); // 172 - } -} -function java_lang_String_endsWithZLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().count); // 180 1 97 - case 6: stack.push(arg1); // 43 - case 7: stack.push(stack.pop().count); // 180 1 97 - case 10: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 11: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.startsWithZLjava_lang_StringI(self, v0, v1)); } // 182 1 152 - case 14: return stack.pop(); // 172 - } -} -function java_lang_String_hashCodeI(arg0) { - var arg1; - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().hash); // 180 1 98 - case 4: arg1 = stack.pop(); // 60 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: arg2 = stack.pop(); // 61 - case 10: stack.push(arg1); // 27 - case 11: if (stack.pop() != 0) { gt = 62; continue; } // 154 0 51 - case 14: stack.push(arg2); // 28 - case 15: if (stack.pop() <= 0) { gt = 62; continue; } // 158 0 47 - case 18: stack.push(arg0); // 42 - case 19: stack.push(stack.pop().offset); // 180 1 99 - case 22: arg3 = stack.pop(); // 62 - case 23: stack.push(arg0); // 42 - case 24: stack.push(stack.pop().value); // 180 1 100 - case 27: arg4 = stack.pop() // 58 4 - case 29: stack.push(0); // 3 - case 30: arg5 = stack.pop() // 54 5 - case 32: stack.push(arg5); // 21 5 - case 34: stack.push(arg2); // 28 - case 35: if (stack.pop() <= stack.pop()) { gt = 57; continue; } // 162 0 22 - case 38: stack.push(31); // 16 31 - case 40: stack.push(arg1); // 27 - case 41: stack.push(stack.pop() * stack.pop()); // 104 - case 42: stack.push(arg4); // 25 4 - case 44: stack.push(arg3); // 29 - case 45: arg3++; // 132 3 1 - case 48: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 49: stack.push(stack.pop() + stack.pop()); // 96 - case 50: arg1 = stack.pop(); // 60 - case 51: arg5++; // 132 5 1 - case 54: gt = 32; continue; // 167 255 234 - case 57: stack.push(arg0); // 42 - case 58: stack.push(arg1); // 27 - case 59: { var v = stack.pop(); stack.pop().hash = v; } // 181 1 98 - case 62: stack.push(arg1); // 27 - case 63: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfII(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 27 - case 2: stack.push(0); // 3 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfIII(self, v0, v1)); } // 182 1 135 - case 6: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfIII(arg0,arg1,arg2) { - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().offset); // 180 1 99 - case 4: stack.push(arg0); // 42 - case 5: stack.push(stack.pop().count); // 180 1 97 - case 8: stack.push(stack.pop() + stack.pop()); // 96 - case 9: arg3 = stack.pop(); // 62 - case 10: stack.push(arg0); // 42 - case 11: stack.push(stack.pop().value); // 180 1 100 - case 14: arg4 = stack.pop() // 58 4 - case 16: stack.push(arg2); // 28 - case 17: if (stack.pop() >= 0) { gt = 25; continue; } // 156 0 8 - case 20: stack.push(0); // 3 - case 21: arg2 = stack.pop(); // 61 - case 22: gt = 35; continue; // 167 0 13 - case 25: stack.push(arg2); // 28 - case 26: stack.push(arg0); // 42 - case 27: stack.push(stack.pop().count); // 180 1 97 - case 30: if (stack.pop() > stack.pop()) { gt = 35; continue; } // 161 0 5 - case 33: // 2 - case 34: return stack.pop(); // 172 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().offset); // 180 1 99 - case 39: stack.push(arg2); // 28 - case 40: stack.push(stack.pop() + stack.pop()); // 96 - case 41: arg5 = stack.pop() // 54 5 - case 43: stack.push(arg1); // 27 - case 44: stack.push(65536); // 18 3 - case 46: if (stack.pop() <= stack.pop()) { gt = 80; continue; } // 162 0 34 - case 49: stack.push(arg5); // 21 5 - case 51: stack.push(arg3); // 29 - case 52: if (stack.pop() <= stack.pop()) { gt = 78; continue; } // 162 0 26 - case 55: stack.push(arg4); // 25 4 - case 57: stack.push(arg5); // 21 5 - case 59: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 60: stack.push(arg1); // 27 - case 61: if (stack.pop() != stack.pop()) { gt = 72; continue; } // 160 0 11 - case 64: stack.push(arg5); // 21 5 - case 66: stack.push(arg0); // 42 - case 67: stack.push(stack.pop().offset); // 180 1 99 - case 70: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 71: return stack.pop(); // 172 - case 72: arg5++; // 132 5 1 - case 75: gt = 49; continue; // 167 255 230 - case 78: // 2 - case 79: return stack.pop(); // 172 - case 80: stack.push(arg1); // 27 - case 81: stack.push(1114111); // 18 4 - case 83: if (stack.pop() < stack.pop()) { gt = 149; continue; } // 163 0 66 - case 86: stack.push(arg1); // 27 - case 87: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109 - case 90: arg6 = stack.pop() // 58 6 - case 92: stack.push(arg5); // 21 5 - case 94: stack.push(arg3); // 29 - case 95: if (stack.pop() <= stack.pop()) { gt = 149; continue; } // 162 0 54 - case 98: stack.push(arg4); // 25 4 - case 100: stack.push(arg5); // 21 5 - case 102: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 103: stack.push(arg6); // 25 6 - case 105: stack.push(0); // 3 - case 106: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 107: if (stack.pop() != stack.pop()) { gt = 143; continue; } // 160 0 36 - case 110: stack.push(arg5); // 21 5 - case 112: stack.push(1); // 4 - case 113: stack.push(stack.pop() + stack.pop()); // 96 - case 114: stack.push(arg3); // 29 - case 115: if (stack.pop() != stack.pop()) { gt = 121; continue; } // 160 0 6 - case 118: gt = 149; continue; // 167 0 31 - case 121: stack.push(arg4); // 25 4 - case 123: stack.push(arg5); // 21 5 - case 125: stack.push(1); // 4 - case 126: stack.push(stack.pop() + stack.pop()); // 96 - case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 128: stack.push(arg6); // 25 6 - case 130: stack.push(1); // 4 - case 131: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 132: if (stack.pop() != stack.pop()) { gt = 143; continue; } // 160 0 11 - case 135: stack.push(arg5); // 21 5 - case 137: stack.push(arg0); // 42 - case 138: stack.push(stack.pop().offset); // 180 1 99 - case 141: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 142: return stack.pop(); // 172 - case 143: arg5++; // 132 5 1 - case 146: gt = 92; continue; // 167 255 202 - case 149: // 2 - case 150: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfII(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 27 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().count); // 180 1 97 - case 6: stack.push(1); // 4 - case 7: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 8: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.lastIndexOfIII(self, v0, v1)); } // 182 1 136 - case 11: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfIII(arg0,arg1,arg2) { - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().offset); // 180 1 99 - case 4: arg3 = stack.pop(); // 62 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().value); // 180 1 100 - case 9: arg4 = stack.pop() // 58 4 - case 11: stack.push(arg0); // 42 - case 12: stack.push(stack.pop().offset); // 180 1 99 - case 15: stack.push(arg2); // 28 - case 16: stack.push(arg0); // 42 - case 17: stack.push(stack.pop().count); // 180 1 97 - case 20: if (stack.pop() > stack.pop()) { gt = 32; continue; } // 161 0 12 - case 23: stack.push(arg0); // 42 - case 24: stack.push(stack.pop().count); // 180 1 97 - case 27: stack.push(1); // 4 - case 28: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 29: gt = 33; continue; // 167 0 4 - case 32: stack.push(arg2); // 28 - case 33: stack.push(stack.pop() + stack.pop()); // 96 - case 34: arg5 = stack.pop() // 54 5 - case 36: stack.push(arg1); // 27 - case 37: stack.push(65536); // 18 3 - case 39: if (stack.pop() <= stack.pop()) { gt = 73; continue; } // 162 0 34 - case 42: stack.push(arg5); // 21 5 - case 44: stack.push(arg3); // 29 - case 45: if (stack.pop() > stack.pop()) { gt = 71; continue; } // 161 0 26 - case 48: stack.push(arg4); // 25 4 - case 50: stack.push(arg5); // 21 5 - case 52: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 53: stack.push(arg1); // 27 - case 54: if (stack.pop() != stack.pop()) { gt = 65; continue; } // 160 0 11 - case 57: stack.push(arg5); // 21 5 - case 59: stack.push(arg0); // 42 - case 60: stack.push(stack.pop().offset); // 180 1 99 - case 63: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 64: return stack.pop(); // 172 - case 65: arg5 += 255; // 132 5 255 - case 68: gt = 42; continue; // 167 255 230 - case 71: // 2 - case 72: return stack.pop(); // 172 - case 73: stack.push(arg0); // 42 - case 74: stack.push(stack.pop().offset); // 180 1 99 - case 77: stack.push(arg0); // 42 - case 78: stack.push(stack.pop().count); // 180 1 97 - case 81: stack.push(stack.pop() + stack.pop()); // 96 - case 82: arg6 = stack.pop() // 54 6 - case 84: stack.push(arg1); // 27 - case 85: stack.push(1114111); // 18 4 - case 87: if (stack.pop() < stack.pop()) { gt = 154; continue; } // 163 0 67 - case 90: stack.push(arg1); // 27 - case 91: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109 - case 94: arg7 = stack.pop() // 58 7 - case 96: stack.push(arg5); // 21 5 - case 98: stack.push(arg3); // 29 - case 99: if (stack.pop() > stack.pop()) { gt = 154; continue; } // 161 0 55 - case 102: stack.push(arg4); // 25 4 - case 104: stack.push(arg5); // 21 5 - case 106: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 107: stack.push(arg7); // 25 7 - case 109: stack.push(0); // 3 - case 110: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 111: if (stack.pop() != stack.pop()) { gt = 148; continue; } // 160 0 37 - case 114: stack.push(arg5); // 21 5 - case 116: stack.push(1); // 4 - case 117: stack.push(stack.pop() + stack.pop()); // 96 - case 118: stack.push(arg6); // 21 6 - case 120: if (stack.pop() != stack.pop()) { gt = 126; continue; } // 160 0 6 - case 123: gt = 154; continue; // 167 0 31 - case 126: stack.push(arg4); // 25 4 - case 128: stack.push(arg5); // 21 5 - case 130: stack.push(1); // 4 - case 131: stack.push(stack.pop() + stack.pop()); // 96 - case 132: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 133: stack.push(arg7); // 25 7 - case 135: stack.push(1); // 4 - case 136: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 137: if (stack.pop() != stack.pop()) { gt = 148; continue; } // 160 0 11 - case 140: stack.push(arg5); // 21 5 - case 142: stack.push(arg0); // 42 - case 143: stack.push(stack.pop().offset); // 180 1 99 - case 146: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 147: return stack.pop(); // 172 - case 148: arg5 += 255; // 132 5 255 - case 151: gt = 96; continue; // 167 255 201 - case 154: // 2 - case 155: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfILjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(0); // 3 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfILjava_lang_StringI(self, v0, v1)); } // 182 1 150 - case 6: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfILjava_lang_StringI(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(7); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: stack.push(arg0); // 42 - case 5: stack.push(stack.pop().offset); // 180 1 99 - case 8: stack.push(arg0); // 42 - case 9: stack.push(stack.pop().count); // 180 1 97 - case 12: stack.push(arg1); // 43 - case 13: stack.push(stack.pop().value); // 180 1 100 - case 16: stack.push(arg1); // 43 - case 17: stack.push(stack.pop().offset); // 180 1 99 - case 20: stack.push(arg1); // 43 - case 21: stack.push(stack.pop().count); // 180 1 97 - case 24: stack.push(arg2); // 28 - case 25: { var v6 = stack.pop(); var v5 = stack.pop(); var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_indexOfAIACAIAIACAIAIAI(v0, v1, v2, v3, v4, v5, v6)); } // 184 1 144 - case 28: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfIACIIACIII(arg0,arg1,arg2,arg3,arg4,arg5,arg6) { - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg6); // 21 6 - case 2: stack.push(arg2); // 28 - case 3: if (stack.pop() > stack.pop()) { gt = 17; continue; } // 161 0 14 - case 6: stack.push(arg5); // 21 5 - case 8: if (stack.pop() != 0) { gt = 15; continue; } // 154 0 7 - case 11: stack.push(arg2); // 28 - case 12: gt = 16; continue; // 167 0 4 - case 15: // 2 - case 16: return stack.pop(); // 172 - case 17: stack.push(arg6); // 21 6 - case 19: if (stack.pop() >= 0) { gt = 25; continue; } // 156 0 6 - case 22: stack.push(0); // 3 - case 23: arg6 = stack.pop() // 54 6 - case 25: stack.push(arg5); // 21 5 - case 27: if (stack.pop() != 0) { gt = 33; continue; } // 154 0 6 - case 30: stack.push(arg6); // 21 6 - case 32: return stack.pop(); // 172 - case 33: stack.push(arg3); // 45 - case 34: stack.push(arg4); // 21 4 - case 36: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 37: arg7 = stack.pop() // 54 7 - case 39: stack.push(arg1); // 27 - case 40: stack.push(arg2); // 28 - case 41: stack.push(arg5); // 21 5 - case 43: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 44: stack.push(stack.pop() + stack.pop()); // 96 - case 45: arg8 = stack.pop() // 54 8 - case 47: stack.push(arg1); // 27 - case 48: stack.push(arg6); // 21 6 - case 50: stack.push(stack.pop() + stack.pop()); // 96 - case 51: arg9 = stack.pop() // 54 9 - case 53: stack.push(arg9); // 21 9 - case 55: stack.push(arg8); // 21 8 - case 57: if (stack.pop() < stack.pop()) { gt = 164; continue; } // 163 0 107 - case 60: stack.push(arg0); // 42 - case 61: stack.push(arg9); // 21 9 - case 63: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 64: stack.push(arg7); // 21 7 - case 66: if (stack.pop() == stack.pop()) { gt = 91; continue; } // 159 0 25 - case 69: arg9++; // 132 9 1 - case 72: stack.push(arg9); // 21 9 - case 74: stack.push(arg8); // 21 8 - case 76: if (stack.pop() < stack.pop()) { gt = 91; continue; } // 163 0 15 - case 79: stack.push(arg0); // 42 - case 80: stack.push(arg9); // 21 9 - case 82: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 83: stack.push(arg7); // 21 7 - case 85: if (stack.pop() == stack.pop()) { gt = 91; continue; } // 159 0 6 - case 88: gt = 69; continue; // 167 255 237 - case 91: stack.push(arg9); // 21 9 - case 93: stack.push(arg8); // 21 8 - case 95: if (stack.pop() < stack.pop()) { gt = 158; continue; } // 163 0 63 - case 98: stack.push(arg9); // 21 9 - case 100: stack.push(1); // 4 - case 101: stack.push(stack.pop() + stack.pop()); // 96 - case 102: arg10 = stack.pop() // 54 10 - case 104: stack.push(arg10); // 21 10 - case 106: stack.push(arg5); // 21 5 - case 108: stack.push(stack.pop() + stack.pop()); // 96 - case 109: stack.push(1); // 4 - case 110: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 111: arg11 = stack.pop() // 54 11 - case 113: stack.push(arg4); // 21 4 - case 115: stack.push(1); // 4 - case 116: stack.push(stack.pop() + stack.pop()); // 96 - case 117: arg12 = stack.pop() // 54 12 - case 119: stack.push(arg10); // 21 10 - case 121: stack.push(arg11); // 21 11 - case 123: if (stack.pop() <= stack.pop()) { gt = 146; continue; } // 162 0 23 - case 126: stack.push(arg0); // 42 - case 127: stack.push(arg10); // 21 10 - case 129: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 130: stack.push(arg3); // 45 - case 131: stack.push(arg12); // 21 12 - case 133: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 134: if (stack.pop() != stack.pop()) { gt = 146; continue; } // 160 0 12 - case 137: arg10++; // 132 10 1 - case 140: arg12++; // 132 12 1 - case 143: gt = 119; continue; // 167 255 232 - case 146: stack.push(arg10); // 21 10 - case 148: stack.push(arg11); // 21 11 - case 150: if (stack.pop() != stack.pop()) { gt = 158; continue; } // 160 0 8 - case 153: stack.push(arg9); // 21 9 - case 155: stack.push(arg1); // 27 - case 156: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 157: return stack.pop(); // 172 - case 158: arg9++; // 132 9 1 - case 161: gt = 53; continue; // 167 255 148 - case 164: // 2 - case 165: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfILjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().count); // 180 1 97 - case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.lastIndexOfILjava_lang_StringI(self, v0, v1)); } // 182 1 151 - case 9: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfILjava_lang_StringI(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(7); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: stack.push(arg0); // 42 - case 5: stack.push(stack.pop().offset); // 180 1 99 - case 8: stack.push(arg0); // 42 - case 9: stack.push(stack.pop().count); // 180 1 97 - case 12: stack.push(arg1); // 43 - case 13: stack.push(stack.pop().value); // 180 1 100 - case 16: stack.push(arg1); // 43 - case 17: stack.push(stack.pop().offset); // 180 1 99 - case 20: stack.push(arg1); // 43 - case 21: stack.push(stack.pop().count); // 180 1 97 - case 24: stack.push(arg2); // 28 - case 25: { var v6 = stack.pop(); var v5 = stack.pop(); var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_lastIndexOfAIACAIAIACAIAIAI(v0, v1, v2, v3, v4, v5, v6)); } // 184 1 145 - case 28: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfIACIIACIII(arg0,arg1,arg2,arg3,arg4,arg5,arg6) { - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; - var arg14; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg2); // 28 - case 1: stack.push(arg5); // 21 5 - case 3: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 4: arg7 = stack.pop() // 54 7 - case 6: stack.push(arg6); // 21 6 - case 8: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 5 - case 11: // 2 - case 12: return stack.pop(); // 172 - case 13: stack.push(arg6); // 21 6 - case 15: stack.push(arg7); // 21 7 - case 17: if (stack.pop() >= stack.pop()) { gt = 24; continue; } // 164 0 7 - case 20: stack.push(arg7); // 21 7 - case 22: arg6 = stack.pop() // 54 6 - case 24: stack.push(arg5); // 21 5 - case 26: if (stack.pop() != 0) { gt = 32; continue; } // 154 0 6 - case 29: stack.push(arg6); // 21 6 - case 31: return stack.pop(); // 172 - case 32: stack.push(arg4); // 21 4 - case 34: stack.push(arg5); // 21 5 - case 36: stack.push(stack.pop() + stack.pop()); // 96 - case 37: stack.push(1); // 4 - case 38: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 39: arg8 = stack.pop() // 54 8 - case 41: stack.push(arg3); // 45 - case 42: stack.push(arg8); // 21 8 - case 44: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 45: arg9 = stack.pop() // 54 9 - case 47: stack.push(arg1); // 27 - case 48: stack.push(arg5); // 21 5 - case 50: stack.push(stack.pop() + stack.pop()); // 96 - case 51: stack.push(1); // 4 - case 52: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 53: arg10 = stack.pop() // 54 10 - case 55: stack.push(arg10); // 21 10 - case 57: stack.push(arg6); // 21 6 - case 59: stack.push(stack.pop() + stack.pop()); // 96 - case 60: arg11 = stack.pop() // 54 11 - case 62: stack.push(arg11); // 21 11 - case 64: stack.push(arg10); // 21 10 - case 66: if (stack.pop() > stack.pop()) { gt = 84; continue; } // 161 0 18 - case 69: stack.push(arg0); // 42 - case 70: stack.push(arg11); // 21 11 - case 72: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 73: stack.push(arg9); // 21 9 - case 75: if (stack.pop() == stack.pop()) { gt = 84; continue; } // 159 0 9 - case 78: arg11 += 255; // 132 11 255 - case 81: gt = 62; continue; // 167 255 237 - case 84: stack.push(arg11); // 21 11 - case 86: stack.push(arg10); // 21 10 - case 88: if (stack.pop() <= stack.pop()) { gt = 93; continue; } // 162 0 5 - case 91: // 2 - case 92: return stack.pop(); // 172 - case 93: stack.push(arg11); // 21 11 - case 95: stack.push(1); // 4 - case 96: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 97: arg12 = stack.pop() // 54 12 - case 99: stack.push(arg12); // 21 12 - case 101: stack.push(arg5); // 21 5 - case 103: stack.push(1); // 4 - case 104: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 105: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 106: arg13 = stack.pop() // 54 13 - case 108: stack.push(arg8); // 21 8 - case 110: stack.push(1); // 4 - case 111: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 112: arg14 = stack.pop() // 54 14 - case 114: stack.push(arg12); // 21 12 - case 116: stack.push(arg13); // 21 13 - case 118: if (stack.pop() >= stack.pop()) { gt = 144; continue; } // 164 0 26 - case 121: stack.push(arg0); // 42 - case 122: stack.push(arg12); // 21 12 - case 124: arg12 += 255; // 132 12 255 - case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 128: stack.push(arg3); // 45 - case 129: stack.push(arg14); // 21 14 - case 131: arg14 += 255; // 132 14 255 - case 134: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 135: if (stack.pop() == stack.pop()) { gt = 114; continue; } // 159 255 235 - case 138: arg11 += 255; // 132 11 255 - case 141: gt = 62; continue; // 167 255 177 - case 144: stack.push(arg13); // 21 13 - case 146: stack.push(arg1); // 27 - case 147: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 148: stack.push(1); // 4 - case 149: stack.push(stack.pop() + stack.pop()); // 96 - case 150: return stack.pop(); // 172 - } -} -function java_lang_String_substringLjava_lang_StringI(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 27 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().count); // 180 1 97 - case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147 - case 9: return stack.pop(); // 176 - } -} -function java_lang_String_substringLjava_lang_StringII(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12 - case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: stack.push(arg1); // 27 - case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 12: // 191 - case 13: stack.push(arg2); // 28 - case 14: stack.push(arg0); // 42 - case 15: stack.push(stack.pop().count); // 180 1 97 - case 18: if (stack.pop() >= stack.pop()) { gt = 30; continue; } // 164 0 12 - case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 24: stack.push(stack[stack.length - 1]); // 89 - case 25: stack.push(arg2); // 28 - case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 29: // 191 - case 30: stack.push(arg1); // 27 - case 31: stack.push(arg2); // 28 - case 32: if (stack.pop() >= stack.pop()) { gt = 46; continue; } // 164 0 14 - case 35: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 38: stack.push(stack[stack.length - 1]); // 89 - case 39: stack.push(arg2); // 28 - case 40: stack.push(arg1); // 27 - case 41: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 42: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 45: // 191 - case 46: stack.push(arg1); // 27 - case 47: if (stack.pop() != 0) { gt = 62; continue; } // 154 0 15 - case 50: stack.push(arg2); // 28 - case 51: stack.push(arg0); // 42 - case 52: stack.push(stack.pop().count); // 180 1 97 - case 55: if (stack.pop() != stack.pop()) { gt = 62; continue; } // 160 0 7 - case 58: stack.push(arg0); // 42 - case 59: gt = 82; continue; // 167 0 23 - case 62: stack.push(new java_lang_String); // 187 0 200 - case 65: stack.push(stack[stack.length - 1]); // 89 - case 66: stack.push(arg0); // 42 - case 67: stack.push(stack.pop().offset); // 180 1 99 - case 70: stack.push(arg1); // 27 - case 71: stack.push(stack.pop() + stack.pop()); // 96 - case 72: stack.push(arg2); // 28 - case 73: stack.push(arg1); // 27 - case 74: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 75: stack.push(arg0); // 42 - case 76: stack.push(stack.pop().value); // 180 1 100 - case 79: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 82: return stack.pop(); // 176 - } -} -function java_lang_String_subSequenceLjava_lang_CharSequenceII(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 27 - case 2: stack.push(arg2); // 28 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147 - case 6: return stack.pop(); // 176 - } -} -function java_lang_String_concatLjava_lang_StringLjava_lang_String(arg0,arg1) { - var arg2; - var arg3; - var arg4; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var self = stack.pop(); stack.push(self.lengthI(self)); } // 182 1 133 - case 4: arg2 = stack.pop(); // 61 - case 5: stack.push(arg2); // 28 - case 6: if (stack.pop() != 0) { gt = 11; continue; } // 154 0 5 - case 9: stack.push(arg0); // 42 - case 10: return stack.pop(); // 176 - case 11: stack.push(arg0); // 42 - case 12: stack.push(stack.pop().count); // 180 1 97 - case 15: stack.push(arg2); // 28 - case 16: stack.push(stack.pop() + stack.pop()); // 96 - case 17: stack.push(new Array(stack.pop())); // 188 5 - case 19: arg3 = stack.pop(); // 78 - case 20: stack.push(arg0); // 42 - case 21: stack.push(0); // 3 - case 22: stack.push(arg0); // 42 - case 23: stack.push(stack.pop().count); // 180 1 97 - case 26: stack.push(arg3); // 45 - case 27: stack.push(0); // 3 - case 28: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138 - case 31: stack.push(arg1); // 43 - case 32: stack.push(0); // 3 - case 33: stack.push(arg2); // 28 - case 34: stack.push(arg3); // 45 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().count); // 180 1 97 - case 39: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138 - case 42: stack.push(new java_lang_String); // 187 0 200 - case 45: stack.push(stack[stack.length - 1]); // 89 - case 46: stack.push(0); // 3 - case 47: stack.push(arg0); // 42 - case 48: stack.push(stack.pop().count); // 180 1 97 - case 51: stack.push(arg2); // 28 - case 52: stack.push(stack.pop() + stack.pop()); // 96 - case 53: stack.push(arg3); // 45 - case 54: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 57: return stack.pop(); // 176 - } -} -function java_lang_String_replaceLjava_lang_StringCC(arg0,arg1,arg2) { - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: stack.push(arg2); // 28 - case 2: if (stack.pop() == stack.pop()) { gt = 140; continue; } // 159 0 138 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: arg3 = stack.pop(); // 62 - case 10: // 2 - case 11: arg4 = stack.pop() // 54 4 - case 13: stack.push(arg0); // 42 - case 14: stack.push(stack.pop().value); // 180 1 100 - case 17: arg5 = stack.pop() // 58 5 - case 19: stack.push(arg0); // 42 - case 20: stack.push(stack.pop().offset); // 180 1 99 - case 23: arg6 = stack.pop() // 54 6 - case 25: arg4++; // 132 4 1 - case 28: stack.push(arg4); // 21 4 - case 30: stack.push(arg3); // 29 - case 31: if (stack.pop() <= stack.pop()) { gt = 49; continue; } // 162 0 18 - case 34: stack.push(arg5); // 25 5 - case 36: stack.push(arg6); // 21 6 - case 38: stack.push(arg4); // 21 4 - case 40: stack.push(stack.pop() + stack.pop()); // 96 - case 41: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 42: stack.push(arg1); // 27 - case 43: if (stack.pop() != stack.pop()) { gt = 25; continue; } // 160 255 238 - case 46: gt = 49; continue; // 167 0 3 - case 49: stack.push(arg4); // 21 4 - case 51: stack.push(arg3); // 29 - case 52: if (stack.pop() <= stack.pop()) { gt = 140; continue; } // 162 0 88 - case 55: stack.push(arg3); // 29 - case 56: stack.push(new Array(stack.pop())); // 188 5 - case 58: arg7 = stack.pop() // 58 7 - case 60: stack.push(0); // 3 - case 61: arg8 = stack.pop() // 54 8 - case 63: stack.push(arg8); // 21 8 - case 65: stack.push(arg4); // 21 4 - case 67: if (stack.pop() <= stack.pop()) { gt = 89; continue; } // 162 0 22 - case 70: stack.push(arg7); // 25 7 - case 72: stack.push(arg8); // 21 8 - case 74: stack.push(arg5); // 25 5 - case 76: stack.push(arg6); // 21 6 - case 78: stack.push(arg8); // 21 8 - case 80: stack.push(stack.pop() + stack.pop()); // 96 - case 81: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 82: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 83: arg8++; // 132 8 1 - case 86: gt = 63; continue; // 167 255 233 - case 89: stack.push(arg4); // 21 4 - case 91: stack.push(arg3); // 29 - case 92: if (stack.pop() <= stack.pop()) { gt = 128; continue; } // 162 0 36 - case 95: stack.push(arg5); // 25 5 - case 97: stack.push(arg6); // 21 6 - case 99: stack.push(arg4); // 21 4 - case 101: stack.push(stack.pop() + stack.pop()); // 96 - case 102: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 103: arg8 = stack.pop() // 54 8 - case 105: stack.push(arg7); // 25 7 - case 107: stack.push(arg4); // 21 4 - case 109: stack.push(arg8); // 21 8 - case 111: stack.push(arg1); // 27 - case 112: if (stack.pop() != stack.pop()) { gt = 119; continue; } // 160 0 7 - case 115: stack.push(arg2); // 28 - case 116: gt = 121; continue; // 167 0 5 - case 119: stack.push(arg8); // 21 8 - case 121: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 122: arg4++; // 132 4 1 - case 125: gt = 89; continue; // 167 255 220 - case 128: stack.push(new java_lang_String); // 187 0 200 - case 131: stack.push(stack[stack.length - 1]); // 89 - case 132: stack.push(0); // 3 - case 133: stack.push(arg3); // 29 - case 134: stack.push(arg7); // 25 7 - case 136: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 139: return stack.pop(); // 176 - case 140: stack.push(arg0); // 42 - case 141: return stack.pop(); // 176 - } -} -function java_lang_String_matchesZLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: stack.push(arg0); // 42 - case 2: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_regex_Pattern_matchesZLjava_lang_StringLjava_lang_CharSequence(v0, v1)); } // 184 1 183 - case 5: return stack.pop(); // 172 - } -} -function java_lang_String_containsZLjava_lang_CharSequence(arg0,arg1) { - var arg2; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132 - case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfILjava_lang_String(self, v0)); } // 182 1 149 - case 8: // 2 - case 9: if (stack.pop() >= stack.pop()) { gt = 16; continue; } // 164 0 7 - case 12: stack.push(1); // 4 - case 13: gt = 17; continue; // 167 0 4 - case 16: stack.push(0); // 3 - case 17: return stack.pop(); // 172 - } -} -function java_lang_String_replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186 - case 4: stack.push(arg0); // 42 - case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185 - case 8: stack.push(arg2); // 44 - case 9: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceFirstLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 182 - case 12: return stack.pop(); // 176 - } -} -function java_lang_String_replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186 - case 4: stack.push(arg0); // 42 - case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185 - case 8: stack.push(arg2); // 44 - case 9: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceAllLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 181 - case 12: return stack.pop(); // 176 - } -} -function java_lang_String_replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132 - case 4: stack.push(16); // 16 16 - case 6: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_StringI(v0, v1)); } // 184 1 187 - case 9: stack.push(arg0); // 42 - case 10: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185 - case 13: stack.push(arg2); // 44 - case 14: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132 - case 17: { var v0 = stack.pop(); stack.push(java_util_regex_Matcher_quoteReplacementLjava_lang_StringLjava_lang_String(v0)); } // 184 1 180 - case 20: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceAllLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 181 - case 23: return stack.pop(); // 176 - } -} -function java_lang_String_splitALjava_lang_StringLjava_lang_StringI(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186 - case 4: stack.push(arg0); // 42 - case 5: stack.push(arg2); // 28 - case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.splitALjava_lang_StringLjava_lang_CharSequenceI(self, v0, v1)); } // 182 1 184 - case 9: return stack.pop(); // 176 - } -} -function java_lang_String_splitALjava_lang_StringLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(0); // 3 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.splitALjava_lang_StringLjava_lang_StringI(self, v0, v1)); } // 182 1 157 - case 6: return stack.pop(); // 176 - } -} -function java_lang_String_toLowerCaseLjava_lang_StringLjava_util_Locale(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; - var arg14; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11 - case 4: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128 - case 11: // 191 - case 12: stack.push(0); // 3 - case 13: arg2 = stack.pop(); // 61 - case 14: stack.push(arg2); // 28 - case 15: stack.push(arg0); // 42 - case 16: stack.push(stack.pop().count); // 180 1 97 - case 19: if (stack.pop() <= stack.pop()) { gt = 94; continue; } // 162 0 75 - case 22: stack.push(arg0); // 42 - case 23: stack.push(stack.pop().value); // 180 1 100 - case 26: stack.push(arg0); // 42 - case 27: stack.push(stack.pop().offset); // 180 1 99 - case 30: stack.push(arg2); // 28 - case 31: stack.push(stack.pop() + stack.pop()); // 96 - case 32: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 33: arg3 = stack.pop(); // 62 - case 34: stack.push(arg3); // 29 - case 35: stack.push(55296); // 18 1 - case 37: if (stack.pop() > stack.pop()) { gt = 77; continue; } // 161 0 40 - case 40: stack.push(arg3); // 29 - case 41: stack.push(56319); // 18 2 - case 43: if (stack.pop() < stack.pop()) { gt = 77; continue; } // 163 0 34 - case 46: stack.push(arg0); // 42 - case 47: stack.push(arg2); // 28 - case 48: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134 - case 51: arg4 = stack.pop() // 54 4 - case 53: stack.push(arg4); // 21 4 - case 55: stack.push(arg4); // 21 4 - case 57: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseII(v0)); } // 184 1 107 - case 60: if (stack.pop() == stack.pop()) { gt = 66; continue; } // 159 0 6 - case 63: gt = 96; continue; // 167 0 33 - case 66: stack.push(arg2); // 28 - case 67: stack.push(arg4); // 21 4 - case 69: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106 - case 72: stack.push(stack.pop() + stack.pop()); // 96 - case 73: arg2 = stack.pop(); // 61 - case 74: gt = 91; continue; // 167 0 17 - case 77: stack.push(arg3); // 29 - case 78: stack.push(arg3); // 29 - case 79: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104 - case 82: if (stack.pop() == stack.pop()) { gt = 88; continue; } // 159 0 6 - case 85: gt = 96; continue; // 167 0 11 - case 88: arg2++; // 132 2 1 - case 91: gt = 14; continue; // 167 255 179 - case 94: stack.push(arg0); // 42 - case 95: return stack.pop(); // 176 - case 96: stack.push(arg0); // 42 - case 97: stack.push(stack.pop().count); // 180 1 97 - case 100: stack.push(new Array(stack.pop())); // 188 5 - case 102: arg3 = stack.pop(); // 78 - case 103: stack.push(0); // 3 - case 104: arg4 = stack.pop() // 54 4 - case 106: stack.push(arg0); // 42 - case 107: stack.push(stack.pop().value); // 180 1 100 - case 110: stack.push(arg0); // 42 - case 111: stack.push(stack.pop().offset); // 180 1 99 - case 114: stack.push(arg3); // 45 - case 115: stack.push(0); // 3 - case 116: stack.push(arg2); // 28 - case 117: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171 - case 120: stack.push(arg1); // 43 - case 121: { var self = stack.pop(); stack.push(self.getLanguageLjava_lang_String(self)); } // 182 1 178 - case 124: arg5 = stack.pop() // 58 5 - case 126: stack.push(arg5); // 25 5 - case 128: stack.push("tr"); // 18 11 - case 130: // 165 - case 131: // 0 - case 132: stack.push(6405); // 17 25 5 - case 135: stack.push("az"); // 18 5 - case 137: // 165 - case 138: // 0 - case 139: stack.push(1); // 10 - case 140: stack.push(arg5); // 25 5 - case 142: stack.push("lt"); // 18 9 - case 144: // 166 - case 145: // 0 - case 146: stack.push(4); // 7 - case 147: stack.push(1); // 4 - case 148: gt = 152; continue; // 167 0 4 - case 151: stack.push(0); // 3 - case 152: arg6 = stack.pop() // 54 6 - case 154: stack.push(arg2); // 28 - case 155: arg11 = stack.pop() // 54 11 - case 157: stack.push(arg11); // 21 11 - case 159: stack.push(arg0); // 42 - case 160: stack.push(stack.pop().count); // 180 1 97 - case 163: if (stack.pop() <= stack.pop()) { gt = 419; continue; } // 162 1 0 - case 166: stack.push(arg0); // 42 - case 167: stack.push(stack.pop().value); // 180 1 100 - case 170: stack.push(arg0); // 42 - case 171: stack.push(stack.pop().offset); // 180 1 99 - case 174: stack.push(arg11); // 21 11 - case 176: stack.push(stack.pop() + stack.pop()); // 96 - case 177: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 178: arg9 = stack.pop() // 54 9 - case 180: stack.push(arg9); // 21 9 - case 182: // number conversion // 146 - case 183: stack.push(55296); // 18 1 - case 185: if (stack.pop() > stack.pop()) { gt = 214; continue; } // 161 0 29 - case 188: stack.push(arg9); // 21 9 - case 190: // number conversion // 146 - case 191: stack.push(56319); // 18 2 - case 193: if (stack.pop() < stack.pop()) { gt = 214; continue; } // 163 0 21 - case 196: stack.push(arg0); // 42 - case 197: stack.push(arg11); // 21 11 - case 199: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134 - case 202: arg9 = stack.pop() // 54 9 - case 204: stack.push(arg9); // 21 9 - case 206: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106 - case 209: arg10 = stack.pop() // 54 10 - case 211: gt = 217; continue; // 167 0 6 - case 214: stack.push(1); // 4 - case 215: arg10 = stack.pop() // 54 10 - case 217: stack.push(arg6); // 21 6 - case 219: if (stack.pop() != 0) { gt = 230; continue; } // 154 0 11 - case 222: stack.push(arg9); // 21 9 - case 224: stack.push(931); // 17 3 163 - case 227: if (stack.pop() != stack.pop()) { gt = 242; continue; } // 160 0 15 - case 230: stack.push(arg0); // 42 - case 231: stack.push(arg11); // 21 11 - case 233: stack.push(arg1); // 43 - case 234: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toLowerCaseExILjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 117 - case 237: arg8 = stack.pop() // 54 8 - case 239: gt = 249; continue; // 167 0 10 - case 242: stack.push(arg9); // 21 9 - case 244: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseII(v0)); } // 184 1 107 - case 247: arg8 = stack.pop() // 54 8 - case 249: stack.push(arg8); // 21 8 - case 251: // 2 - case 252: if (stack.pop() == stack.pop()) { gt = 262; continue; } // 159 0 10 - case 255: stack.push(arg8); // 21 8 - case 257: stack.push(65536); // 18 3 - case 259: if (stack.pop() > stack.pop()) { gt = 399; continue; } // 161 0 140 - case 262: stack.push(arg8); // 21 8 - case 264: // 2 - case 265: if (stack.pop() != stack.pop()) { gt = 280; continue; } // 160 0 15 - case 268: stack.push(arg0); // 42 - case 269: stack.push(arg11); // 21 11 - case 271: stack.push(arg1); // 43 - case 272: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toLowerCaseCharArrayACLjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 119 - case 275: arg7 = stack.pop() // 58 7 - case 277: gt = 315; continue; // 167 0 38 - case 280: stack.push(arg10); // 21 10 - case 282: stack.push(2); // 5 - case 283: if (stack.pop() != stack.pop()) { gt = 308; continue; } // 160 0 25 - case 286: stack.push(arg4); // 21 4 - case 288: stack.push(arg8); // 21 8 - case 290: stack.push(arg3); // 45 - case 291: stack.push(arg11); // 21 11 - case 293: stack.push(arg4); // 21 4 - case 295: stack.push(stack.pop() + stack.pop()); // 96 - case 296: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_toCharsAIIACAI(v0, v1, v2)); } // 184 1 111 - case 299: stack.push(arg10); // 21 10 - case 301: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 302: stack.push(stack.pop() + stack.pop()); // 96 - case 303: arg4 = stack.pop() // 54 4 - case 305: gt = 409; continue; // 167 0 104 - case 308: stack.push(arg8); // 21 8 - case 310: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109 - case 313: arg7 = stack.pop() // 58 7 - case 315: stack.push(arg7); // 25 7 - case 317: stack.push(stack.pop().length); // 190 - case 318: arg12 = stack.pop() // 54 12 - case 320: stack.push(arg12); // 21 12 - case 322: stack.push(arg10); // 21 10 - case 324: if (stack.pop() >= stack.pop()) { gt = 355; continue; } // 164 0 31 - case 327: stack.push(arg3); // 45 - case 328: stack.push(stack.pop().length); // 190 - case 329: stack.push(arg12); // 21 12 - case 331: stack.push(stack.pop() + stack.pop()); // 96 - case 332: stack.push(arg10); // 21 10 - case 334: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 335: stack.push(new Array(stack.pop())); // 188 5 - case 337: arg13 = stack.pop() // 58 13 - case 339: stack.push(arg3); // 45 - case 340: stack.push(0); // 3 - case 341: stack.push(arg13); // 25 13 - case 343: stack.push(0); // 3 - case 344: stack.push(arg11); // 21 11 - case 346: stack.push(arg4); // 21 4 - case 348: stack.push(stack.pop() + stack.pop()); // 96 - case 349: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171 - case 352: stack.push(arg13); // 25 13 - case 354: arg3 = stack.pop(); // 78 - case 355: stack.push(0); // 3 - case 356: arg13 = stack.pop() // 54 13 - case 358: stack.push(arg13); // 21 13 - case 360: stack.push(arg12); // 21 12 - case 362: if (stack.pop() <= stack.pop()) { gt = 386; continue; } // 162 0 24 - case 365: stack.push(arg3); // 45 - case 366: stack.push(arg11); // 21 11 - case 368: stack.push(arg4); // 21 4 - case 370: stack.push(stack.pop() + stack.pop()); // 96 - case 371: stack.push(arg13); // 21 13 - case 373: stack.push(stack.pop() + stack.pop()); // 96 - case 374: stack.push(arg7); // 25 7 - case 376: stack.push(arg13); // 21 13 - case 378: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 379: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 380: arg13++; // 132 13 1 - case 383: gt = 358; continue; // 167 255 231 - case 386: stack.push(arg4); // 21 4 - case 388: stack.push(arg12); // 21 12 - case 390: stack.push(arg10); // 21 10 - case 392: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 393: stack.push(stack.pop() + stack.pop()); // 96 - case 394: arg4 = stack.pop() // 54 4 - case 396: gt = 409; continue; // 167 0 13 - case 399: stack.push(arg3); // 45 - case 400: stack.push(arg11); // 21 11 - case 402: stack.push(arg4); // 21 4 - case 404: stack.push(stack.pop() + stack.pop()); // 96 - case 405: stack.push(arg8); // 21 8 - case 407: // number conversion // 146 - case 408: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 409: stack.push(arg11); // 21 11 - case 411: stack.push(arg10); // 21 10 - case 413: stack.push(stack.pop() + stack.pop()); // 96 - case 414: arg11 = stack.pop() // 54 11 - case 416: gt = 157; continue; // 167 254 253 - case 419: stack.push(new java_lang_String); // 187 0 200 - case 422: stack.push(stack[stack.length - 1]); // 89 - case 423: stack.push(0); // 3 - case 424: stack.push(arg0); // 42 - case 425: stack.push(stack.pop().count); // 180 1 97 - case 428: stack.push(arg4); // 21 4 - case 430: stack.push(stack.pop() + stack.pop()); // 96 - case 431: stack.push(arg3); // 45 - case 432: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 435: return stack.pop(); // 176 - } -} -function java_lang_String_toLowerCaseLjava_lang_String(arg0) { - var arg1; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { stack.push(java_util_Locale_getDefaultLjava_util_Locale()); } // 184 1 179 - case 4: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.toLowerCaseLjava_lang_StringLjava_util_Locale(self, v0)); } // 182 1 158 - case 7: return stack.pop(); // 176 - } -} -function java_lang_String_toUpperCaseLjava_lang_StringLjava_util_Locale(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; - var arg14; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11 - case 4: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128 - case 11: // 191 - case 12: stack.push(0); // 3 - case 13: arg2 = stack.pop(); // 61 - case 14: stack.push(arg2); // 28 - case 15: stack.push(arg0); // 42 - case 16: stack.push(stack.pop().count); // 180 1 97 - case 19: if (stack.pop() <= stack.pop()) { gt = 93; continue; } // 162 0 74 - case 22: stack.push(arg0); // 42 - case 23: stack.push(stack.pop().value); // 180 1 100 - case 26: stack.push(arg0); // 42 - case 27: stack.push(stack.pop().offset); // 180 1 99 - case 30: stack.push(arg2); // 28 - case 31: stack.push(stack.pop() + stack.pop()); // 96 - case 32: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 33: arg3 = stack.pop(); // 62 - case 34: stack.push(arg3); // 29 - case 35: stack.push(55296); // 18 1 - case 37: if (stack.pop() > stack.pop()) { gt = 61; continue; } // 161 0 24 - case 40: stack.push(arg3); // 29 - case 41: stack.push(56319); // 18 2 - case 43: if (stack.pop() < stack.pop()) { gt = 61; continue; } // 163 0 18 - case 46: stack.push(arg0); // 42 - case 47: stack.push(arg2); // 28 - case 48: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134 - case 51: arg3 = stack.pop(); // 62 - case 52: stack.push(arg3); // 29 - case 53: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106 - case 56: arg4 = stack.pop() // 54 4 - case 58: gt = 64; continue; // 167 0 6 - case 61: stack.push(1); // 4 - case 62: arg4 = stack.pop() // 54 4 - case 64: stack.push(arg3); // 29 - case 65: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseExII(v0)); } // 184 1 108 - case 68: arg5 = stack.pop() // 54 5 - case 70: stack.push(arg5); // 21 5 - case 72: // 2 - case 73: if (stack.pop() == stack.pop()) { gt = 95; continue; } // 159 0 22 - case 76: stack.push(arg3); // 29 - case 77: stack.push(arg5); // 21 5 - case 79: if (stack.pop() == stack.pop()) { gt = 85; continue; } // 159 0 6 - case 82: gt = 95; continue; // 167 0 13 - case 85: stack.push(arg2); // 28 - case 86: stack.push(arg4); // 21 4 - case 88: stack.push(stack.pop() + stack.pop()); // 96 - case 89: arg2 = stack.pop(); // 61 - case 90: gt = 14; continue; // 167 255 180 - case 93: stack.push(arg0); // 42 - case 94: return stack.pop(); // 176 - case 95: stack.push(arg0); // 42 - case 96: stack.push(stack.pop().count); // 180 1 97 - case 99: stack.push(new Array(stack.pop())); // 188 5 - case 101: arg3 = stack.pop(); // 78 - case 102: stack.push(0); // 3 - case 103: arg4 = stack.pop() // 54 4 - case 105: stack.push(arg0); // 42 - case 106: stack.push(stack.pop().value); // 180 1 100 - case 109: stack.push(arg0); // 42 - case 110: stack.push(stack.pop().offset); // 180 1 99 - case 113: stack.push(arg3); // 45 - case 114: stack.push(0); // 3 - case 115: stack.push(arg2); // 28 - case 116: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171 - case 119: stack.push(arg1); // 43 - case 120: { var self = stack.pop(); stack.push(self.getLanguageLjava_lang_String(self)); } // 182 1 178 - case 123: arg5 = stack.pop() // 58 5 - case 125: stack.push(arg5); // 25 5 - case 127: stack.push("tr"); // 18 11 - case 129: // 165 - case 130: // 0 - case 131: stack.push(6405); // 17 25 5 - case 134: stack.push("az"); // 18 5 - case 136: // 165 - case 137: // 0 - case 138: stack.push(1); // 10 - case 139: stack.push(arg5); // 25 5 - case 141: stack.push("lt"); // 18 9 - case 143: // 166 - case 144: // 0 - case 145: stack.push(4); // 7 - case 146: stack.push(1); // 4 - case 147: gt = 151; continue; // 167 0 4 - case 150: stack.push(0); // 3 - case 151: arg6 = stack.pop() // 54 6 - case 153: stack.push(arg2); // 28 - case 154: arg11 = stack.pop() // 54 11 - case 156: stack.push(arg11); // 21 11 - case 158: stack.push(arg0); // 42 - case 159: stack.push(stack.pop().count); // 180 1 97 - case 162: if (stack.pop() <= stack.pop()) { gt = 425; continue; } // 162 1 7 - case 165: stack.push(arg0); // 42 - case 166: stack.push(stack.pop().value); // 180 1 100 - case 169: stack.push(arg0); // 42 - case 170: stack.push(stack.pop().offset); // 180 1 99 - case 173: stack.push(arg11); // 21 11 - case 175: stack.push(stack.pop() + stack.pop()); // 96 - case 176: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 177: arg9 = stack.pop() // 54 9 - case 179: stack.push(arg9); // 21 9 - case 181: // number conversion // 146 - case 182: stack.push(55296); // 18 1 - case 184: if (stack.pop() > stack.pop()) { gt = 213; continue; } // 161 0 29 - case 187: stack.push(arg9); // 21 9 - case 189: // number conversion // 146 - case 190: stack.push(56319); // 18 2 - case 192: if (stack.pop() < stack.pop()) { gt = 213; continue; } // 163 0 21 - case 195: stack.push(arg0); // 42 - case 196: stack.push(arg11); // 21 11 - case 198: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134 - case 201: arg9 = stack.pop() // 54 9 - case 203: stack.push(arg9); // 21 9 - case 205: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106 - case 208: arg10 = stack.pop() // 54 10 - case 210: gt = 216; continue; // 167 0 6 - case 213: stack.push(1); // 4 - case 214: arg10 = stack.pop() // 54 10 - case 216: stack.push(arg6); // 21 6 - case 218: if (stack.pop() == 0) { gt = 233; continue; } // 153 0 15 - case 221: stack.push(arg0); // 42 - case 222: stack.push(arg11); // 21 11 - case 224: stack.push(arg1); // 43 - case 225: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toUpperCaseExILjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 118 - case 228: arg8 = stack.pop() // 54 8 - case 230: gt = 240; continue; // 167 0 10 - case 233: stack.push(arg9); // 21 9 - case 235: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseExII(v0)); } // 184 1 108 - case 238: arg8 = stack.pop() // 54 8 - case 240: stack.push(arg8); // 21 8 - case 242: // 2 - case 243: if (stack.pop() == stack.pop()) { gt = 253; continue; } // 159 0 10 - case 246: stack.push(arg8); // 21 8 - case 248: stack.push(65536); // 18 3 - case 250: if (stack.pop() > stack.pop()) { gt = 405; continue; } // 161 0 155 - case 253: stack.push(arg8); // 21 8 - case 255: // 2 - case 256: if (stack.pop() != stack.pop()) { gt = 286; continue; } // 160 0 30 - case 259: stack.push(arg6); // 21 6 - case 261: if (stack.pop() == 0) { gt = 276; continue; } // 153 0 15 - case 264: stack.push(arg0); // 42 - case 265: stack.push(arg11); // 21 11 - case 267: stack.push(arg1); // 43 - case 268: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toUpperCaseCharArrayACLjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 120 - case 271: arg7 = stack.pop() // 58 7 - case 273: gt = 321; continue; // 167 0 48 - case 276: stack.push(arg9); // 21 9 - case 278: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCharArrayACI(v0)); } // 184 1 110 - case 281: arg7 = stack.pop() // 58 7 - case 283: gt = 321; continue; // 167 0 38 - case 286: stack.push(arg10); // 21 10 - case 288: stack.push(2); // 5 - case 289: if (stack.pop() != stack.pop()) { gt = 314; continue; } // 160 0 25 - case 292: stack.push(arg4); // 21 4 - case 294: stack.push(arg8); // 21 8 - case 296: stack.push(arg3); // 45 - case 297: stack.push(arg11); // 21 11 - case 299: stack.push(arg4); // 21 4 - case 301: stack.push(stack.pop() + stack.pop()); // 96 - case 302: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_toCharsAIIACAI(v0, v1, v2)); } // 184 1 111 - case 305: stack.push(arg10); // 21 10 - case 307: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 308: stack.push(stack.pop() + stack.pop()); // 96 - case 309: arg4 = stack.pop() // 54 4 - case 311: gt = 415; continue; // 167 0 104 - case 314: stack.push(arg8); // 21 8 - case 316: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109 - case 319: arg7 = stack.pop() // 58 7 - case 321: stack.push(arg7); // 25 7 - case 323: stack.push(stack.pop().length); // 190 - case 324: arg12 = stack.pop() // 54 12 - case 326: stack.push(arg12); // 21 12 - case 328: stack.push(arg10); // 21 10 - case 330: if (stack.pop() >= stack.pop()) { gt = 361; continue; } // 164 0 31 - case 333: stack.push(arg3); // 45 - case 334: stack.push(stack.pop().length); // 190 - case 335: stack.push(arg12); // 21 12 - case 337: stack.push(stack.pop() + stack.pop()); // 96 - case 338: stack.push(arg10); // 21 10 - case 340: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 341: stack.push(new Array(stack.pop())); // 188 5 - case 343: arg13 = stack.pop() // 58 13 - case 345: stack.push(arg3); // 45 - case 346: stack.push(0); // 3 - case 347: stack.push(arg13); // 25 13 - case 349: stack.push(0); // 3 - case 350: stack.push(arg11); // 21 11 - case 352: stack.push(arg4); // 21 4 - case 354: stack.push(stack.pop() + stack.pop()); // 96 - case 355: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171 - case 358: stack.push(arg13); // 25 13 - case 360: arg3 = stack.pop(); // 78 - case 361: stack.push(0); // 3 - case 362: arg13 = stack.pop() // 54 13 - case 364: stack.push(arg13); // 21 13 - case 366: stack.push(arg12); // 21 12 - case 368: if (stack.pop() <= stack.pop()) { gt = 392; continue; } // 162 0 24 - case 371: stack.push(arg3); // 45 - case 372: stack.push(arg11); // 21 11 - case 374: stack.push(arg4); // 21 4 - case 376: stack.push(stack.pop() + stack.pop()); // 96 - case 377: stack.push(arg13); // 21 13 - case 379: stack.push(stack.pop() + stack.pop()); // 96 - case 380: stack.push(arg7); // 25 7 - case 382: stack.push(arg13); // 21 13 - case 384: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 385: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 386: arg13++; // 132 13 1 - case 389: gt = 364; continue; // 167 255 231 - case 392: stack.push(arg4); // 21 4 - case 394: stack.push(arg12); // 21 12 - case 396: stack.push(arg10); // 21 10 - case 398: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 399: stack.push(stack.pop() + stack.pop()); // 96 - case 400: arg4 = stack.pop() // 54 4 - case 402: gt = 415; continue; // 167 0 13 - case 405: stack.push(arg3); // 45 - case 406: stack.push(arg11); // 21 11 - case 408: stack.push(arg4); // 21 4 - case 410: stack.push(stack.pop() + stack.pop()); // 96 - case 411: stack.push(arg8); // 21 8 - case 413: // number conversion // 146 - case 414: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 415: stack.push(arg11); // 21 11 - case 417: stack.push(arg10); // 21 10 - case 419: stack.push(stack.pop() + stack.pop()); // 96 - case 420: arg11 = stack.pop() // 54 11 - case 422: gt = 156; continue; // 167 254 246 - case 425: stack.push(new java_lang_String); // 187 0 200 - case 428: stack.push(stack[stack.length - 1]); // 89 - case 429: stack.push(0); // 3 - case 430: stack.push(arg0); // 42 - case 431: stack.push(stack.pop().count); // 180 1 97 - case 434: stack.push(arg4); // 21 4 - case 436: stack.push(stack.pop() + stack.pop()); // 96 - case 437: stack.push(arg3); // 45 - case 438: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 441: return stack.pop(); // 176 - } -} -function java_lang_String_toUpperCaseLjava_lang_String(arg0) { - var arg1; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { stack.push(java_util_Locale_getDefaultLjava_util_Locale()); } // 184 1 179 - case 4: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.toUpperCaseLjava_lang_StringLjava_util_Locale(self, v0)); } // 182 1 159 - case 7: return stack.pop(); // 176 - } -} -function java_lang_String_trimLjava_lang_String(arg0) { - var arg1; - var arg2; - var arg3; - var arg4; - var arg5; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().count); // 180 1 97 - case 4: arg1 = stack.pop(); // 60 - case 5: stack.push(0); // 3 - case 6: arg2 = stack.pop(); // 61 - case 7: stack.push(arg0); // 42 - case 8: stack.push(stack.pop().offset); // 180 1 99 - case 11: arg3 = stack.pop(); // 62 - case 12: stack.push(arg0); // 42 - case 13: stack.push(stack.pop().value); // 180 1 100 - case 16: arg4 = stack.pop() // 58 4 - case 18: stack.push(arg2); // 28 - case 19: stack.push(arg1); // 27 - case 20: if (stack.pop() <= stack.pop()) { gt = 40; continue; } // 162 0 20 - case 23: stack.push(arg4); // 25 4 - case 25: stack.push(arg3); // 29 - case 26: stack.push(arg2); // 28 - case 27: stack.push(stack.pop() + stack.pop()); // 96 - case 28: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 29: stack.push(32); // 16 32 - case 31: if (stack.pop() < stack.pop()) { gt = 40; continue; } // 163 0 9 - case 34: arg2++; // 132 2 1 - case 37: gt = 18; continue; // 167 255 237 - case 40: stack.push(arg2); // 28 - case 41: stack.push(arg1); // 27 - case 42: if (stack.pop() <= stack.pop()) { gt = 64; continue; } // 162 0 22 - case 45: stack.push(arg4); // 25 4 - case 47: stack.push(arg3); // 29 - case 48: stack.push(arg1); // 27 - case 49: stack.push(stack.pop() + stack.pop()); // 96 - case 50: stack.push(1); // 4 - case 51: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 52: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 53: stack.push(32); // 16 32 - case 55: if (stack.pop() < stack.pop()) { gt = 64; continue; } // 163 0 9 - case 58: arg1 += 255; // 132 1 255 - case 61: gt = 40; continue; // 167 255 235 - case 64: stack.push(arg2); // 28 - case 65: if (stack.pop() > 0) { gt = 76; continue; } // 157 0 11 - case 68: stack.push(arg1); // 27 - case 69: stack.push(arg0); // 42 - case 70: stack.push(stack.pop().count); // 180 1 97 - case 73: if (stack.pop() <= stack.pop()) { gt = 85; continue; } // 162 0 12 - case 76: stack.push(arg0); // 42 - case 77: stack.push(arg2); // 28 - case 78: stack.push(arg1); // 27 - case 79: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147 - case 82: gt = 86; continue; // 167 0 4 - case 85: stack.push(arg0); // 42 - case 86: return stack.pop(); // 176 - } -} -*/ -function java_lang_String_toStringLjava_lang_String(arg0) { - return arg0.toString(); -} -/* -function java_lang_String_toCharArrayAC(arg0) { - var arg1; - var arg2; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().count); // 180 1 97 - case 4: stack.push(new Array(stack.pop())); // 188 5 - case 6: arg1 = stack.pop(); // 76 - case 7: stack.push(arg0); // 42 - case 8: stack.push(0); // 3 - case 9: stack.push(arg0); // 42 - case 10: stack.push(stack.pop().count); // 180 1 97 - case 13: stack.push(arg1); // 43 - case 14: stack.push(0); // 3 - case 15: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138 - case 18: stack.push(arg1); // 43 - case 19: return stack.pop(); // 176 - } -} -function java_lang_String_formatLjava_lang_StringLjava_lang_StringLjava_lang_Object(arg0,arg1) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_util_Formatter); // 187 0 211 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: { java_util_Formatter_consV(stack.pop()); } // 183 1 174 - case 7: stack.push(arg0); // 42 - case 8: stack.push(arg1); // 43 - case 9: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.formatALjava_util_FormatterLjava_lang_StringALjava_lang_Object(self, v0, v1)); } // 182 1 177 - case 12: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 175 - case 15: return stack.pop(); // 176 - } -} -function java_lang_String_formatLjava_lang_StringLjava_util_LocaleLjava_lang_StringLjava_lang_Object(arg0,arg1,arg2) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_util_Formatter); // 187 0 211 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(arg0); // 42 - case 5: { var v0 = stack.pop(); java_util_Formatter_consVLjava_util_Locale(stack.pop(), v0); } // 183 1 176 - case 8: stack.push(arg1); // 43 - case 9: stack.push(arg2); // 44 - case 10: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.formatALjava_util_FormatterLjava_lang_StringALjava_lang_Object(self, v0, v1)); } // 182 1 177 - case 13: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 175 - case 16: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringLjava_lang_Object(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: if (stack.pop()) { gt = 9; continue; } // 199 0 8 - case 4: stack.push("null"); // 18 10 - case 6: gt = 13; continue; // 167 0 7 - case 9: stack.push(arg0); // 42 - case 10: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132 - case 13: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringAC(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_lang_String); // 187 0 200 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(arg0); // 42 - case 5: { var v0 = stack.pop(); java_lang_String_consVAC(stack.pop(), v0); } // 183 1 142 - case 8: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringACII(arg0,arg1,arg2) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_lang_String); // 187 0 200 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(arg0); // 42 - case 5: stack.push(arg1); // 27 - case 6: stack.push(arg2); // 28 - case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVACAIAI(stack.pop(), v0, v1, v2); } // 183 1 143 - case 10: return stack.pop(); // 176 - } -} -function java_lang_String_copyValueOfLjava_lang_StringACII(arg0,arg1,arg2) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_lang_String); // 187 0 200 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(arg0); // 42 - case 5: stack.push(arg1); // 27 - case 6: stack.push(arg2); // 28 - case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVACAIAI(stack.pop(), v0, v1, v2); } // 183 1 143 - case 10: return stack.pop(); // 176 - } -} -function java_lang_String_copyValueOfLjava_lang_StringAC(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(0); // 3 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().length); // 190 - case 4: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_copyValueOfALjava_lang_StringACAIAI(v0, v1, v2)); } // 184 1 155 - case 7: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringZ(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 26 - case 1: if (stack.pop() == 0) { gt = 9; continue; } // 153 0 8 - case 4: stack.push("true"); // 18 12 - case 6: gt = 11; continue; // 167 0 5 - case 9: stack.push("false"); // 18 8 - case 11: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringC(arg0) { - var arg1; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(1); // 4 - case 1: stack.push(new Array(stack.pop())); // 188 5 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(0); // 3 - case 5: stack.push(arg0); // 26 - case 6: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 7: arg1 = stack.pop(); // 76 - case 8: stack.push(new java_lang_String); // 187 0 200 - case 11: stack.push(stack[stack.length - 1]); // 89 - case 12: stack.push(0); // 3 - case 13: stack.push(1); // 4 - case 14: stack.push(arg1); // 43 - case 15: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 18: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringI(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 26 - case 1: stack.push(10); // 16 10 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Integer_toStringLjava_lang_StringII(v0, v1)); } // 184 1 125 - case 6: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringJ(arg0) { - var arg1; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 30 - case 1: stack.push(10); // 16 10 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Long_toStringLjava_lang_StringJI(v0, v1)); } // 184 1 126 - case 6: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringF(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 34 - case 1: { var v0 = stack.pop(); stack.push(java_lang_Float_toStringLjava_lang_StringF(v0)); } // 184 1 122 - case 4: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringD(arg0) { - var arg1; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 38 - case 1: { var v0 = stack.pop(); stack.push(java_lang_Double_toStringLjava_lang_StringD(v0)); } // 184 1 121 - case 4: return stack.pop(); // 176 - } -} -function java_lang_String_internLjava_lang_String(arg0) { - // no code found for null -} -function java_lang_String_compareToILjava_lang_Object(arg0,arg1) { - var arg2; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: if(stack[stack.length - 1].$instOf_java_lang_String != 1) throw {}; // 192 0 200 - case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.compareToILjava_lang_String(self, v0)); } // 182 1 148 - case 8: return stack.pop(); // 172 - } -} -function java_lang_String_classV() { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(0); // 3 - case 1: stack.push(new Array(stack.pop())); // 189 0 183 - case 4: java_lang_String_serialPersistentFields = stack.pop(); // 179 1 101 - case 7: stack.push(new java_lang_String$CaseInsensitiveComparator); // 187 0 202 - case 10: stack.push(stack[stack.length - 1]); // 89 - case 11: // 1 - case 12: { var v0 = stack.pop(); java_lang_String$CaseInsensitiveComparator_consVLjava_lang_String$1(stack.pop(), v0); } // 183 1 160 - case 15: java_lang_String_CASE_INSENSITIVE_ORDER = stack.pop(); // 179 1 102 - case 18: return; // 177 - } -} -*/ -var java_lang_String_serialVersionUID = 0; -var java_lang_String_serialPersistentFields = 0; -var java_lang_String_CASE_INSENSITIVE_ORDER = 0; -function java_lang_String() { - /** the real value of this 'string' we delegate to */ - this.r = ''; - - var self = this; - /* - this.value = 0; - this.offset = 0; - this.count = 0; - this.hash = 0; - */ - this.toString = function() { return self.r; }; -} -java_lang_String.prototype = new String; -//java_lang_String_classV(); - -/* new method for JavaScript String */ -String.prototype.charAtCI = java_lang_String_charAtCI; -String.prototype.lengthI = java_lang_String_lengthI; -String.prototype.isEmptyZ = java_lang_String_isEmptyZ; -String.prototype.getCharsVIIACI = java_lang_String_getCharsVIIACAI; -String.prototype.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String; -String.prototype.$instOf_java_lang_String = true; -String.prototype.$instOf_java_io_Serializable = true; -String.prototype.$instOf_java_lang_Comparable = true; -String.prototype.$instOf_java_lang_CharSequence = true; - -/* - this.lengthI = java_lang_String_lengthI; - this.isEmptyZ = java_lang_String_isEmptyZ; - this.charAtCI = java_lang_String_charAtCI; - this.codePointAtII = java_lang_String_codePointAtII; - this.codePointBeforeII = java_lang_String_codePointBeforeII; - this.codePointCountIII = java_lang_String_codePointCountIII; - this.offsetByCodePointsIII = java_lang_String_offsetByCodePointsIII; - this.getCharsVACI = java_lang_String_getCharsVACI; - this.getCharsVIIACI = java_lang_String_getCharsVIIACI; - this.getBytesVIIABI = java_lang_String_getBytesVIIABI; - this.getBytesABLjava_lang_String = java_lang_String_getBytesABLjava_lang_String; - this.getBytesABLjava_nio_charset_Charset = java_lang_String_getBytesABLjava_nio_charset_Charset; - this.getBytesAB = java_lang_String_getBytesAB; - this.equalsZLjava_lang_Object = java_lang_String_equalsZLjava_lang_Object; - this.contentEqualsZLjava_lang_StringBuffer = java_lang_String_contentEqualsZLjava_lang_StringBuffer; - this.contentEqualsZLjava_lang_CharSequence = java_lang_String_contentEqualsZLjava_lang_CharSequence; - this.equalsIgnoreCaseZLjava_lang_String = java_lang_String_equalsIgnoreCaseZLjava_lang_String; - this.compareToILjava_lang_String = java_lang_String_compareToILjava_lang_String; - this.compareToIgnoreCaseILjava_lang_String = java_lang_String_compareToIgnoreCaseILjava_lang_String; - this.regionMatchesZILjava_lang_StringII = java_lang_String_regionMatchesZILjava_lang_StringII; - this.regionMatchesZZILjava_lang_StringII = java_lang_String_regionMatchesZZILjava_lang_StringII; - this.startsWithZLjava_lang_StringI = java_lang_String_startsWithZLjava_lang_StringI; - this.startsWithZLjava_lang_String = java_lang_String_startsWithZLjava_lang_String; - this.endsWithZLjava_lang_String = java_lang_String_endsWithZLjava_lang_String; - this.hashCodeI = java_lang_String_hashCodeI; - this.indexOfII = java_lang_String_indexOfII; - this.indexOfIII = java_lang_String_indexOfIII; - this.lastIndexOfII = java_lang_String_lastIndexOfII; - this.lastIndexOfIII = java_lang_String_lastIndexOfIII; - this.indexOfILjava_lang_String = java_lang_String_indexOfILjava_lang_String; - this.indexOfILjava_lang_StringI = java_lang_String_indexOfILjava_lang_StringI; - this.lastIndexOfILjava_lang_String = java_lang_String_lastIndexOfILjava_lang_String; - this.lastIndexOfILjava_lang_StringI = java_lang_String_lastIndexOfILjava_lang_StringI; - this.substringLjava_lang_StringI = java_lang_String_substringLjava_lang_StringI; - this.substringLjava_lang_StringII = java_lang_String_substringLjava_lang_StringII; - this.subSequenceLjava_lang_CharSequenceII = java_lang_String_subSequenceLjava_lang_CharSequenceII; - this.concatLjava_lang_StringLjava_lang_String = java_lang_String_concatLjava_lang_StringLjava_lang_String; - this.replaceLjava_lang_StringCC = java_lang_String_replaceLjava_lang_StringCC; - this.matchesZLjava_lang_String = java_lang_String_matchesZLjava_lang_String; - this.containsZLjava_lang_CharSequence = java_lang_String_containsZLjava_lang_CharSequence; - this.replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String = java_lang_String_replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String; - this.replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String = java_lang_String_replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String; - this.replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence = java_lang_String_replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence; - this.splitALjava_lang_StringLjava_lang_StringI = java_lang_String_splitALjava_lang_StringLjava_lang_StringI; - this.splitALjava_lang_StringLjava_lang_String = java_lang_String_splitALjava_lang_StringLjava_lang_String; - this.toLowerCaseLjava_lang_StringLjava_util_Locale = java_lang_String_toLowerCaseLjava_lang_StringLjava_util_Locale; - this.toLowerCaseLjava_lang_String = java_lang_String_toLowerCaseLjava_lang_String; - this.toUpperCaseLjava_lang_StringLjava_util_Locale = java_lang_String_toUpperCaseLjava_lang_StringLjava_util_Locale; - this.toUpperCaseLjava_lang_String = java_lang_String_toUpperCaseLjava_lang_String; - this.trimLjava_lang_String = java_lang_String_trimLjava_lang_String; - this.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String; - this.toCharArrayAC = java_lang_String_toCharArrayAC; - this.internLjava_lang_String = java_lang_String_internLjava_lang_String; - this.compareToILjava_lang_Object = java_lang_String_compareToILjava_lang_Object; - */ - - - + return ret; +}; diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/pom.xml --- a/htmlpage/pom.xml Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ - - - 4.0.0 - - org.apidesign - bck2brwsr - 1.0-SNAPSHOT - - org.apidesign - htmlpage - 1.0-SNAPSHOT - htmlpage - http://maven.apache.org - - UTF-8 - - - - org.testng - testng - test - - - junit - junit - - - - - org.netbeans.api - org-openide-util-lookup - - - org.apidesign.bck2brwsr - core - 1.0-SNAPSHOT - jar - - - org.apidesign.bck2brwsr - emul - 1.0-SNAPSHOT - jar - - - org.apidesign.bck2brwsr - vm4brwsr - 0.1-SNAPSHOT - jar - test - - - - - - com.mycila.maven-license-plugin - maven-license-plugin - 1.9.0 - -

    ../vm/src/header.txt
    - - - - - diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -/** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-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.bck2brwsr.htmlpage; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.Locale; -import java.util.Set; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.Processor; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; -import javax.tools.FileObject; -import javax.tools.StandardLocation; -import org.apidesign.bck2brwsr.htmlpage.api.OnClick; -import org.apidesign.bck2brwsr.htmlpage.api.Page; -import org.openide.util.lookup.ServiceProvider; - -/** Annotation processor to process an XHTML page and generate appropriate - * "id" file. - * - * @author Jaroslav Tulach - */ -@ServiceProvider(service=Processor.class) -@SupportedAnnotationTypes({ - "org.apidesign.bck2brwsr.htmlpage.api.Page", - "org.apidesign.bck2brwsr.htmlpage.api.OnClick" -}) -public final class PageProcessor extends AbstractProcessor { - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) { - Page p = e.getAnnotation(Page.class); - PackageElement pe = (PackageElement)e.getEnclosingElement(); - String pkg = pe.getQualifiedName().toString(); - - ProcessPage pp; - try { - InputStream is = openStream(pkg, p.xhtml()); - pp = ProcessPage.readPage(is); - is.close(); - } catch (IOException iOException) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't read " + p.xhtml(), e); - return false; - } - Writer w; - try { - FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + p.name(), e); - w = new OutputStreamWriter(java.openOutputStream()); - try { - w.append("package " + pkg + ";\n"); - w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n"); - w.append("class ").append(p.name()).append(" {\n"); - for (String id : pp.ids()) { - String tag = pp.tagNameForId(id); - String type = type(tag); - w.append(" ").append("public static final "). - append(type).append(' ').append(cnstnt(id)).append(" = new "). - append(type).append("(\"").append(id).append("\");\n"); - } - w.append(" static {\n"); - if (!initializeOnClick(pe, w, pp)) { - return false; - } - w.append(" }\n"); - w.append("}\n"); - } finally { - w.close(); - } - } catch (IOException ex) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + p.name() + ".java", e); - return false; - } - } - return true; - } - - private InputStream openStream(String pkg, String name) throws IOException { - FileObject fo = processingEnv.getFiler().getResource( - StandardLocation.SOURCE_PATH, pkg, name); - try { - return fo.openInputStream(); - } catch (IOException ex) { - return processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, pkg, name).openInputStream(); - } - } - - private static String type(String tag) { - if (tag.equals("title")) { - return "Title"; - } - if (tag.equals("button")) { - return "Button"; - } - if (tag.equals("input")) { - return "Input"; - } - return "Element"; - } - - private static String cnstnt(String id) { - return id.toUpperCase(Locale.ENGLISH).replace('.', '_'); - } - - private boolean initializeOnClick(PackageElement pe, Writer w, ProcessPage pp) throws IOException { - for (Element clazz : pe.getEnclosedElements()) { - if (clazz.getKind() != ElementKind.CLASS) { - continue; - } - TypeElement type = (TypeElement)clazz; - for (Element method : clazz.getEnclosedElements()) { - OnClick oc = method.getAnnotation(OnClick.class); - if (oc != null) { - if (pp.tagNameForId(oc.id()) == null) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + oc.id() + " does not exist in the HTML page. Found only " + pp.ids(), method); - return false; - } - ExecutableElement ee = (ExecutableElement)method; - if (!ee.getParameters().isEmpty()) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClose method can't take arguments", ee); - return false; - } - if (!ee.getModifiers().contains(Modifier.STATIC)) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClose method has to be static", ee); - return false; - } - if (ee.getModifiers().contains(Modifier.PRIVATE)) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClose method can't be private", ee); - return false; - } - w.append(" ").append(cnstnt(oc.id())). - append(".addOnClick(new Runnable() { public void run() {\n"); - w.append(" ").append(type.getSimpleName().toString()). - append('.').append(ee.getSimpleName()).append("();\n"); - w.append(" }});\n"); - } - } - } - return true; - } -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/ProcessPage.java --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/ProcessPage.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-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.bck2brwsr.htmlpage; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -class ProcessPage { - private final Map ids2Elems = new TreeMap(); - - public Set ids() { - return Collections.unmodifiableSet(ids2Elems.keySet()); - } - - public String tagNameForId(String id) { - return ids2Elems.get(id); - } - - public static ProcessPage readPage(InputStream is) throws IOException { - DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); - f.setValidating(false); - f.setIgnoringComments(true); - - Document doc = null; - try { - DocumentBuilder b = f.newDocumentBuilder(); - doc = b.parse(is); - } catch (IOException ex) { - throw ex; - } catch (Exception e) { - throw new IOException(e); - } - Element root = doc.getDocumentElement(); - - ProcessPage pp = new ProcessPage(); - pp.seekForIds(root); - return pp; - } - - private void seekForIds(Element e) { - String val = e.getAttribute("id"); - if (val != null && !val.isEmpty()) { - String prev = ids2Elems.put(val, e.getTagName()); - } - NodeList arr = e.getChildNodes(); - for (int i = 0; i < arr.getLength(); i++) { - final Node n = arr.item(i); - if (n instanceof Element) { - seekForIds((Element)n); - } - } - } -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Button.java --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Button.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-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.bck2brwsr.htmlpage.api; - -/** - * - * @author Jaroslav Tulach - */ -public final class Button extends Element { - public Button(String id) { - super(id); - } - - @Override - void dontSubclass() { - } - - public void setDisabled(boolean state) { - setAttribute(this, "disabled", state); - } -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-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.bck2brwsr.htmlpage.api; - -import org.apidesign.bck2brwsr.core.JavaScriptBody; - -/** Represents a generic HTML element. - * - * @author Jaroslav Tulach - */ -public abstract class Element { - private final String id; - - public Element(String id) { - this.id = id; - } - - abstract void dontSubclass(); - - @JavaScriptBody( - args={"el", "property", "value"}, - body="var e = window.document.getElementById(el.id);\n" - + "e[property] = value;\n" - ) - static void setAttribute(Element el, String property, Object value) { - throw new UnsupportedOperationException("Needs JavaScript!"); - } - - @JavaScriptBody( - args={"el", "property"}, - body="var e = window.document.getElementById(el.id);\n" - + "return e[property];\n" - ) - static Object getAttribute(Element el, String property) { - throw new UnsupportedOperationException("Needs JavaScript!"); - } - - /** Executes given runnable when user performs a "click" on the given - * element. - * @param r the runnable to execute, never null - */ - @JavaScriptBody( - args={"el", "r"}, - body="var e = window.document.getElementById(el.id);\n" - + "e.onclick = function() { r.runV(); };\n" - ) - public final void addOnClick(Runnable r) { - throw new UnsupportedOperationException("Needs JavaScript!"); - } -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Input.java --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Input.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-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.bck2brwsr.htmlpage.api; - -/** - * - * @author Jaroslav Tulach - */ -public final class Input extends Element { - public Input(String id) { - super(id); - } - - @Override - void dontSubclass() { - } - - public void setAutocomplete(boolean state) { - Element.setAttribute(this, "autocomplete", state); - } - - public final String getValue() { - return (String)Element.getAttribute(this, "value"); - } -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnClick.java --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnClick.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.apidesign.bck2brwsr.htmlpage.api; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** Adds an onClick handler to an element identified by given id. - * Apply on a public static void method with no arguments. - * - * @author Jaroslav Tulach - */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.METHOD) -public @interface OnClick { - String id(); -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Page.java --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Page.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-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. - */ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.apidesign.bck2brwsr.htmlpage.api; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** Converts an XHTML page into a Java class that contains - * references to all IDs. - * - * @author Jaroslav Tulach - */ -@Retention(RetentionPolicy.SOURCE) -@Target(ElementType.TYPE) -public @interface Page { - /** Path to the XHTML page to read in */ - String xhtml(); - /** Name of a Java class to generate. It will contain constants for all - * found elements with IDs. - */ - String name(); -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Title.java --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Title.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-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.bck2brwsr.htmlpage.api; - -/** - * - * @author Jaroslav Tulach - */ -public class Title extends Element { - public Title(String id) { - super(id); - } - - @Override - void dontSubclass() { - } - - public final void setText(String text) { - Element.setAttribute(this, "innerHTML", text); - } -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java --- a/htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -package org.apidesign.bck2brwsr.htmlpage; - -import org.apidesign.bck2brwsr.htmlpage.api.OnClick; -import org.apidesign.bck2brwsr.htmlpage.api.Page; - -/** Trivial demo for the bck2brwsr project. First of all start - * with your XHTML page. Include there - * a script that will boot Java in your browser. - *

    - * Then use @Page annotation to - * generate a Java representation of elements with IDs in that page. - * Depending on the type of the elements, they will have different - * methods (e.g. PG_TITLE has setText, etc.). - * Use @OnClick annotation to associate behavior - * with existing elements. Use the generated elements - * (PG_TITLE, PG_TEXT) to modify the page. - *

    - * Everything is type-safe. As soon as somebody modifies the page and - * removes the IDs or re-assigns them to wrong elements. Java compiler - * will emit an error. - *

    - * Welcome to the type-safe HTML5 world! - * - * @author Jaroslav Tulach - */ -@Page(xhtml="TestPage.html", name="TestPage") -public class PageController { - @OnClick(id="pg.button") - static void updateTitle() { - TestPage.PG_TITLE.setText(TestPage.PG_TEXT.getValue()); - } -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java --- a/htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-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.bck2brwsr.htmlpage; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Method; -import java.util.Set; -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; -import org.testng.annotations.Test; -import static org.testng.Assert.*; - -public class ProcessPageTest { - - - @Test public void findsThreeIds() throws IOException { - InputStream is = ProcessPageTest.class.getResourceAsStream("TestPage.html"); - assertNotNull(is, "Sample HTML page found"); - ProcessPage res = ProcessPage.readPage(is); - final Set ids = res.ids(); - assertEquals(ids.size(), 3, "Three ids found: " + ids); - - assertEquals(res.tagNameForId("pg.title"), "title"); - assertEquals(res.tagNameForId("pg.button"), "button"); - assertEquals(res.tagNameForId("pg.text"), "input"); - } - - @Test public void testCompileAndRunPageController() throws Exception { - StringBuilder sb = new StringBuilder(); - sb.append( - "var window = new Object();\n" - + "var doc = new Object();\n" - + "doc.button = new Object();\n" - + "doc.title = new Object();\n" - + "doc.title.innerHTML = 'nothing';\n" - + "doc.text = new Object();\n" - + "doc.text.value = 'something';\n" - + "doc.getElementById = function(id) {\n" - + " switch(id) {\n" - + " case 'pg.button': return doc.button;\n" - + " case 'pg.title': return doc.title;\n" - + " case 'pg.text': return doc.text;\n" - + " }\n" - + " throw id;\n" - + " }\n" - + "\n" - + "function clickAndCheck() {\n" - + " doc.button.onclick();\n" - + " return doc.title.innerHTML.toString();\n" - + "};\n" - + "\n" - + "window.document = doc;\n" - ); - Invocable i = compileClass(sb, "org/apidesign/bck2brwsr/htmlpage/PageController"); - - Object ret = null; - try { - ret = i.invokeFunction("clickAndCheck"); - } catch (ScriptException ex) { - fail("Execution failed in " + sb, ex); - } catch (NoSuchMethodException ex) { - fail("Cannot find method in " + sb, ex); - } - assertEquals(ret, "something", "We expect that the JavaCode performs all the wiring"); - } - - static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException { - if (sb == null) { - sb = new StringBuilder(); - } - try { - Method m; - Class genJS = Class.forName("org.apidesign.vm4brwsr.GenJS"); - m = genJS.getDeclaredMethod("compile", Appendable.class, String[].class); - m.setAccessible(true); - m.invoke(null, sb, names); - } catch (Exception exception) { - throw new IOException(exception); - } - ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine js = sem.getEngineByExtension("js"); - try { - Object res = js.eval(sb.toString()); - assertTrue(js instanceof Invocable, "It is invocable object: " + res); - return (Invocable) js; - } catch (ScriptException ex) { - fail("Could not compile:\n" + sb, ex); - return null; - } - } -} diff -r 029e6eed60e9 -r 388e48c0a37a htmlpage/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html --- a/htmlpage/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - Default Title - - - New title: - - - diff -r 029e6eed60e9 -r 388e48c0a37a javap/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,41 @@ + + + 4.0.0 + + org.apidesign + bck2brwsr + 0.3-SNAPSHOT + + org.apidesign.bck2brwsr + javap + 0.3-SNAPSHOT + javap + http://maven.apache.org + + UTF-8 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + + + + 1.6 + 1.6 + + + + + + + org.apidesign.bck2brwsr + emul + 0.3-SNAPSHOT + + + diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/AnnotationParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.apidesign.javap; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; + +/** An abstract parser for annotation definitions. Analyses the bytes and + * performs some callbacks to the overriden parser methods. + * + * @author Jaroslav Tulach + */ +public class AnnotationParser { + private final boolean textual; + + protected AnnotationParser(boolean textual) { + this.textual = textual; + } + + protected void visitAnnotationStart(String type) throws IOException { + } + + protected void visitAnnotationEnd(String type) throws IOException { + } + + protected void visitAttr( + String annoType, String attr, String attrType, String value + ) throws IOException { + } + + /** Initialize the parsing with constant pool from cd. + * + * @param attr the attribute defining annotations + * @param cd constant pool + * @throws IOException in case I/O fails + */ + public final void parse(byte[] attr, ClassData cd) throws IOException { + ByteArrayInputStream is = new ByteArrayInputStream(attr); + DataInputStream dis = new DataInputStream(is); + try { + read(dis, cd); + } finally { + is.close(); + } + } + + private void read(DataInputStream dis, ClassData cd) throws IOException { + int cnt = dis.readUnsignedShort(); + for (int i = 0; i < cnt; i++) { + readAnno(dis, cd); + } + } + + private void readAnno(DataInputStream dis, ClassData cd) throws IOException { + int type = dis.readUnsignedShort(); + String typeName = cd.StringValue(type); + visitAnnotationStart(typeName); + int cnt = dis.readUnsignedShort(); + for (int i = 0; i < cnt; i++) { + String attrName = cd.StringValue(dis.readUnsignedShort()); + readValue(dis, cd, typeName, attrName); + } + visitAnnotationEnd(typeName); + if (cnt == 0) { + visitAttr(typeName, null, null, null); + } + } + + private void readValue(DataInputStream dis, ClassData cd, String typeName, String attrName) + throws IOException { + char type = (char)dis.readByte(); + if (type == '@') { + readAnno(dis, cd); + } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N + int primitive = dis.readUnsignedShort(); + String val = cd.stringValue(primitive, textual); + String attrType; + if (type == 's') { + attrType = "Ljava_lang_String_2"; + if (textual) { + val = '"' + val + '"'; + } + } else { + attrType = "" + type; + } + visitAttr(typeName, attrName, attrType, val); + } else if (type == 'c') { + int cls = dis.readUnsignedShort(); + } else if (type == '[') { + int cnt = dis.readUnsignedShort(); + for (int i = 0; i < cnt; i++) { + readValue(dis, cd, typeName, attrName); + } + } else if (type == 'e') { + int enumT = dis.readUnsignedShort(); + int enumN = dis.readUnsignedShort(); + } else { + throw new IOException("Unknown type " + type); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/AttrData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/AttrData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + + +package org.apidesign.javap; + +import java.io.*; + +/** + * Reads and stores attribute information. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ +class AttrData { + ClassData cls; + int name_cpx; + int datalen; + byte data[]; + + public AttrData (ClassData cls) { + this.cls=cls; + } + + /** + * Reads unknown attribute. + */ + public void read(int name_cpx, DataInputStream in) throws IOException { + this.name_cpx=name_cpx; + datalen=in.readInt(); + data=new byte[datalen]; + in.readFully(data); + } + + /** + * Reads just the name of known attribute. + */ + public void read(int name_cpx){ + this.name_cpx=name_cpx; + } + + /** + * Returns attribute name. + */ + public String getAttrName(){ + return cls.getString(name_cpx); + } + + /** + * Returns attribute data. + */ + public byte[] getData(){ + return data; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/CPX.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/CPX.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +/** + * Stores constant pool entry information with one field. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ +class CPX { + int cpx; + + CPX (int cpx) { + this.cpx=cpx; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/CPX2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/CPX2.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +/** + * Stores constant pool entry information with two fields. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ +class CPX2 { + int cpx1,cpx2; + + CPX2 (int cpx1, int cpx2) { + this.cpx1=cpx1; + this.cpx2=cpx2; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/ClassData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/ClassData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,713 @@ +/* + * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +import java.io.*; + +/** + * Central data repository of the Java Disassembler. + * Stores all the information in java class file. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ +public final class ClassData implements RuntimeConstants { + + private int magic; + private int minor_version; + private int major_version; + private int cpool_count; + private Object cpool[]; + private int access; + private int this_class = 0;; + private int super_class; + private int interfaces_count; + private int[] interfaces = new int[0];; + private int fields_count; + private FieldData[] fields; + private int methods_count; + private MethodData[] methods; + private InnerClassData[] innerClasses; + private int attributes_count; + private AttrData[] attrs; + private String classname; + private String superclassname; + private int source_cpx=0; + private byte tags[]; + private Hashtable indexHashAscii = new Hashtable(); + private String pkgPrefix=""; + private int pkgPrefixLen=0; + + /** + * Read classfile to disassemble. + */ + public ClassData(InputStream infile) throws IOException { + this.read(new DataInputStream(infile)); + } + + /** + * Reads and stores class file information. + */ + public void read(DataInputStream in) throws IOException { + // Read the header + magic = in.readInt(); + if (magic != JAVA_MAGIC) { + throw new ClassFormatError("wrong magic: " + + toHex(magic) + ", expected " + + toHex(JAVA_MAGIC)); + } + minor_version = in.readShort(); + major_version = in.readShort(); + if (major_version != JAVA_VERSION) { + } + + // Read the constant pool + readCP(in); + access = in.readUnsignedShort(); + this_class = in.readUnsignedShort(); + super_class = in.readUnsignedShort(); + + //Read interfaces. + interfaces_count = in.readUnsignedShort(); + if(interfaces_count > 0){ + interfaces = new int[interfaces_count]; + } + for (int i = 0; i < interfaces_count; i++) { + interfaces[i]=in.readShort(); + } + + // Read the fields + readFields(in); + + // Read the methods + readMethods(in); + + // Read the attributes + attributes_count = in.readUnsignedShort(); + attrs=new AttrData[attributes_count]; + for (int k = 0; k < attributes_count; k++) { + int name_cpx=in.readUnsignedShort(); + if (getTag(name_cpx)==CONSTANT_UTF8 + && getString(name_cpx).equals("SourceFile") + ){ if (in.readInt()!=2) + throw new ClassFormatError("invalid attr length"); + source_cpx=in.readUnsignedShort(); + AttrData attr=new AttrData(this); + attr.read(name_cpx); + attrs[k]=attr; + + } else if (getTag(name_cpx)==CONSTANT_UTF8 + && getString(name_cpx).equals("InnerClasses") + ){ int length=in.readInt(); + int num=in.readUnsignedShort(); + if (2+num*8 != length) + throw new ClassFormatError("invalid attr length"); + innerClasses=new InnerClassData[num]; + for (int j = 0; j < num; j++) { + InnerClassData innerClass=new InnerClassData(this); + innerClass.read(in); + innerClasses[j]=innerClass; + } + AttrData attr=new AttrData(this); + attr.read(name_cpx); + attrs[k]=attr; + } else { + AttrData attr=new AttrData(this); + attr.read(name_cpx, in); + attrs[k]=attr; + } + } + in.close(); + } // end ClassData.read() + + /** + * Reads and stores constant pool info. + */ + void readCP(DataInputStream in) throws IOException { + cpool_count = in.readUnsignedShort(); + tags = new byte[cpool_count]; + cpool = new Object[cpool_count]; + for (int i = 1; i < cpool_count; i++) { + byte tag = in.readByte(); + + switch(tags[i] = tag) { + case CONSTANT_UTF8: + String str=in.readUTF(); + indexHashAscii.put(cpool[i] = str, new Integer(i)); + break; + case CONSTANT_INTEGER: + cpool[i] = new Integer(in.readInt()); + break; + case CONSTANT_FLOAT: + cpool[i] = new Float(in.readFloat()); + break; + case CONSTANT_LONG: + cpool[i++] = new Long(in.readLong()); + break; + case CONSTANT_DOUBLE: + cpool[i++] = new Double(in.readDouble()); + break; + case CONSTANT_CLASS: + case CONSTANT_STRING: + cpool[i] = new CPX(in.readUnsignedShort()); + break; + + case CONSTANT_FIELD: + case CONSTANT_METHOD: + case CONSTANT_INTERFACEMETHOD: + case CONSTANT_NAMEANDTYPE: + cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort()); + break; + + case 0: + default: + throw new ClassFormatError("invalid constant type: " + (int)tags[i]); + } + } + } + + /** + * Reads and strores field info. + */ + protected void readFields(DataInputStream in) throws IOException { + int fields_count = in.readUnsignedShort(); + fields=new FieldData[fields_count]; + for (int k = 0; k < fields_count; k++) { + FieldData field=new FieldData(this); + field.read(in); + fields[k]=field; + } + } + + /** + * Reads and strores Method info. + */ + protected void readMethods(DataInputStream in) throws IOException { + int methods_count = in.readUnsignedShort(); + methods=new MethodData[methods_count]; + for (int k = 0; k < methods_count ; k++) { + MethodData method=new MethodData(this); + method.read(in); + methods[k]=method; + } + } + + /** + * get a string + */ + public String getString(int n) { + if (n == 0) { + return null; + } else { + return (String)cpool[n]; + } + } + + /** + * get the type of constant given an index + */ + public byte getTag(int n) { + try{ + return tags[n]; + } catch (ArrayIndexOutOfBoundsException e) { + return (byte)100; + } + } + + static final String hexString="0123456789ABCDEF"; + + public static char hexTable[]=hexString.toCharArray(); + + static String toHex(long val, int width) { + StringBuffer s = new StringBuffer(); + for (int i=width-1; i>=0; i--) + s.append(hexTable[((int)(val>>(4*i)))&0xF]); + return "0x"+s.toString(); + } + + static String toHex(long val) { + int width; + for (width=16; width>0; width--) { + if ((val>>(width-1)*4)!=0) break; + } + return toHex(val, width); + } + + static String toHex(int val) { + int width; + for (width=8; width>0; width--) { + if ((val>>(width-1)*4)!=0) break; + } + return toHex(val, width); + } + + /** + * Returns the name of this class. + */ + public String getClassName() { + String res=null; + if (this_class==0) { + return res; + } + int tcpx; + try { + if (tags[this_class]!=CONSTANT_CLASS) { + return res; //" "; + } + tcpx=((CPX)cpool[this_class]).cpx; + } catch (ArrayIndexOutOfBoundsException e) { + return res; // "#"+cpx+"// invalid constant pool index"; + } catch (Throwable e) { + return res; // "#"+cpx+"// ERROR IN DISASSEMBLER"; + } + + try { + return (String)(cpool[tcpx]); + } catch (ArrayIndexOutOfBoundsException e) { + return res; // "class #"+scpx+"// invalid constant pool index"; + } catch (ClassCastException e) { + return res; // "class #"+scpx+"// invalid constant pool reference"; + } catch (Throwable e) { + return res; // "#"+cpx+"// ERROR IN DISASSEMBLER"; + } + + } + + /** + * Returns the name of class at perticular index. + */ + public String getClassName(int cpx) { + String res="#"+cpx; + if (cpx==0) { + return res; + } + int scpx; + try { + if (tags[cpx]!=CONSTANT_CLASS) { + return res; //" "; + } + scpx=((CPX)cpool[cpx]).cpx; + } catch (ArrayIndexOutOfBoundsException e) { + return res; // "#"+cpx+"// invalid constant pool index"; + } catch (Throwable e) { + return res; // "#"+cpx+"// ERROR IN DISASSEMBLER"; + } + res="#"+scpx; + try { + return (String)(cpool[scpx]); + } catch (ArrayIndexOutOfBoundsException e) { + return res; // "class #"+scpx+"// invalid constant pool index"; + } catch (ClassCastException e) { + return res; // "class #"+scpx+"// invalid constant pool reference"; + } catch (Throwable e) { + return res; // "#"+cpx+"// ERROR IN DISASSEMBLER"; + } + } + + public int getAccessFlags() { + return access; + } + + /** + * Returns true if it is a class + */ + public boolean isClass() { + if((access & ACC_INTERFACE) == 0) return true; + return false; + } + + /** + * Returns true if it is a interface. + */ + public boolean isInterface(){ + if((access & ACC_INTERFACE) != 0) return true; + return false; + } + + /** + * Returns true if this member is public, false otherwise. + */ + public boolean isPublic(){ + return (access & ACC_PUBLIC) != 0; + } + + /** + * Returns the access of this class or interface. + */ + public String[] getAccess(){ + Vector v = new Vector(); + if ((access & ACC_PUBLIC) !=0) v.addElement("public"); + if ((access & ACC_FINAL) !=0) v.addElement("final"); + if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract"); + String[] accflags = new String[v.size()]; + v.copyInto(accflags); + return accflags; + } + + /** + * Returns list of innerclasses. + */ + public InnerClassData[] getInnerClasses(){ + return innerClasses; + } + + /** + * Returns list of attributes. + */ + final AttrData[] getAttributes(){ + return attrs; + } + + public byte[] findAnnotationData(boolean classRetention) { + String n = classRetention ? + "RuntimeInvisibleAnnotations" : // NOI18N + "RuntimeVisibleAnnotations"; // NOI18N + return findAttr(n, attrs); + } + + /** + * Returns true if superbit is set. + */ + public boolean isSuperSet(){ + if ((access & ACC_SUPER) !=0) return true; + return false; + } + + /** + * Returns super class name. + */ + public String getSuperClassName(){ + String res=null; + if (super_class==0) { + return res; + } + int scpx; + try { + if (tags[super_class]!=CONSTANT_CLASS) { + return res; //" "; + } + scpx=((CPX)cpool[super_class]).cpx; + } catch (ArrayIndexOutOfBoundsException e) { + return res; // "#"+cpx+"// invalid constant pool index"; + } catch (Throwable e) { + return res; // "#"+cpx+"// ERROR IN DISASSEMBLER"; + } + + try { + return (String)(cpool[scpx]); + } catch (ArrayIndexOutOfBoundsException e) { + return res; // "class #"+scpx+"// invalid constant pool index"; + } catch (ClassCastException e) { + return res; // "class #"+scpx+"// invalid constant pool reference"; + } catch (Throwable e) { + return res; // "#"+cpx+"// ERROR IN DISASSEMBLER"; + } + } + + /** + * Returns list of super interfaces. + */ + public String[] getSuperInterfaces(){ + String interfacenames[] = new String[interfaces.length]; + int interfacecpx = -1; + for(int i = 0; i < interfaces.length; i++){ + interfacecpx=((CPX)cpool[interfaces[i]]).cpx; + interfacenames[i] = (String)(cpool[interfacecpx]); + } + return interfacenames; + } + + /** + * Returns string at prticular constant pool index. + */ + public String getStringValue(int cpoolx) { + try { + return ((String)cpool[cpoolx]); + } catch (ArrayIndexOutOfBoundsException e) { + return "//invalid constant pool index:"+cpoolx; + } catch (ClassCastException e) { + return "//invalid constant pool ref:"+cpoolx; + } + } + + /** + * Returns list of field info. + */ + public FieldData[] getFields(){ + return fields; + } + + /** + * Returns list of method info. + */ + public MethodData[] getMethods(){ + return methods; + } + + /** + * Returns constant pool entry at that index. + */ + public CPX2 getCpoolEntry(int cpx){ + return ((CPX2)(cpool[cpx])); + } + + public Object getCpoolEntryobj(int cpx){ + return (cpool[cpx]); + } + + /** + * Returns index of this class. + */ + public int getthis_cpx(){ + return this_class; + } + + /** + * Returns string at that index. + */ + public String StringValue(int cpx) { + return stringValue(cpx, false); + } + public String stringValue(int cpx, boolean textual) { + return stringValue(cpx, textual, null); + } + public String stringValue(int cpx, String[] classRefs) { + return stringValue(cpx, true, classRefs); + } + private String stringValue(int cpx, boolean textual, String[] refs) { + if (cpx==0) return "#0"; + int tag; + Object x; + String suffix=""; + try { + tag=tags[cpx]; + x=cpool[cpx]; + } catch (IndexOutOfBoundsException e) { + return ""; + } + + if (x==null) return ""; + switch (tag) { + case CONSTANT_UTF8: { + if (!textual) { + return (String)x; + } + StringBuilder sb=new StringBuilder(); + String s=(String)x; + for (int k=0; k"; + } catch (ClassCastException e) { + return ""; + } + } + + /** + * Returns unqualified class name. + */ + public String getShortClassName(int cpx) { + String classname=javaName(getClassName(cpx)); + pkgPrefixLen=classname.lastIndexOf("/")+1; + if (pkgPrefixLen!=0) { + pkgPrefix=classname.substring(0,pkgPrefixLen); + if (classname.startsWith(pkgPrefix)) { + return classname.substring(pkgPrefixLen); + } + } + return classname; + } + + /** + * Returns source file name. + */ + public String getSourceName(){ + return getName(source_cpx); + } + + /** + * Returns package name. + */ + public String getPkgName(){ + String classname=getClassName(this_class); + pkgPrefixLen=classname.lastIndexOf("/")+1; + if (pkgPrefixLen!=0) { + pkgPrefix=classname.substring(0,pkgPrefixLen); + return("package "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n"); + }else return null; + } + + /** + * Returns total constant pool entry count. + */ + public int getCpoolCount(){ + return cpool_count; + } + + /** + * Returns minor version of class file. + */ + public int getMinor_version(){ + return minor_version; + } + + /** + * Returns major version of class file. + */ + public int getMajor_version(){ + return major_version; + } + + private boolean isJavaIdentifierStart(int cp) { + return ('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z'); + } + + private boolean isJavaIdentifierPart(int cp) { + return isJavaIdentifierStart(cp) || ('0' <= cp && cp <= '9'); + } + + public String[] getNameAndType(int indx) { + return getNameAndType(indx, 0, new String[2]); + } + + private String[] getNameAndType(int indx, int at, String[] arr) { + CPX2 c2 = getCpoolEntry(indx); + arr[at] = StringValue(c2.cpx1); + arr[at + 1] = StringValue(c2.cpx2); + return arr; + } + + public String[] getFieldInfoName(int indx) { + CPX2 c2 = getCpoolEntry(indx); + String[] arr = new String[3]; + arr[0] = getClassName(c2.cpx1); + return getNameAndType(c2.cpx2, 1, arr); + } + + static byte[] findAttr(String n, AttrData[] attrs) { + for (AttrData ad : attrs) { + if (n.equals(ad.getAttrName())) { + return ad.getData(); + } + } + return null; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/Constants.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/Constants.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + + +package org.apidesign.javap; + +/** + * This interface defines constant that are used + * throughout the compiler. It inherits from RuntimeConstants, + * which is an autogenerated class that contains contstants + * defined in the interpreter. + */ + +public +interface Constants extends RuntimeConstants { + + /** + * End of input + */ + public static final int EOF = -1; + + /* + * Flags + */ + public static final int F_VERBOSE = 1 << 0; + public static final int F_DUMP = 1 << 1; + public static final int F_WARNINGS = 1 << 2; + public static final int F_DEBUG = 1 << 3; + public static final int F_OPTIMIZE = 1 << 4; + public static final int F_DEPENDENCIES = 1 << 5; + + /* + * Type codes + */ + public static final int TC_BOOLEAN = 0; + public static final int TC_BYTE = 1; + public static final int TC_CHAR = 2; + public static final int TC_SHORT = 3; + public static final int TC_INT = 4; + public static final int TC_LONG = 5; + public static final int TC_FLOAT = 6; + public static final int TC_DOUBLE = 7; + public static final int TC_NULL = 8; + public static final int TC_ARRAY = 9; + public static final int TC_CLASS = 10; + public static final int TC_VOID = 11; + public static final int TC_METHOD = 12; + public static final int TC_ERROR = 13; + + /* + * Type Masks + */ + public static final int TM_NULL = 1 << TC_NULL; + public static final int TM_VOID = 1 << TC_VOID; + public static final int TM_BOOLEAN = 1 << TC_BOOLEAN; + public static final int TM_BYTE = 1 << TC_BYTE; + public static final int TM_CHAR = 1 << TC_CHAR; + public static final int TM_SHORT = 1 << TC_SHORT; + public static final int TM_INT = 1 << TC_INT; + public static final int TM_LONG = 1 << TC_LONG; + public static final int TM_FLOAT = 1 << TC_FLOAT; + public static final int TM_DOUBLE = 1 << TC_DOUBLE; + public static final int TM_ARRAY = 1 << TC_ARRAY; + public static final int TM_CLASS = 1 << TC_CLASS; + public static final int TM_METHOD = 1 << TC_METHOD; + public static final int TM_ERROR = 1 << TC_ERROR; + + public static final int TM_INT32 = TM_BYTE | TM_SHORT | TM_CHAR | TM_INT; + public static final int TM_NUM32 = TM_INT32 | TM_FLOAT; + public static final int TM_NUM64 = TM_LONG | TM_DOUBLE; + public static final int TM_INTEGER = TM_INT32 | TM_LONG; + public static final int TM_REAL = TM_FLOAT | TM_DOUBLE; + public static final int TM_NUMBER = TM_INTEGER | TM_REAL; + public static final int TM_REFERENCE = TM_ARRAY | TM_CLASS | TM_NULL; + + /* + * Class status + */ + public static final int CS_UNDEFINED = 0; + public static final int CS_UNDECIDED = 1; + public static final int CS_BINARY = 2; + public static final int CS_SOURCE = 3; + public static final int CS_PARSED = 4; + public static final int CS_COMPILED = 5; + public static final int CS_NOTFOUND = 6; + + /* + * Attributes + */ + public static final int ATT_ALL = -1; + public static final int ATT_CODE = 1; + + /* + * Number of bits used in file offsets + */ + public static final int OFFSETBITS = 19; + public static final int MAXFILESIZE = (1 << OFFSETBITS) - 1; + public static final int MAXLINENUMBER = (1 << (32 - OFFSETBITS)) - 1; + + /* + * Operators + */ + public final int COMMA = 0; + public final int ASSIGN = 1; + + public final int ASGMUL = 2; + public final int ASGDIV = 3; + public final int ASGREM = 4; + public final int ASGADD = 5; + public final int ASGSUB = 6; + public final int ASGLSHIFT = 7; + public final int ASGRSHIFT = 8; + public final int ASGURSHIFT = 9; + public final int ASGBITAND = 10; + public final int ASGBITOR = 11; + public final int ASGBITXOR = 12; + + public final int COND = 13; + public final int OR = 14; + public final int AND = 15; + public final int BITOR = 16; + public final int BITXOR = 17; + public final int BITAND = 18; + public final int NE = 19; + public final int EQ = 20; + public final int GE = 21; + public final int GT = 22; + public final int LE = 23; + public final int LT = 24; + public final int INSTANCEOF = 25; + public final int LSHIFT = 26; + public final int RSHIFT = 27; + public final int URSHIFT = 28; + public final int ADD = 29; + public final int SUB = 30; + public final int DIV = 31; + public final int REM = 32; + public final int MUL = 33; + public final int CAST = 34; // (x)y + public final int POS = 35; // +x + public final int NEG = 36; // -x + public final int NOT = 37; + public final int BITNOT = 38; + public final int PREINC = 39; // ++x + public final int PREDEC = 40; // --x + public final int NEWARRAY = 41; + public final int NEWINSTANCE = 42; + public final int NEWFROMNAME = 43; + public final int POSTINC = 44; // x++ + public final int POSTDEC = 45; // x-- + public final int FIELD = 46; + public final int METHOD = 47; // x(y) + public final int ARRAYACCESS = 48; // x[y] + public final int NEW = 49; + public final int INC = 50; + public final int DEC = 51; + + public final int CONVERT = 55; // implicit conversion + public final int EXPR = 56; // (x) + public final int ARRAY = 57; // {x, y, ...} + public final int GOTO = 58; + + /* + * Value tokens + */ + public final int IDENT = 60; + public final int BOOLEANVAL = 61; + public final int BYTEVAL = 62; + public final int CHARVAL = 63; + public final int SHORTVAL = 64; + public final int INTVAL = 65; + public final int LONGVAL = 66; + public final int FLOATVAL = 67; + public final int DOUBLEVAL = 68; + public final int STRINGVAL = 69; + + /* + * Type keywords + */ + public final int BYTE = 70; + public final int CHAR = 71; + public final int SHORT = 72; + public final int INT = 73; + public final int LONG = 74; + public final int FLOAT = 75; + public final int DOUBLE = 76; + public final int VOID = 77; + public final int BOOLEAN = 78; + + /* + * Expression keywords + */ + public final int TRUE = 80; + public final int FALSE = 81; + public final int THIS = 82; + public final int SUPER = 83; + public final int NULL = 84; + + /* + * Statement keywords + */ + public final int IF = 90; + public final int ELSE = 91; + public final int FOR = 92; + public final int WHILE = 93; + public final int DO = 94; + public final int SWITCH = 95; + public final int CASE = 96; + public final int DEFAULT = 97; + public final int BREAK = 98; + public final int CONTINUE = 99; + public final int RETURN = 100; + public final int TRY = 101; + public final int CATCH = 102; + public final int FINALLY = 103; + public final int THROW = 104; + public final int STAT = 105; + public final int EXPRESSION = 106; + public final int DECLARATION = 107; + public final int VARDECLARATION = 108; + + /* + * Declaration keywords + */ + public final int IMPORT = 110; + public final int CLASS = 111; + public final int EXTENDS = 112; + public final int IMPLEMENTS = 113; + public final int INTERFACE = 114; + public final int PACKAGE = 115; + + /* + * Modifier keywords + */ + public final int PRIVATE = 120; + public final int PUBLIC = 121; + public final int PROTECTED = 122; + public final int CONST = 123; + public final int STATIC = 124; + public final int TRANSIENT = 125; + public final int SYNCHRONIZED = 126; + public final int NATIVE = 127; + public final int FINAL = 128; + public final int VOLATILE = 129; + public final int ABSTRACT = 130; + public final int STRICT = 165; + + /* + * Punctuation + */ + public final int SEMICOLON = 135; + public final int COLON = 136; + public final int QUESTIONMARK = 137; + public final int LBRACE = 138; + public final int RBRACE = 139; + public final int LPAREN = 140; + public final int RPAREN = 141; + public final int LSQBRACKET = 142; + public final int RSQBRACKET = 143; + public final int THROWS = 144; + + /* + * Special tokens + */ + public final int ERROR = 145; // an error + public final int COMMENT = 146; // not used anymore. + public final int TYPE = 147; + public final int LENGTH = 148; + public final int INLINERETURN = 149; + public final int INLINEMETHOD = 150; + public final int INLINENEWINSTANCE = 151; + + /* + * Added for jasm + */ + public final int METHODREF = 152; + public final int FIELDREF = 153; + public final int STACK = 154; + public final int LOCAL = 155; + public final int CPINDEX = 156; + public final int CPNAME = 157; + public final int SIGN = 158; + public final int BITS = 159; + public final int INF = 160; + public final int NAN = 161; + public final int INNERCLASS = 162; + public final int OF = 163; + public final int SYNTHETIC = 164; +// last used=165; + + /* + * Operator precedence + */ + public static final int opPrecedence[] = { + 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 12, 13, 14, 15, 16, 17, 18, + 18, 19, 19, 19, 19, 19, 20, 20, 20, 21, + 21, 22, 22, 22, 23, 24, 24, 24, 24, 24, + 24, 25, 25, 26, 26, 26, 26, 26, 26 + }; + + /* + * Operator names + */ + public static final String opNames[] = { + ",", "=", "*=", "/=", "%=", + "+=", "-=", "<<=", ">>=", "<<<=", + "&=", "|=", "^=", "?:", "||", + "&&", "|", "^", "&", "!=", + "==", ">=", ">", "<=", "<", + "instanceof", "<<", ">>", "<<<", "+", + "-", "/", "%", "*", "cast", + "+", "-", "!", "~", "++", + "--", "new", "new", "new", "++", + "--", "field", "method", "[]", "new", + "++", "--", null, null, null, + + "convert", "expr", "array", "goto", null, + + "Identifier", "Boolean", "Byte", "Char", "Short", + "Integer", "Long", "Float", "Double", "String", + + "byte", "char", "short", "int", "long", + "float", "double", "void", "boolean", null, + + "true", "false", "this", "super", "null", + null, null, null, null, null, + + "if", "else", "for", "while", "do", + "switch", "case", "default", "break", "continue", + "return", "try", "catch", "finally", "throw", + "stat", "expression", "declaration", "declaration", null, + + "import", "class", "extends", "implements", "interface", + "package", null, null, null, null, + + "private", "public", "protected", "const", "static", + "transient", "synchronized", "native", "final", "volatile", + "abstract", null, null, null, null, + + ";", ":", "?", "{", "}", + "(", ")", "[", "]", "throws", + "error", "comment", "type", "length", "inline-return", + "inline-method", "inline-new", + "method", "field", "stack", "locals", "CPINDEX", "CPName", "SIGN", + "bits", "INF", "NaN", "InnerClass", "of", "synthetic" + }; + +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/FieldData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/FieldData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +import java.io.*; + +/** + * Strores field data informastion. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ + +public class FieldData implements RuntimeConstants { + + ClassData cls; + int access; + int name_index; + int descriptor_index; + int attributes_count; + int value_cpx=0; + boolean isSynthetic=false; + boolean isDeprecated=false; + Vector attrs; + + public FieldData(ClassData cls){ + this.cls=cls; + } + + /** + * Read and store field info. + */ + public void read(DataInputStream in) throws IOException { + access = in.readUnsignedShort(); + name_index = in.readUnsignedShort(); + descriptor_index = in.readUnsignedShort(); + // Read the attributes + int attributes_count = in.readUnsignedShort(); + attrs=new Vector(attributes_count); + for (int i = 0; i < attributes_count; i++) { + int attr_name_index=in.readUnsignedShort(); + if (cls.getTag(attr_name_index)!=CONSTANT_UTF8) continue; + String attr_name=cls.getString(attr_name_index); + if (attr_name.equals("ConstantValue")){ + if (in.readInt()!=2) + throw new ClassFormatError("invalid ConstantValue attr length"); + value_cpx=in.readUnsignedShort(); + AttrData attr=new AttrData(cls); + attr.read(attr_name_index); + attrs.addElement(attr); + } else if (attr_name.equals("Synthetic")){ + if (in.readInt()!=0) + throw new ClassFormatError("invalid Synthetic attr length"); + isSynthetic=true; + AttrData attr=new AttrData(cls); + attr.read(attr_name_index); + attrs.addElement(attr); + } else if (attr_name.equals("Deprecated")){ + if (in.readInt()!=0) + throw new ClassFormatError("invalid Synthetic attr length"); + isDeprecated = true; + AttrData attr=new AttrData(cls); + attr.read(attr_name_index); + attrs.addElement(attr); + } else { + AttrData attr=new AttrData(cls); + attr.read(attr_name_index, in); + attrs.addElement(attr); + } + } + + } // end read + + public boolean isStatic() { + return (access & ACC_STATIC) != 0; + } + + /** + * Returns access of a field. + */ + public String[] getAccess(){ + Vector v = new Vector(); + if ((access & ACC_PUBLIC) !=0) v.addElement("public"); + if ((access & ACC_PRIVATE) !=0) v.addElement("private"); + if ((access & ACC_PROTECTED) !=0) v.addElement("protected"); + if ((access & ACC_STATIC) !=0) v.addElement("static"); + if ((access & ACC_FINAL) !=0) v.addElement("final"); + if ((access & ACC_VOLATILE) !=0) v.addElement("volatile"); + if ((access & ACC_TRANSIENT) !=0) v.addElement("transient"); + String[] accflags = new String[v.size()]; + v.copyInto(accflags); + return accflags; + } + + /** + * Returns name of a field. + */ + public String getName(){ + return cls.getStringValue(name_index); + } + + /** + * Returns internal signature of a field + */ + public String getInternalSig(){ + return cls.getStringValue(descriptor_index); + } + + /** + * Returns true if field is synthetic. + */ + public boolean isSynthetic(){ + return isSynthetic; + } + + /** + * Returns true if field is deprecated. + */ + public boolean isDeprecated(){ + return isDeprecated; + } + + /** + * Returns index of constant value in cpool. + */ + public int getConstantValueIndex(){ + return (value_cpx); + } + + /** + * Returns list of attributes of field. + */ + public Vector getAttributes(){ + return attrs; + } + + public byte[] findAnnotationData(boolean classRetention) { + String n = classRetention ? + "RuntimeInvisibleAnnotations" : // NOI18N + "RuntimeVisibleAnnotations"; // NOI18N + AttrData[] arr = new AttrData[attrs.size()]; + attrs.copyInto(arr); + return ClassData.findAttr(n, arr); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/Hashtable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/Hashtable.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,94 @@ +/** + * 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.javap; + +/** A JavaScript optimized replacement for Hashtable. + * + * @author Jaroslav Tulach + */ +final class Hashtable { + private Object[] keys; + private Object[] values; + + Hashtable(int i) { + this(); + } + + Hashtable(int i, double d) { + this(); + } + + Hashtable() { + } + + synchronized void put(Object key, Object val) { + int[] where = { -1, -1 }; + Object found = get(key, where); + if (where[0] != -1) { + // key exists + values[where[0]] = val; + } else { + if (where[1] != -1) { + // null found + keys[where[1]] = key; + values[where[1]] = val; + } else { + if (keys == null) { + keys = new Object[11]; + values = new Object[11]; + keys[0] = key; + values[0] = val; + } else { + Object[] newKeys = new Object[keys.length * 2]; + Object[] newValues = new Object[values.length * 2]; + for (int i = 0; i < keys.length; i++) { + newKeys[i] = keys[i]; + newValues[i] = values[i]; + } + newKeys[keys.length] = key; + newValues[keys.length] = val; + keys = newKeys; + values = newValues; + } + } + } + } + + Object get(Object key) { + return get(key, null); + } + private synchronized Object get(Object key, int[] foundAndNull) { + if (keys == null) { + return null; + } + for (int i = 0; i < keys.length; i++) { + if (keys[i] == null) { + if (foundAndNull != null) { + foundAndNull[1] = i; + } + } else if (keys[i].equals(key)) { + if (foundAndNull != null) { + foundAndNull[0] = i; + } + return values[i]; + } + } + return null; + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/InnerClassData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/InnerClassData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +import java.io.*; +import java.util.*; + +/** + * Strores InnerClass data informastion. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ +class InnerClassData implements RuntimeConstants { + ClassData cls; + + + int inner_class_info_index + ,outer_class_info_index + ,inner_name_index + ,access + ; + + public InnerClassData(ClassData cls) { + this.cls=cls; + + } + + /** + * Read Innerclass attribute data. + */ + public void read(DataInputStream in) throws IOException { + inner_class_info_index = in.readUnsignedShort(); + outer_class_info_index = in.readUnsignedShort(); + inner_name_index = in.readUnsignedShort(); + access = in.readUnsignedShort(); + } // end read + + /** + * Returns the access of this class or interface. + */ + public String[] getAccess(){ + Vector v = new Vector(); + if ((access & ACC_PUBLIC) !=0) v.addElement("public"); + if ((access & ACC_FINAL) !=0) v.addElement("final"); + if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract"); + String[] accflags = new String[v.size()]; + v.copyInto(accflags); + return accflags; + } + +} // end InnerClassData diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/LineNumData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/LineNumData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +import java.util.*; +import java.io.*; + +/** + * Strores LineNumberTable data information. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ +class LineNumData { + short start_pc, line_number; + + public LineNumData() {} + + /** + * Read LineNumberTable attribute. + */ + public LineNumData(DataInputStream in) throws IOException { + start_pc = in.readShort(); + line_number=in.readShort(); + + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/LocVarData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/LocVarData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +import java.util.*; +import java.io.*; + +/** + * Strores LocalVariableTable data information. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ +class LocVarData { + short start_pc, length, name_cpx, sig_cpx, slot; + + public LocVarData() { + } + + /** + * Read LocalVariableTable attribute. + */ + public LocVarData(DataInputStream in) throws IOException { + start_pc = in.readShort(); + length=in.readShort(); + name_cpx=in.readShort(); + sig_cpx=in.readShort(); + slot=in.readShort(); + + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/MethodData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/MethodData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.apidesign.javap; + + +import java.io.DataInputStream; +import java.io.IOException; +import static org.apidesign.javap.RuntimeConstants.*; + +/** + * Strores method data informastion. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ +public class MethodData { + + ClassData cls; + int access; + int name_index; + int descriptor_index; + int attributes_count; + byte[] code; + Vector exception_table = new Vector(0); + Vector lin_num_tb = new Vector(0); + Vector loc_var_tb = new Vector(0); + StackMapTableData[] stackMapTable; + StackMapData[] stackMap; + int[] exc_index_table=null; + Vector attrs=new Vector(0); + Vector code_attrs=new Vector(0); + int max_stack, max_locals; + boolean isSynthetic=false; + boolean isDeprecated=false; + + public MethodData(ClassData cls){ + this.cls=cls; + } + + /** + * Read method info. + */ + public void read(DataInputStream in) throws IOException { + access = in.readUnsignedShort(); + name_index=in.readUnsignedShort(); + descriptor_index =in.readUnsignedShort(); + int attributes_count = in.readUnsignedShort(); + for (int i = 0; i < attributes_count; i++) { + int attr_name_index=in.readUnsignedShort(); + + readAttr: { + if (cls.getTag(attr_name_index)==CONSTANT_UTF8) { + String attr_name=cls.getString(attr_name_index); + if ( attr_name.equals("Code")){ + readCode (in); + AttrData attr=new AttrData(cls); + attr.read(attr_name_index); + attrs.addElement(attr); + break readAttr; + } else if ( attr_name.equals("Exceptions")){ + readExceptions(in); + AttrData attr=new AttrData(cls); + attr.read(attr_name_index); + attrs.addElement(attr); + break readAttr; + } else if (attr_name.equals("Synthetic")){ + if (in.readInt()!=0) + throw new ClassFormatError("invalid Synthetic attr length"); + isSynthetic=true; + AttrData attr=new AttrData(cls); + attr.read(attr_name_index); + attrs.addElement(attr); + break readAttr; + } else if (attr_name.equals("Deprecated")){ + if (in.readInt()!=0) + throw new ClassFormatError("invalid Synthetic attr length"); + isDeprecated = true; + AttrData attr=new AttrData(cls); + attr.read(attr_name_index); + attrs.addElement(attr); + break readAttr; + } + } + AttrData attr=new AttrData(cls); + attr.read(attr_name_index, in); + attrs.addElement(attr); + } + } + } + + /** + * Read code attribute info. + */ + public void readCode(DataInputStream in) throws IOException { + + int attr_length = in.readInt(); + max_stack=in.readUnsignedShort(); + max_locals=in.readUnsignedShort(); + int codelen=in.readInt(); + + code=new byte[codelen]; + int totalread = 0; + while(totalread < codelen){ + totalread += in.read(code, totalread, codelen-totalread); + } + // in.read(code, 0, codelen); + int clen = 0; + readExceptionTable(in); + int code_attributes_count = in.readUnsignedShort(); + + for (int k = 0 ; k < code_attributes_count ; k++) { + int table_name_index=in.readUnsignedShort(); + int table_name_tag=cls.getTag(table_name_index); + AttrData attr=new AttrData(cls); + if (table_name_tag==CONSTANT_UTF8) { + String table_name_tstr=cls.getString(table_name_index); + if (table_name_tstr.equals("LineNumberTable")) { + readLineNumTable(in); + attr.read(table_name_index); + } else if (table_name_tstr.equals("LocalVariableTable")) { + readLocVarTable(in); + attr.read(table_name_index); + } else if (table_name_tstr.equals("StackMapTable")) { + readStackMapTable(in); + attr.read(table_name_index); + } else if (table_name_tstr.equals("StackMap")) { + readStackMap(in); + attr.read(table_name_index); + } else { + attr.read(table_name_index, in); + } + code_attrs.addElement(attr); + continue; + } + + attr.read(table_name_index, in); + code_attrs.addElement(attr); + } + } + + /** + * Read exception table info. + */ + void readExceptionTable (DataInputStream in) throws IOException { + int exception_table_len=in.readUnsignedShort(); + exception_table=new Vector(exception_table_len); + for (int l = 0; l < exception_table_len; l++) { + exception_table.addElement(new TrapData(in, l)); + } + } + + /** + * Read LineNumberTable attribute info. + */ + void readLineNumTable (DataInputStream in) throws IOException { + int attr_len = in.readInt(); // attr_length + int lin_num_tb_len = in.readUnsignedShort(); + lin_num_tb=new Vector(lin_num_tb_len); + for (int l = 0; l < lin_num_tb_len; l++) { + lin_num_tb.addElement(new LineNumData(in)); + } + } + + /** + * Read LocalVariableTable attribute info. + */ + void readLocVarTable (DataInputStream in) throws IOException { + int attr_len=in.readInt(); // attr_length + int loc_var_tb_len = in.readUnsignedShort(); + loc_var_tb = new Vector(loc_var_tb_len); + for (int l = 0; l < loc_var_tb_len; l++) { + loc_var_tb.addElement(new LocVarData(in)); + } + } + + /** + * Read Exception attribute info. + */ + public void readExceptions(DataInputStream in) throws IOException { + int attr_len=in.readInt(); // attr_length in prog + int num_exceptions = in.readUnsignedShort(); + exc_index_table=new int[num_exceptions]; + for (int l = 0; l < num_exceptions; l++) { + int exc=in.readShort(); + exc_index_table[l]=exc; + } + } + + /** + * Read StackMapTable attribute info. + */ + void readStackMapTable(DataInputStream in) throws IOException { + int attr_len = in.readInt(); //attr_length + int stack_map_tb_len = in.readUnsignedShort(); + stackMapTable = new StackMapTableData[stack_map_tb_len]; + for (int i=0; i".equals(getName()); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/RuntimeConstants.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/RuntimeConstants.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,787 @@ +/* + * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +public interface RuntimeConstants { + + /* Signature Characters */ + public static final char SIGC_VOID = 'V'; + public static final String SIG_VOID = "V"; + public static final char SIGC_BOOLEAN = 'Z'; + public static final String SIG_BOOLEAN = "Z"; + public static final char SIGC_BYTE = 'B'; + public static final String SIG_BYTE = "B"; + public static final char SIGC_CHAR = 'C'; + public static final String SIG_CHAR = "C"; + public static final char SIGC_SHORT = 'S'; + public static final String SIG_SHORT = "S"; + public static final char SIGC_INT = 'I'; + public static final String SIG_INT = "I"; + public static final char SIGC_LONG = 'J'; + public static final String SIG_LONG = "J"; + public static final char SIGC_FLOAT = 'F'; + public static final String SIG_FLOAT = "F"; + public static final char SIGC_DOUBLE = 'D'; + public static final String SIG_DOUBLE = "D"; + public static final char SIGC_ARRAY = '['; + public static final String SIG_ARRAY = "["; + public static final char SIGC_CLASS = 'L'; + public static final String SIG_CLASS = "L"; + public static final char SIGC_METHOD = '('; + public static final String SIG_METHOD = "("; + public static final char SIGC_ENDCLASS = ';'; + public static final String SIG_ENDCLASS = ";"; + public static final char SIGC_ENDMETHOD = ')'; + public static final String SIG_ENDMETHOD = ")"; + public static final char SIGC_PACKAGE = '/'; + public static final String SIG_PACKAGE = "/"; + + /* Class File Constants */ + public static final int JAVA_MAGIC = 0xcafebabe; + public static final int JAVA_VERSION = 45; + public static final int JAVA_MINOR_VERSION = 3; + + /* Constant table */ + public static final int CONSTANT_UTF8 = 1; + public static final int CONSTANT_UNICODE = 2; + public static final int CONSTANT_INTEGER = 3; + public static final int CONSTANT_FLOAT = 4; + public static final int CONSTANT_LONG = 5; + public static final int CONSTANT_DOUBLE = 6; + public static final int CONSTANT_CLASS = 7; + public static final int CONSTANT_STRING = 8; + public static final int CONSTANT_FIELD = 9; + public static final int CONSTANT_METHOD = 10; + public static final int CONSTANT_INTERFACEMETHOD = 11; + public static final int CONSTANT_NAMEANDTYPE = 12; + + /* Access Flags */ + public static final int ACC_PUBLIC = 0x00000001; + public static final int ACC_PRIVATE = 0x00000002; + public static final int ACC_PROTECTED = 0x00000004; + public static final int ACC_STATIC = 0x00000008; + public static final int ACC_FINAL = 0x00000010; + public static final int ACC_SYNCHRONIZED = 0x00000020; + public static final int ACC_SUPER = 0x00000020; + public static final int ACC_VOLATILE = 0x00000040; + public static final int ACC_TRANSIENT = 0x00000080; + public static final int ACC_NATIVE = 0x00000100; + public static final int ACC_INTERFACE = 0x00000200; + public static final int ACC_ABSTRACT = 0x00000400; + public static final int ACC_STRICT = 0x00000800; + public static final int ACC_EXPLICIT = 0x00001000; + public static final int ACC_SYNTHETIC = 0x00010000; // actually, this is an attribute + + /* Type codes */ + public static final int T_CLASS = 0x00000002; + public static final int T_BOOLEAN = 0x00000004; + public static final int T_CHAR = 0x00000005; + public static final int T_FLOAT = 0x00000006; + public static final int T_DOUBLE = 0x00000007; + public static final int T_BYTE = 0x00000008; + public static final int T_SHORT = 0x00000009; + public static final int T_INT = 0x0000000a; + public static final int T_LONG = 0x0000000b; + + /* Type codes for StackMap attribute */ + public static final int ITEM_Bogus =0; // an unknown or uninitialized value + public static final int ITEM_Integer =1; // a 32-bit integer + public static final int ITEM_Float =2; // not used + public static final int ITEM_Double =3; // not used + public static final int ITEM_Long =4; // a 64-bit integer + public static final int ITEM_Null =5; // the type of null + public static final int ITEM_InitObject =6; // "this" in constructor + public static final int ITEM_Object =7; // followed by 2-byte index of class name + public static final int ITEM_NewObject =8; // followed by 2-byte ref to "new" + + /* Constants used in StackMapTable attribute */ + public static final int SAME_FRAME_BOUND = 64; + public static final int SAME_LOCALS_1_STACK_ITEM_BOUND = 128; + public static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247; + public static final int SAME_FRAME_EXTENDED = 251; + public static final int FULL_FRAME = 255; + + /* Opcodes */ + public static final int opc_dead = -2; + public static final int opc_label = -1; + public static final int opc_nop = 0; + public static final int opc_aconst_null = 1; + public static final int opc_iconst_m1 = 2; + public static final int opc_iconst_0 = 3; + public static final int opc_iconst_1 = 4; + public static final int opc_iconst_2 = 5; + public static final int opc_iconst_3 = 6; + public static final int opc_iconst_4 = 7; + public static final int opc_iconst_5 = 8; + public static final int opc_lconst_0 = 9; + public static final int opc_lconst_1 = 10; + public static final int opc_fconst_0 = 11; + public static final int opc_fconst_1 = 12; + public static final int opc_fconst_2 = 13; + public static final int opc_dconst_0 = 14; + public static final int opc_dconst_1 = 15; + public static final int opc_bipush = 16; + public static final int opc_sipush = 17; + public static final int opc_ldc = 18; + public static final int opc_ldc_w = 19; + public static final int opc_ldc2_w = 20; + public static final int opc_iload = 21; + public static final int opc_lload = 22; + public static final int opc_fload = 23; + public static final int opc_dload = 24; + public static final int opc_aload = 25; + public static final int opc_iload_0 = 26; + public static final int opc_iload_1 = 27; + public static final int opc_iload_2 = 28; + public static final int opc_iload_3 = 29; + public static final int opc_lload_0 = 30; + public static final int opc_lload_1 = 31; + public static final int opc_lload_2 = 32; + public static final int opc_lload_3 = 33; + public static final int opc_fload_0 = 34; + public static final int opc_fload_1 = 35; + public static final int opc_fload_2 = 36; + public static final int opc_fload_3 = 37; + public static final int opc_dload_0 = 38; + public static final int opc_dload_1 = 39; + public static final int opc_dload_2 = 40; + public static final int opc_dload_3 = 41; + public static final int opc_aload_0 = 42; + public static final int opc_aload_1 = 43; + public static final int opc_aload_2 = 44; + public static final int opc_aload_3 = 45; + public static final int opc_iaload = 46; + public static final int opc_laload = 47; + public static final int opc_faload = 48; + public static final int opc_daload = 49; + public static final int opc_aaload = 50; + public static final int opc_baload = 51; + public static final int opc_caload = 52; + public static final int opc_saload = 53; + public static final int opc_istore = 54; + public static final int opc_lstore = 55; + public static final int opc_fstore = 56; + public static final int opc_dstore = 57; + public static final int opc_astore = 58; + public static final int opc_istore_0 = 59; + public static final int opc_istore_1 = 60; + public static final int opc_istore_2 = 61; + public static final int opc_istore_3 = 62; + public static final int opc_lstore_0 = 63; + public static final int opc_lstore_1 = 64; + public static final int opc_lstore_2 = 65; + public static final int opc_lstore_3 = 66; + public static final int opc_fstore_0 = 67; + public static final int opc_fstore_1 = 68; + public static final int opc_fstore_2 = 69; + public static final int opc_fstore_3 = 70; + public static final int opc_dstore_0 = 71; + public static final int opc_dstore_1 = 72; + public static final int opc_dstore_2 = 73; + public static final int opc_dstore_3 = 74; + public static final int opc_astore_0 = 75; + public static final int opc_astore_1 = 76; + public static final int opc_astore_2 = 77; + public static final int opc_astore_3 = 78; + public static final int opc_iastore = 79; + public static final int opc_lastore = 80; + public static final int opc_fastore = 81; + public static final int opc_dastore = 82; + public static final int opc_aastore = 83; + public static final int opc_bastore = 84; + public static final int opc_castore = 85; + public static final int opc_sastore = 86; + public static final int opc_pop = 87; + public static final int opc_pop2 = 88; + public static final int opc_dup = 89; + public static final int opc_dup_x1 = 90; + public static final int opc_dup_x2 = 91; + public static final int opc_dup2 = 92; + public static final int opc_dup2_x1 = 93; + public static final int opc_dup2_x2 = 94; + public static final int opc_swap = 95; + public static final int opc_iadd = 96; + public static final int opc_ladd = 97; + public static final int opc_fadd = 98; + public static final int opc_dadd = 99; + public static final int opc_isub = 100; + public static final int opc_lsub = 101; + public static final int opc_fsub = 102; + public static final int opc_dsub = 103; + public static final int opc_imul = 104; + public static final int opc_lmul = 105; + public static final int opc_fmul = 106; + public static final int opc_dmul = 107; + public static final int opc_idiv = 108; + public static final int opc_ldiv = 109; + public static final int opc_fdiv = 110; + public static final int opc_ddiv = 111; + public static final int opc_irem = 112; + public static final int opc_lrem = 113; + public static final int opc_frem = 114; + public static final int opc_drem = 115; + public static final int opc_ineg = 116; + public static final int opc_lneg = 117; + public static final int opc_fneg = 118; + public static final int opc_dneg = 119; + public static final int opc_ishl = 120; + public static final int opc_lshl = 121; + public static final int opc_ishr = 122; + public static final int opc_lshr = 123; + public static final int opc_iushr = 124; + public static final int opc_lushr = 125; + public static final int opc_iand = 126; + public static final int opc_land = 127; + public static final int opc_ior = 128; + public static final int opc_lor = 129; + public static final int opc_ixor = 130; + public static final int opc_lxor = 131; + public static final int opc_iinc = 132; + public static final int opc_i2l = 133; + public static final int opc_i2f = 134; + public static final int opc_i2d = 135; + public static final int opc_l2i = 136; + public static final int opc_l2f = 137; + public static final int opc_l2d = 138; + public static final int opc_f2i = 139; + public static final int opc_f2l = 140; + public static final int opc_f2d = 141; + public static final int opc_d2i = 142; + public static final int opc_d2l = 143; + public static final int opc_d2f = 144; + public static final int opc_i2b = 145; + public static final int opc_int2byte = 145; + public static final int opc_i2c = 146; + public static final int opc_int2char = 146; + public static final int opc_i2s = 147; + public static final int opc_int2short = 147; + public static final int opc_lcmp = 148; + public static final int opc_fcmpl = 149; + public static final int opc_fcmpg = 150; + public static final int opc_dcmpl = 151; + public static final int opc_dcmpg = 152; + public static final int opc_ifeq = 153; + public static final int opc_ifne = 154; + public static final int opc_iflt = 155; + public static final int opc_ifge = 156; + public static final int opc_ifgt = 157; + public static final int opc_ifle = 158; + public static final int opc_if_icmpeq = 159; + public static final int opc_if_icmpne = 160; + public static final int opc_if_icmplt = 161; + public static final int opc_if_icmpge = 162; + public static final int opc_if_icmpgt = 163; + public static final int opc_if_icmple = 164; + public static final int opc_if_acmpeq = 165; + public static final int opc_if_acmpne = 166; + public static final int opc_goto = 167; + public static final int opc_jsr = 168; + public static final int opc_ret = 169; + public static final int opc_tableswitch = 170; + public static final int opc_lookupswitch = 171; + public static final int opc_ireturn = 172; + public static final int opc_lreturn = 173; + public static final int opc_freturn = 174; + public static final int opc_dreturn = 175; + public static final int opc_areturn = 176; + public static final int opc_return = 177; + public static final int opc_getstatic = 178; + public static final int opc_putstatic = 179; + public static final int opc_getfield = 180; + public static final int opc_putfield = 181; + public static final int opc_invokevirtual = 182; + public static final int opc_invokenonvirtual = 183; + public static final int opc_invokespecial = 183; + public static final int opc_invokestatic = 184; + public static final int opc_invokeinterface = 185; +// public static final int opc_xxxunusedxxx = 186; + public static final int opc_new = 187; + public static final int opc_newarray = 188; + public static final int opc_anewarray = 189; + public static final int opc_arraylength = 190; + public static final int opc_athrow = 191; + public static final int opc_checkcast = 192; + public static final int opc_instanceof = 193; + public static final int opc_monitorenter = 194; + public static final int opc_monitorexit = 195; + public static final int opc_wide = 196; + public static final int opc_multianewarray = 197; + public static final int opc_ifnull = 198; + public static final int opc_ifnonnull = 199; + public static final int opc_goto_w = 200; + public static final int opc_jsr_w = 201; + /* Pseudo-instructions */ + public static final int opc_bytecode = 203; + public static final int opc_try = 204; + public static final int opc_endtry = 205; + public static final int opc_catch = 206; + public static final int opc_var = 207; + public static final int opc_endvar = 208; + public static final int opc_localsmap = 209; + public static final int opc_stackmap = 210; + /* PicoJava prefixes */ + public static final int opc_nonpriv = 254; + public static final int opc_priv = 255; + + /* Wide instructions */ + public static final int opc_iload_w = (opc_wide<<8)|opc_iload; + public static final int opc_lload_w = (opc_wide<<8)|opc_lload; + public static final int opc_fload_w = (opc_wide<<8)|opc_fload; + public static final int opc_dload_w = (opc_wide<<8)|opc_dload; + public static final int opc_aload_w = (opc_wide<<8)|opc_aload; + public static final int opc_istore_w = (opc_wide<<8)|opc_istore; + public static final int opc_lstore_w = (opc_wide<<8)|opc_lstore; + public static final int opc_fstore_w = (opc_wide<<8)|opc_fstore; + public static final int opc_dstore_w = (opc_wide<<8)|opc_dstore; + public static final int opc_astore_w = (opc_wide<<8)|opc_astore; + public static final int opc_ret_w = (opc_wide<<8)|opc_ret; + public static final int opc_iinc_w = (opc_wide<<8)|opc_iinc; + + /* Opcode Names */ + public static final String opcNamesTab[] = { + "nop", + "aconst_null", + "iconst_m1", + "iconst_0", + "iconst_1", + "iconst_2", + "iconst_3", + "iconst_4", + "iconst_5", + "lconst_0", + "lconst_1", + "fconst_0", + "fconst_1", + "fconst_2", + "dconst_0", + "dconst_1", + "bipush", + "sipush", + "ldc", + "ldc_w", + "ldc2_w", + "iload", + "lload", + "fload", + "dload", + "aload", + "iload_0", + "iload_1", + "iload_2", + "iload_3", + "lload_0", + "lload_1", + "lload_2", + "lload_3", + "fload_0", + "fload_1", + "fload_2", + "fload_3", + "dload_0", + "dload_1", + "dload_2", + "dload_3", + "aload_0", + "aload_1", + "aload_2", + "aload_3", + "iaload", + "laload", + "faload", + "daload", + "aaload", + "baload", + "caload", + "saload", + "istore", + "lstore", + "fstore", + "dstore", + "astore", + "istore_0", + "istore_1", + "istore_2", + "istore_3", + "lstore_0", + "lstore_1", + "lstore_2", + "lstore_3", + "fstore_0", + "fstore_1", + "fstore_2", + "fstore_3", + "dstore_0", + "dstore_1", + "dstore_2", + "dstore_3", + "astore_0", + "astore_1", + "astore_2", + "astore_3", + "iastore", + "lastore", + "fastore", + "dastore", + "aastore", + "bastore", + "castore", + "sastore", + "pop", + "pop2", + "dup", + "dup_x1", + "dup_x2", + "dup2", + "dup2_x1", + "dup2_x2", + "swap", + "iadd", + "ladd", + "fadd", + "dadd", + "isub", + "lsub", + "fsub", + "dsub", + "imul", + "lmul", + "fmul", + "dmul", + "idiv", + "ldiv", + "fdiv", + "ddiv", + "irem", + "lrem", + "frem", + "drem", + "ineg", + "lneg", + "fneg", + "dneg", + "ishl", + "lshl", + "ishr", + "lshr", + "iushr", + "lushr", + "iand", + "land", + "ior", + "lor", + "ixor", + "lxor", + "iinc", + "i2l", + "i2f", + "i2d", + "l2i", + "l2f", + "l2d", + "f2i", + "f2l", + "f2d", + "d2i", + "d2l", + "d2f", + "i2b", + "i2c", + "i2s", + "lcmp", + "fcmpl", + "fcmpg", + "dcmpl", + "dcmpg", + "ifeq", + "ifne", + "iflt", + "ifge", + "ifgt", + "ifle", + "if_icmpeq", + "if_icmpne", + "if_icmplt", + "if_icmpge", + "if_icmpgt", + "if_icmple", + "if_acmpeq", + "if_acmpne", + "goto", + "jsr", + "ret", + "tableswitch", + "lookupswitch", + "ireturn", + "lreturn", + "freturn", + "dreturn", + "areturn", + "return", + "getstatic", + "putstatic", + "getfield", + "putfield", + "invokevirtual", + "invokespecial", // was "invokenonvirtual", + "invokestatic", + "invokeinterface", + "bytecode 186", //"xxxunusedxxx", + "new", + "newarray", + "anewarray", + "arraylength", + "athrow", + "checkcast", + "instanceof", + "monitorenter", + "monitorexit", + null, // "wide", + "multianewarray", + "ifnull", + "ifnonnull", + "goto_w", + "jsr_w", + "bytecode 202", // "breakpoint", + "bytecode", + "try", + "endtry", + "catch", + "var", + "endvar", + "locals_map", + "stack_map" + }; + + /* Opcode Lengths */ + public static final int opcLengthsTab[] = { + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 3, + 2, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 3, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 99, + 99, + 1, + 1, + 1, + 1, + 1, + 1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 5, + 0, + 3, + 2, + 3, + 1, + 1, + 3, + 3, + 1, + 1, + 0, // wide + 4, + 3, + 3, + 5, + 5, + 1, + 1, 0, 0, 0, 0, 0 // pseudo + }; + +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/StackMapData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/StackMapData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +import java.util.*; +import java.io.*; + +import static org.apidesign.javap.RuntimeConstants.*; + +/* represents one entry of StackMap attribute + */ +class StackMapData { + final int offset; + final int[] locals; + final int[] stack; + + StackMapData(int offset, int[] locals, int[] stack) { + this.offset = offset; + this.locals = locals; + this.stack = stack; + } + + StackMapData(DataInputStream in, MethodData method) throws IOException { + offset = in.readUnsignedShort(); + int local_size = in.readUnsignedShort(); + locals = readTypeArray(in, local_size, method); + int stack_size = in.readUnsignedShort(); + stack = readTypeArray(in, stack_size, method); + } + + static final int[] readTypeArray(DataInputStream in, int length, MethodData method) throws IOException { + int[] types = new int[length]; + for (int i=0; i= (stackMapTable[nextFrameIndex].offsetDelta + + 1))) { + final StackMapTableData nextFrame = stackMapTable[nextFrameIndex]; + + lastFrameByteCodeOffset += nextFrame.offsetDelta + 1; + nextFrame.applyTo(localTypes, stackTypes); + + ++nextFrameIndex; + } + } + + public void advanceTo(final int nextByteCodeOffset) { + advanceBy(nextByteCodeOffset - byteCodeOffset); + } + + private static TypeArray getArgTypes(final String methodSignature, + final boolean isStaticMethod) { + final TypeArray argTypes = new TypeArray(); + + if (!isStaticMethod) { + argTypes.add(ITEM_Object); + } + + if (methodSignature.charAt(0) != '(') { + throw new IllegalArgumentException("Invalid method signature"); + } + + final int length = methodSignature.length(); + boolean skipType = false; + int argType; + for (int i = 1; i < length; ++i) { + switch (methodSignature.charAt(i)) { + case 'B': + case 'C': + case 'S': + case 'Z': + case 'I': + argType = ITEM_Integer; + break; + case 'J': + argType = ITEM_Long; + break; + case 'F': + argType = ITEM_Float; + break; + case 'D': + argType = ITEM_Double; + break; + case 'L': { + i = methodSignature.indexOf(';', i + 1); + if (i == -1) { + throw new IllegalArgumentException( + "Invalid method signature"); + } + argType = ITEM_Object; + break; + } + case ')': + // not interested in the return value type + return argTypes; + case '[': + if (!skipType) { + argTypes.add(ITEM_Object); + skipType = true; + } + continue; + + default: + throw new IllegalArgumentException( + "Invalid method signature"); + } + + if (!skipType) { + argTypes.add(argType); + } else { + skipType = false; + } + } + + return argTypes; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/StackMapTableData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/StackMapTableData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +import java.io.*; + +import static org.apidesign.javap.RuntimeConstants.*; + +/* represents one entry of StackMapTable attribute + */ +abstract class StackMapTableData { + final int frameType; + int offsetDelta; + + StackMapTableData(int frameType) { + this.frameType = frameType; + } + + abstract void applyTo(TypeArray localTypes, TypeArray stackTypes); + + protected static String toString( + final String frameType, + final int offset, + final int[] localTypes, + final int[] stackTypes) { + final StringBuilder sb = new StringBuilder(frameType); + + sb.append("(off: +").append(offset); + if (localTypes != null) { + sb.append(", locals: "); + appendTypes(sb, localTypes); + } + if (stackTypes != null) { + sb.append(", stack: "); + appendTypes(sb, stackTypes); + } + sb.append(')'); + + return sb.toString(); + } + + private static void appendTypes(final StringBuilder sb, final int[] types) { + sb.append('['); + if (types.length > 0) { + sb.append(TypeArray.typeString(types[0])); + for (int i = 1; i < types.length; ++i) { + sb.append(", "); + sb.append(TypeArray.typeString(types[i])); + } + } + sb.append(']'); + } + + static class SameFrame extends StackMapTableData { + SameFrame(int frameType, int offsetDelta) { + super(frameType); + this.offsetDelta = offsetDelta; + } + + @Override + void applyTo(TypeArray localTypes, TypeArray stackTypes) { + stackTypes.clear(); + } + + @Override + public String toString() { + return toString("SAME" + ((frameType == SAME_FRAME_EXTENDED) + ? "_FRAME_EXTENDED" : ""), + offsetDelta, + null, null); + } + } + + static class SameLocals1StackItem extends StackMapTableData { + final int[] stack; + SameLocals1StackItem(int frameType, int offsetDelta, int[] stack) { + super(frameType); + this.offsetDelta = offsetDelta; + this.stack = stack; + } + + @Override + void applyTo(TypeArray localTypes, TypeArray stackTypes) { + stackTypes.setAll(stack); + } + + @Override + public String toString() { + return toString( + "SAME_LOCALS_1_STACK_ITEM" + + ((frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) + ? "_EXTENDED" : ""), + offsetDelta, + null, stack); + } + } + + static class ChopFrame extends StackMapTableData { + ChopFrame(int frameType, int offsetDelta) { + super(frameType); + this.offsetDelta = offsetDelta; + } + + @Override + void applyTo(TypeArray localTypes, TypeArray stackTypes) { + localTypes.setSize(localTypes.getSize() + - (SAME_FRAME_EXTENDED - frameType)); + stackTypes.clear(); + } + + @Override + public String toString() { + return toString("CHOP", offsetDelta, null, null); + } + } + + static class AppendFrame extends StackMapTableData { + final int[] locals; + AppendFrame(int frameType, int offsetDelta, int[] locals) { + super(frameType); + this.offsetDelta = offsetDelta; + this.locals = locals; + } + + @Override + void applyTo(TypeArray localTypes, TypeArray stackTypes) { + localTypes.addAll(locals); + stackTypes.clear(); + } + + @Override + public String toString() { + return toString("APPEND", offsetDelta, locals, null); + } + } + + static class FullFrame extends StackMapTableData { + final int[] locals; + final int[] stack; + FullFrame(int offsetDelta, int[] locals, int[] stack) { + super(FULL_FRAME); + this.offsetDelta = offsetDelta; + this.locals = locals; + this.stack = stack; + } + + @Override + void applyTo(TypeArray localTypes, TypeArray stackTypes) { + localTypes.setAll(locals); + stackTypes.setAll(stack); + } + + @Override + public String toString() { + return toString("FULL", offsetDelta, locals, stack); + } + } + + static StackMapTableData getInstance(DataInputStream in, MethodData method) + throws IOException { + int frameType = in.readUnsignedByte(); + + if (frameType < SAME_FRAME_BOUND) { + // same_frame + return new SameFrame(frameType, frameType); + } else if (SAME_FRAME_BOUND <= frameType && frameType < SAME_LOCALS_1_STACK_ITEM_BOUND) { + // same_locals_1_stack_item_frame + // read additional single stack element + return new SameLocals1StackItem(frameType, + (frameType - SAME_FRAME_BOUND), + StackMapData.readTypeArray(in, 1, method)); + } else if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { + // same_locals_1_stack_item_extended + return new SameLocals1StackItem(frameType, + in.readUnsignedShort(), + StackMapData.readTypeArray(in, 1, method)); + } else if (SAME_LOCALS_1_STACK_ITEM_EXTENDED < frameType && frameType < SAME_FRAME_EXTENDED) { + // chop_frame or same_frame_extended + return new ChopFrame(frameType, in.readUnsignedShort()); + } else if (frameType == SAME_FRAME_EXTENDED) { + // chop_frame or same_frame_extended + return new SameFrame(frameType, in.readUnsignedShort()); + } else if (SAME_FRAME_EXTENDED < frameType && frameType < FULL_FRAME) { + // append_frame + return new AppendFrame(frameType, in.readUnsignedShort(), + StackMapData.readTypeArray(in, frameType - SAME_FRAME_EXTENDED, method)); + } else if (frameType == FULL_FRAME) { + // full_frame + int offsetDelta = in.readUnsignedShort(); + int locals_size = in.readUnsignedShort(); + int[] locals = StackMapData.readTypeArray(in, locals_size, method); + int stack_size = in.readUnsignedShort(); + int[] stack = StackMapData.readTypeArray(in, stack_size, method); + return new FullFrame(offsetDelta, locals, stack); + } else { + throw new ClassFormatError("unrecognized frame_type in StackMapTable"); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/TrapData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/TrapData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.apidesign.javap; + +import java.io.*; + +/** + * Stores exception table data in code attribute. + * + * @author Sucheta Dambalkar (Adopted code from jdis) + */ +public final class TrapData { + public final short start_pc; + public final short end_pc; + public final short handler_pc; + public final short catch_cpx; + final int num; + + + /** + * Read and store exception table data in code attribute. + */ + TrapData(DataInputStream in, int num) throws IOException { + this.num=num; + start_pc = in.readShort(); + end_pc=in.readShort(); + handler_pc=in.readShort(); + catch_cpx=in.readShort(); + } + + /** + * returns recommended identifier + */ + public String ident() { + return "t"+num; + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/TrapDataIterator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/TrapDataIterator.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,114 @@ +/** + * 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.javap; + +/** + * + * @author Jaroslav Tulach + */ +public final class TrapDataIterator { + private final Hashtable exStart = new Hashtable(); + private final Hashtable exStop = new Hashtable(); + private TrapData[] current = new TrapData[10]; + private int currentCount; + + TrapDataIterator(Vector exceptionTable) { + for (int i=0 ; i < exceptionTable.size(); i++) { + final TrapData td = (TrapData)exceptionTable.elementAt(i); + put(exStart, td.start_pc, td); + put(exStop, td.end_pc, td); + } + } + + private static void put(Hashtable h, short key, TrapData td) { + Short s = Short.valueOf((short)key); + Vector v = (Vector) h.get(s); + if (v == null) { + v = new Vector(1); + h.put(s, v); + } + v.add(td); + } + + private boolean processAll(Hashtable h, Short key, boolean add) { + boolean change = false; + Vector v = (Vector)h.get(key); + if (v != null) { + int s = v.size(); + for (int i = 0; i < s; i++) { + TrapData td = (TrapData)v.elementAt(i); + if (add) { + add(td); + change = true; + } else { + remove(td); + change = true; + } + } + } + return change; + } + + public boolean advanceTo(int i) { + Short s = Short.valueOf((short)i); + boolean ch1 = processAll(exStart, s, true); + boolean ch2 = processAll(exStop, s, false); + return ch1 || ch2; + } + + public boolean useTry() { + return currentCount > 0; + } + + public TrapData[] current() { + TrapData[] copy = new TrapData[currentCount]; + for (int i = 0; i < currentCount; i++) { + copy[i] = current[i]; + } + return copy; + } + + private void add(TrapData e) { + if (currentCount == current.length) { + TrapData[] data = new TrapData[currentCount * 2]; + for (int i = 0; i < currentCount; i++) { + data[i] = current[i]; + } + current = data; + } + current[currentCount++] = e; + } + + private void remove(TrapData e) { + if (currentCount == 0) { + return; + } + int from = 0; + while (from < currentCount) { + if (e == current[from++]) { + break; + } + } + while (from < currentCount) { + current[from - 1] = current[from]; + current[from] = null; + from++; + } + currentCount--; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/TypeArray.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/TypeArray.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.apidesign.javap; + +import static org.apidesign.javap.RuntimeConstants.ITEM_Bogus; +import static org.apidesign.javap.RuntimeConstants.ITEM_Integer; +import static org.apidesign.javap.RuntimeConstants.ITEM_Float; +import static org.apidesign.javap.RuntimeConstants.ITEM_Double; +import static org.apidesign.javap.RuntimeConstants.ITEM_Long; +import static org.apidesign.javap.RuntimeConstants.ITEM_Null; +import static org.apidesign.javap.RuntimeConstants.ITEM_InitObject; +import static org.apidesign.javap.RuntimeConstants.ITEM_Object; +import static org.apidesign.javap.RuntimeConstants.ITEM_NewObject; + +public final class TypeArray { + private static final int CAPACITY_INCREMENT = 16; + + private int[] types; + private int size; + + public TypeArray() { + } + + public TypeArray(final TypeArray initialTypes) { + setAll(initialTypes); + } + + public void add(final int newType) { + ensureCapacity(size + 1); + types[size++] = newType; + } + + public void addAll(final TypeArray newTypes) { + addAll(newTypes.types, 0, newTypes.size); + } + + public void addAll(final int[] newTypes) { + addAll(newTypes, 0, newTypes.length); + } + + public void addAll(final int[] newTypes, + final int offset, + final int count) { + if (count > 0) { + ensureCapacity(size + count); + arraycopy(newTypes, offset, types, size, count); + size += count; + } + } + + public void set(final int index, final int newType) { + types[index] = newType; + } + + public void setAll(final TypeArray newTypes) { + setAll(newTypes.types, 0, newTypes.size); + } + + public void setAll(final int[] newTypes) { + setAll(newTypes, 0, newTypes.length); + } + + public void setAll(final int[] newTypes, + final int offset, + final int count) { + if (count > 0) { + ensureCapacity(count); + arraycopy(newTypes, offset, types, 0, count); + size = count; + } else { + clear(); + } + } + + public void setSize(final int newSize) { + if (size != newSize) { + ensureCapacity(newSize); + + for (int i = size; i < newSize; ++i) { + types[i] = 0; + } + size = newSize; + } + } + + public void clear() { + size = 0; + } + + public int getSize() { + return size; + } + + public int get(final int index) { + return types[index]; + } + + public static String typeString(final int type) { + switch (type & 0xff) { + case ITEM_Bogus: + return "_top_"; + case ITEM_Integer: + return "_int_"; + case ITEM_Float: + return "_float_"; + case ITEM_Double: + return "_double_"; + case ITEM_Long: + return "_long_"; + case ITEM_Null: + return "_null_"; + case ITEM_InitObject: // UninitializedThis + return "_init_"; + case ITEM_Object: + return "_object_"; + case ITEM_NewObject: // Uninitialized + return "_new_"; + default: + throw new IllegalArgumentException("Unknown type"); + } + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("["); + if (size > 0) { + sb.append(typeString(types[0])); + for (int i = 1; i < size; ++i) { + sb.append(", "); + sb.append(typeString(types[i])); + } + } + + return sb.append(']').toString(); + } + + private void ensureCapacity(final int minCapacity) { + if ((minCapacity == 0) + || (types != null) && (minCapacity <= types.length)) { + return; + } + + final int newCapacity = + ((minCapacity + CAPACITY_INCREMENT - 1) / CAPACITY_INCREMENT) + * CAPACITY_INCREMENT; + final int[] newTypes = new int[newCapacity]; + + if (size > 0) { + arraycopy(types, 0, newTypes, 0, size); + } + + types = newTypes; + } + + // no System.arraycopy + private void arraycopy(final int[] src, final int srcPos, + final int[] dest, final int destPos, + final int length) { + for (int i = 0; i < length; ++i) { + dest[destPos + i] = src[srcPos + i]; + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javap/src/main/java/org/apidesign/javap/Vector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/org/apidesign/javap/Vector.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,89 @@ +/** + * 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.javap; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.core.JavaScriptPrototype; + +/** A JavaScript ready replacement for java.util.Vector + * + * @author Jaroslav Tulach + */ +@JavaScriptPrototype(prototype = "new Array" ) +final class Vector { + private Object[] arr; + + Vector() { + } + + Vector(int i) { + } + + void add(Object objectType) { + addElement(objectType); + } + @JavaScriptBody(args = { "obj" }, body = + "this.push(obj);" + ) + void addElement(Object obj) { + final int s = size(); + setSize(s + 1); + setElementAt(obj, s); + } + + @JavaScriptBody(args = { }, body = + "return this.length;" + ) + int size() { + return arr == null ? 0 : arr.length; + } + + @JavaScriptBody(args = { "newArr" }, body = + "for (var i = 0; i < this.length; i++) {\n" + + " newArr[i] = this[i];\n" + + "}\n") + void copyInto(Object[] newArr) { + if (arr == null) { + return; + } + int min = Math.min(newArr.length, arr.length); + for (int i = 0; i < min; i++) { + newArr[i] = arr[i]; + } + } + + @JavaScriptBody(args = { "index" }, body = + "return this[index];" + ) + Object elementAt(int index) { + return arr[index]; + } + + private void setSize(int len) { + Object[] newArr = new Object[len]; + copyInto(newArr); + arr = newArr; + } + + @JavaScriptBody(args = { "val", "index" }, body = + "this[index] = val;" + ) + void setElementAt(Object val, int index) { + arr[index] = val; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,74 @@ + + + 4.0.0 + + org.apidesign.bck2brwsr + javaquery + 0.3-SNAPSHOT + + org.apidesign.bck2brwsr + javaquery.api + 0.3-SNAPSHOT + JavaQuery API + http://maven.apache.org + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + + UTF-8 + + + + org.testng + testng + test + + + junit + junit + + + + + org.netbeans.api + org-openide-util-lookup + + + org.apidesign.bck2brwsr + core + 0.3-SNAPSHOT + jar + + + org.apidesign.bck2brwsr + emul + 0.3-SNAPSHOT + jar + runtime + + + org.apidesign.bck2brwsr + vm4brwsr + 0.3-SNAPSHOT + jar + test + + + ${project.groupId} + vmtest + ${project.version} + test + + + diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,93 @@ +/** + * 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.bck2brwsr.htmlpage; + +import java.lang.reflect.Method; +import org.apidesign.bck2brwsr.core.ExtraJavaScript; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** Provides binding between models and + * + * @author Jaroslav Tulach + */ +@ExtraJavaScript(resource = "/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js") +public class Knockout { + /** used by tests */ + static Knockout next; + + Knockout() { + } + + public static Knockout applyBindings( + Class modelClass, M model, String[] propsGettersAndSetters + ) { + Knockout bindings = next; + next = null; + if (bindings == null) { + bindings = new Knockout(); + } + for (int i = 0; i < propsGettersAndSetters.length; i += 4) { + try { + Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]); + bind(bindings, model, propsGettersAndSetters[i], + propsGettersAndSetters[i + 1], + propsGettersAndSetters[i + 2], + getter.getReturnType().isPrimitive() + ); + } catch (NoSuchMethodException ex) { + throw new IllegalStateException(ex.getMessage()); + } + } + applyBindings(bindings); + return bindings; + } + + @JavaScriptBody(args = { "prop" }, body = + "this[prop].valueHasMutated();" + ) + public void valueHasMutated(String prop) { + } + + + @JavaScriptBody(args = { "id", "ev" }, body = "ko.utils.triggerEvent(window.document.getElementById(id), ev.substring(2));") + public static void triggerEvent(String id, String ev) { + } + + @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive" }, body = + "var bnd = {\n" + + " read: function() {\n" + + " var v = model[getter]();\n" + + " return v;\n" + + " },\n" + + " owner: bindings\n" + + "};\n" + + "if (setter != null) {\n" + + " bnd.write = function(val) {\n" + + " model[setter](primitive ? new Number(val) : val);\n" + + " };\n" + + "}\n" + + "bindings[prop] = ko.computed(bnd);" + ) + private static void bind( + Object bindings, Object model, String prop, String getter, String setter, boolean primitive + ) { + } + + @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);") + private static void applyBindings(Object bindings) {} +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,435 @@ +/** + * 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.bck2brwsr.htmlpage; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Completion; +import javax.annotation.processing.Completions; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.MirroredTypeException; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic; +import javax.tools.FileObject; +import javax.tools.StandardLocation; +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty; +import org.apidesign.bck2brwsr.htmlpage.api.On; +import org.apidesign.bck2brwsr.htmlpage.api.Page; +import org.apidesign.bck2brwsr.htmlpage.api.Property; +import org.openide.util.lookup.ServiceProvider; + +/** Annotation processor to process an XHTML page and generate appropriate + * "id" file. + * + * @author Jaroslav Tulach + */ +@ServiceProvider(service=Processor.class) +@SupportedAnnotationTypes({ + "org.apidesign.bck2brwsr.htmlpage.api.Page", + "org.apidesign.bck2brwsr.htmlpage.api.On" +}) +public final class PageProcessor extends AbstractProcessor { + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) { + Page p = e.getAnnotation(Page.class); + if (p == null) { + continue; + } + PackageElement pe = (PackageElement)e.getEnclosingElement(); + String pkg = pe.getQualifiedName().toString(); + + ProcessPage pp; + try { + InputStream is = openStream(pkg, p.xhtml()); + pp = ProcessPage.readPage(is); + is.close(); + } catch (IOException iOException) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't read " + p.xhtml(), e); + return false; + } + Writer w; + String className = p.className(); + if (className.isEmpty()) { + int indx = p.xhtml().indexOf('.'); + className = p.xhtml().substring(0, indx); + } + try { + FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e); + w = new OutputStreamWriter(java.openOutputStream()); + try { + w.append("package " + pkg + ";\n"); + w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n"); + w.append("final class ").append(className).append(" {\n"); + w.append(" private boolean locked;\n"); + if (!initializeOnClick(className, (TypeElement) e, w, pp)) { + return false; + } + for (String id : pp.ids()) { + String tag = pp.tagNameForId(id); + String type = type(tag); + w.append(" ").append("public final "). + append(type).append(' ').append(cnstnt(id)).append(" = new "). + append(type).append("(\"").append(id).append("\");\n"); + } + List propsGetSet = new ArrayList(); + Map> propsDeps = new HashMap>(); + generateComputedProperties(w, e.getEnclosedElements(), propsGetSet, propsDeps); + generateProperties(w, p.properties(), propsGetSet, propsDeps); + w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n"); + if (!propsGetSet.isEmpty()) { + w.write("public " + className + " applyBindings() {\n"); + w.write(" ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings("); + w.write(className + ".class, this, "); + w.write("new String[] {\n"); + String sep = ""; + for (String n : propsGetSet) { + w.write(sep); + if (n == null) { + w.write(" null"); + } else { + w.write(" \"" + n + "\""); + } + sep = ",\n"; + } + w.write("\n });\n return this;\n}\n"); + + w.write("public void triggerEvent(Element e, OnEvent ev) {\n"); + w.write(" org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n"); + w.write("}\n"); + } + w.append("}\n"); + } finally { + w.close(); + } + } catch (IOException ex) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + className + ".java", e); + return false; + } + } + return true; + } + + private InputStream openStream(String pkg, String name) throws IOException { + try { + FileObject fo = processingEnv.getFiler().getResource( + StandardLocation.SOURCE_PATH, pkg, name); + return fo.openInputStream(); + } catch (IOException ex) { + return processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, pkg, name).openInputStream(); + } + } + + private static String type(String tag) { + if (tag.equals("title")) { + return "Title"; + } + if (tag.equals("button")) { + return "Button"; + } + if (tag.equals("input")) { + return "Input"; + } + if (tag.equals("canvas")) { + return "Canvas"; + } + if (tag.equals("img")) { + return "Image"; + } + return "Element"; + } + + private static String cnstnt(String id) { + return id.toUpperCase(Locale.ENGLISH).replace('.', '_').replace('-', '_'); + } + + private boolean initializeOnClick( + String className, TypeElement type, Writer w, ProcessPage pp + ) throws IOException { + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType(); + { //for (Element clazz : pe.getEnclosedElements()) { + // if (clazz.getKind() != ElementKind.CLASS) { + // continue; + // } + w.append(" public ").append(className).append("() {\n"); + StringBuilder dispatch = new StringBuilder(); + int dispatchCnt = 0; + for (Element method : type.getEnclosedElements()) { + On oc = method.getAnnotation(On.class); + if (oc != null) { + for (String id : oc.id()) { + if (pp.tagNameForId(id) == null) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method); + return false; + } + ExecutableElement ee = (ExecutableElement)method; + StringBuilder params = new StringBuilder(); + { + boolean first = true; + for (VariableElement ve : ee.getParameters()) { + if (!first) { + params.append(", "); + } + first = false; + if (ve.asType() == stringType) { + params.append('"').append(id).append('"'); + continue; + } + String rn = ve.asType().toString(); + int last = rn.lastIndexOf('.'); + if (last >= 0) { + rn = rn.substring(last + 1); + } + if (rn.equals(className)) { + params.append(className).append(".this"); + continue; + } + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, + "@On method can only accept String or " + className + " arguments", + ee + ); + return false; + } + } + if (!ee.getModifiers().contains(Modifier.STATIC)) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method has to be static", ee); + return false; + } + if (ee.getModifiers().contains(Modifier.PRIVATE)) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method can't be private", ee); + return false; + } + w.append(" OnEvent." + oc.event()).append(".of(").append(cnstnt(id)). + append(").perform(new OnDispatch(" + dispatchCnt + "));\n"); + + dispatch. + append(" case ").append(dispatchCnt).append(": "). + append(type.getSimpleName().toString()). + append('.').append(ee.getSimpleName()).append("("). + append(params). + append("); break;\n"); + + dispatchCnt++; + } + } + } + w.append(" }\n"); + if (dispatchCnt > 0) { + w.append("class OnDispatch implements Runnable {\n"); + w.append(" private final int dispatch;\n"); + w.append(" OnDispatch(int d) { dispatch = d; }\n"); + w.append(" public void run() {\n"); + w.append(" switch (dispatch) {\n"); + w.append(dispatch); + w.append(" }\n"); + w.append(" }\n"); + w.append("}\n"); + } + + + } + return true; + } + + @Override + public Iterable getCompletions( + Element element, AnnotationMirror annotation, + ExecutableElement member, String userText + ) { + if (!userText.startsWith("\"")) { + return Collections.emptyList(); + } + + Element cls = findClass(element); + Page p = cls.getAnnotation(Page.class); + PackageElement pe = (PackageElement) cls.getEnclosingElement(); + String pkg = pe.getQualifiedName().toString(); + ProcessPage pp; + try { + InputStream is = openStream(pkg, p.xhtml()); + pp = ProcessPage.readPage(is); + is.close(); + } catch (IOException iOException) { + return Collections.emptyList(); + } + + List cc = new ArrayList(); + userText = userText.substring(1); + for (String id : pp.ids()) { + if (id.startsWith(userText)) { + cc.add(Completions.of("\"" + id + "\"", id)); + } + } + return cc; + } + + private static Element findClass(Element e) { + if (e == null) { + return null; + } + Page p = e.getAnnotation(Page.class); + if (p != null) { + return e; + } + return e.getEnclosingElement(); + } + + private static void generateProperties( + Writer w, Property[] properties, Collection props, + Map> deps + ) throws IOException { + for (Property p : properties) { + final String tn = typeName(p); + String[] gs = toGetSet(p.name(), tn); + + w.write("private " + tn + " prop_" + p.name() + ";\n"); + w.write("public " + tn + " " + gs[0] + "() {\n"); + w.write(" if (locked) throw new IllegalStateException();\n"); + w.write(" return prop_" + p.name() + ";\n"); + w.write("}\n"); + w.write("public void " + gs[1] + "(" + tn + " v) {\n"); + w.write(" if (locked) throw new IllegalStateException();\n"); + w.write(" prop_" + p.name() + " = v;\n"); + w.write(" if (ko != null) {\n"); + w.write(" ko.valueHasMutated(\"" + p.name() + "\");\n"); + final Collection dependants = deps.get(p.name()); + if (dependants != null) { + for (String depProp : dependants) { + w.write(" ko.valueHasMutated(\"" + depProp + "\");\n"); + } + } + w.write(" }\n"); + w.write("}\n"); + + props.add(p.name()); + props.add(gs[2]); + props.add(gs[3]); + props.add(gs[0]); + } + } + + private boolean generateComputedProperties( + Writer w, Collection arr, Collection props, + Map> deps + ) throws IOException { + for (Element e : arr) { + if (e.getKind() != ElementKind.METHOD) { + continue; + } + if (e.getAnnotation(ComputedProperty.class) == null) { + continue; + } + ExecutableElement ee = (ExecutableElement)e; + final String tn = ee.getReturnType().toString(); + final String sn = ee.getSimpleName().toString(); + String[] gs = toGetSet(sn, tn); + + w.write("public " + tn + " " + gs[0] + "() {\n"); + w.write(" if (locked) throw new IllegalStateException();\n"); + int arg = 0; + for (VariableElement pe : ee.getParameters()) { + final String dn = pe.getSimpleName().toString(); + final String dt = pe.asType().toString(); + String[] call = toGetSet(dn, dt); + w.write(" " + dt + " arg" + (++arg) + " = "); + w.write(call[0] + "();\n"); + + Collection depends = deps.get(dn); + if (depends == null) { + depends = new LinkedHashSet(); + deps.put(dn, depends); + } + depends.add(sn); + } + w.write(" try {\n"); + w.write(" locked = true;\n"); + w.write(" return " + e.getEnclosingElement().getSimpleName() + '.' + e.getSimpleName() + "("); + String sep = ""; + for (int i = 1; i <= arg; i++) { + w.write(sep); + w.write("arg" + i); + sep = ", "; + } + w.write(");\n"); + w.write(" } finally {\n"); + w.write(" locked = false;\n"); + w.write(" }\n"); + w.write("}\n"); + + props.add(e.getSimpleName().toString()); + props.add(gs[2]); + props.add(null); + props.add(gs[0]); + } + + return true; + } + + private static String[] toGetSet(String name, String type) { + String n = Character.toUpperCase(name.charAt(0)) + name.substring(1); + String bck2brwsrType = "L" + type.replace('.', '_') + "_2"; + if ("int".equals(type)) { + bck2brwsrType = "I"; + } + if ("double".equals(type)) { + bck2brwsrType = "D"; + } + String pref = "get"; + if ("boolean".equals(type)) { + pref = "is"; + bck2brwsrType = "Z"; + } + final String nu = n.replace('.', '_'); + return new String[]{ + pref + n, + "set" + n, + pref + nu + "__" + bck2brwsrType, + "set" + nu + "__V" + bck2brwsrType + }; + } + + private static String typeName(Property p) { + try { + return p.type().getName(); + } catch (MirroredTypeException ex) { + return ex.getTypeMirror().toString(); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ProcessPage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ProcessPage.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,78 @@ +/** + * 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.bck2brwsr.htmlpage; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +class ProcessPage { + private final Map ids2Elems = new TreeMap(); + + public Set ids() { + return Collections.unmodifiableSet(ids2Elems.keySet()); + } + + public String tagNameForId(String id) { + return ids2Elems.get(id); + } + + public static ProcessPage readPage(InputStream is) throws IOException { + DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); + f.setValidating(false); + f.setIgnoringComments(true); + + Document doc = null; + try { + DocumentBuilder b = f.newDocumentBuilder(); + doc = b.parse(is); + } catch (IOException ex) { + throw ex; + } catch (Exception e) { + throw new IOException(e); + } + Element root = doc.getDocumentElement(); + + ProcessPage pp = new ProcessPage(); + pp.seekForIds(root); + return pp; + } + + private void seekForIds(Element e) { + String val = e.getAttribute("id"); + if (val != null && !val.isEmpty()) { + String prev = ids2Elems.put(val, e.getTagName()); + } + NodeList arr = e.getChildNodes(); + for (int i = 0; i < arr.getLength(); i++) { + final Node n = arr.item(i); + if (n instanceof Element) { + seekForIds((Element)n); + } + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Button.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Button.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,36 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +/** + * + * @author Jaroslav Tulach + */ +public final class Button extends Element { + public Button(String id) { + super(id); + } + + @Override + void dontSubclass() { + } + + public void setDisabled(boolean state) { + setAttribute(this, "disabled", state); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Canvas.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Canvas.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,61 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Anton Epple + */ +public class Canvas extends Element { + + public Canvas(String id) { + super(id); + } + + public void setHeight(int height) { + setAttribute(this, "height", height); + } + + public int getHeight() { + return (Integer) getAttribute(this, "height"); + } + + public void setWidth(int width) { + setAttribute(this, "width", width); + } + + public int getWidth() { + return (Integer) getAttribute(this, "width"); + } + + @JavaScriptBody( + args = {"el"}, + body = "var e = window.document.getElementById(el.fld_id);\n" + + "return e.getContext('2d');\n") + private native static Object getContextImpl(Canvas el); + + public GraphicsContext getContext() { + return new GraphicsContext(getContextImpl(this)); + } + + @Override + void dontSubclass() { + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,38 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Can be used in classes annotated with {@link Page} annotation to + * define a derived property. Value of derived property is based on values + * of {@link Property} as enumerated by {@link Page#properties()}. + *

    + * The name of the derived property is the name of the method. The arguments + * of the method define the property names (from {@link Page#properties()} list) + * the value of property depends on. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.METHOD) +public @interface ComputedProperty { +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,95 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** Represents a generic HTML element. + * + * @author Jaroslav Tulach + */ +public abstract class Element { + private final String id; + + public Element(String id) { + this.id = id; + } + + /** Id of the element in the document. + * @return the id for this element + */ + public String getId() { + return id; + } + + abstract void dontSubclass(); + + @JavaScriptBody( + args={"el", "property", "value"}, + body="var e = window.document.getElementById(el.fld_id);\n" + + "e[property] = value;\n" + ) + static native void setAttribute(Element el, String property, Object value); + + @JavaScriptBody( + args={"el", "property"}, + body="var e = window.document.getElementById(el.fld_id);\n" + + "return e[property];\n" + ) + static native Object getAttribute(Element el, String property); + + @JavaScriptBody( + args={"el"}, + body="return window.document.getElementById(el.fld_id);" + ) + static native Object getElementById(Element el); + + /** Executes given runnable when user performs a "click" on the given + * element. + * @param r the runnable to execute, never null + */ + @JavaScriptBody( + args={ "ev", "r" }, + body="var e = window.document.getElementById(this.fld_id);\n" + + "e[ev.fld_id] = function() { r.run__V(); };\n" + ) + final void on(OnEvent ev, Runnable r) { + } + + /** Shows alert message dialog in a browser. + * @param msg the message to show + */ + @JavaScriptBody(args = "msg", body = "alert(msg);") + public static native void alert(String msg); + + /** Generic way to query any attribute of this element. + * @param property name of the attribute + */ + public final Object getAttribute(String property) { + return getAttribute(this, property); + } + + /** Generic way to change an attribute of this element. + * + * @param property name of the attribute + * @param value value to associate with the attribute + */ + public final void setAttribute(String property, Object value) { + setAttribute(this, property, value); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,335 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Anton Epple + */ +public class GraphicsContext { + + Object context; + + GraphicsContext(Object contextImpl) { + this.context = contextImpl; + } + + @JavaScriptBody(args = {"centerx", "centery", "radius", "startangle", "endangle", "ccw"}, + body = "this.fld_context.arc(centerx,centery, radius, startangle, endangle,ccw);") + public native void arc(double centerX, + double centerY, + double startAngle, + double radius, + double endAngle, + boolean ccw); + + @JavaScriptBody(args = {"x1", "y1", "x2", "y2", "r"}, + body = "this.fld_context.arcTo(x1,y1,x2,y2,r);") + public native void arcTo(double x1, + double y1, + double x2, + double y2, + double r); + + @JavaScriptBody(args = {"x", "y"}, + body = "return this.fld_context.isPointInPath(x,y);") + public native boolean isPointInPath(double x, double y); + + @JavaScriptBody(args = {}, body = "this.fld_context.fill();") + public native void fill(); + + @JavaScriptBody(args = {}, body = "this.fld_context.stroke();") + public native void stroke(); + + @JavaScriptBody(args = {}, body = "this.fld_context.beginPath();") + public native void beginPath(); + + @JavaScriptBody(args = {}, body = "this.fld_context.closePath();") + public native void closePath(); + + @JavaScriptBody(args = {}, body = "this.fld_context.clip();") + public native void clip(); + + @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.moveTo(x,y);") + public native void moveTo(double x, double y); + + @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.lineTo(x,y);") + public native void lineTo(double x, double y); + + @JavaScriptBody(args = {"cpx", "cpy", "x", "y"}, body = "this.fld_context.quadraticCurveTo(cpx,cpy,x,y);") + public native void quadraticCurveTo(double cpx, double cpy, double x, double y); + + @JavaScriptBody(args = {"cp1x", "cp1y", "cp2x", "cp2y", "x", "y"}, + body = "this.fld_context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);") + public native void bezierCurveTo(double cp1x, double cp1y, double cp2x, double cp2y, double x, double y); + + @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.fillRect(x,y,width,height);") + public native void fillRect(double x, double y, double width, double height); + + @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.strokeRect(x,y,width,height);") + public native void strokeRect(double x, double y, double width, double height); + + @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.clearRect(x,y,width,height);") + public native void clearRect(double x, double y, double width, double height); + + @JavaScriptBody(args = {"x", "y", "width", "height"}, body = "this.fld_context.rectect(x,y,width,height);") + public native void rect(double x, double y, double width, double height); + + @JavaScriptBody(args = {}, body = "this.fld_context.save();") + public native void save(); + + @JavaScriptBody(args = {}, body = "this.fld_context.restore();") + public native void restore(); + + @JavaScriptBody(args = {"angle"}, body = "this.fld_context.rotate(angle);") + public native void rotate(double angle); + + @JavaScriptBody(args = {"a", "b", "c", "d", "e", "f"}, body = "this.fld_context.transform(a,b,c,d,e,f);") + public native void transform(double a, double b, double c, double d, double e, double f); + + @JavaScriptBody(args = {"a", "b", "c", "d", "e", "f"}, body = "this.fld_context.setTransform(a,b,c,d,e,f);") + public native void setTransform(double a, double b, double c, double d, double e, double f); + + @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.translate(x,y);") + public native void translate(double x, double y); + + @JavaScriptBody(args = {"x", "y"}, body = "this.fld_context.scale(x,y);") + public native void scale(double x, double y); + + public void drawImage(Image image, double x, double y) { + drawImageImpl(context, Element.getElementById(image), x, y); + } + + public void drawImage(Image image, double x, double y, double width, double height) { + drawImageImpl(context, Element.getElementById(image), x, y, width, height); + } + + public void drawImage(Image image, double sx, double sy, double sWidth, double sHeight, double x, double y, double width, double height) { + drawImageImpl(context, Element.getElementById(image), sx, sy, sWidth, sHeight, x, y, width, height); + } + + @JavaScriptBody(args = {"ctx", "img", "x", "y", "width", "height"}, body = "ctx.drawImage(img,x,y,width,height);") + private native static void drawImageImpl(Object ctx, Object img, double x, double y, double width, double height); + + @JavaScriptBody(args = {"ctx", "img", "sx", "sy", "swidth", "sheight", "x", "y", "width", "height"}, body = "ctx.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);") + private native static void drawImageImpl(Object ctx, Object img, double sx, double sy, double sWidth, double sHeight, double x, double y, double width, double height); + + @JavaScriptBody(args = {"ctx", "img", "x", "y"}, body = "ctx.drawImage(img,x,y);") + private native static void drawImageImpl(Object ctx, Object img, double x, double y); + + @JavaScriptBody(args = {"style"}, body = "this.fld_context.fillStyle=style;") + public native void setFillStyle(String style); + + @JavaScriptBody(args = {}, body = "return this.fld_context.fillStyle;") + public native String getFillStyle(); + + public void setFillStyle(LinearGradient style) { + setFillStyleImpl(context, style.object()); + } + + public void setFillStyle(RadialGradient style) { + setFillStyleImpl(context, style.object()); + } + + public void setFillStyle(Pattern style) { + setFillStyleImpl(context, style.object()); + } + + @JavaScriptBody(args = {"context","obj"}, body = "context.fillStyle=obj;") + private native void setFillStyleImpl(Object context, Object obj); + + @JavaScriptBody(args = {"style"}, body = "this.fld_context.strokeStyle=style;") + public native void setStrokeStyle(String style); + + public void setStrokeStyle(LinearGradient style) { + setStrokeStyleImpl(context, style.object()); + } + + public void setStrokeStyle(RadialGradient style) { + setStrokeStyleImpl(context, style.object()); + } + + @JavaScriptBody(args = {"style"}, body = "this.fld_context.fillStyle=style;") + public void setStrokeStyle(Pattern style) { + setStrokeStyleImpl(context, style.object()); + } + + @JavaScriptBody(args = {"context","obj"}, body = "context.strokeStyle=obj;") + private native void setStrokeStyleImpl(Object context, Object obj); + + @JavaScriptBody(args = {"color"}, body = "this.fld_context.shadowColor=color;") + public native void setShadowColor(String color); + + @JavaScriptBody(args = {"blur"}, body = "this.fld_context.shadowBlur=blur;") + public native void setShadowBlur(double blur); + + @JavaScriptBody(args = {"x"}, body = "this.fld_context.shadowOffsetX=x;") + public native void setShadowOffsetX(double x); + + @JavaScriptBody(args = {"y"}, body = "this.fld_context.shadowOffsetY=y;") + public native void setShadowOffsetY(double y); + + @JavaScriptBody(args = {}, body = "return this.fld_context.strokeStyle;") + public native String getStrokeStyle(); + + @JavaScriptBody(args = {}, body = "return this.fld_context.shadowColor;") + public native String getShadowColor(); + + @JavaScriptBody(args = {}, body = "return this.fld_context.shadowBlur;") + public native double getShadowBlur(); + + @JavaScriptBody(args = {}, body = "return this.fld_context.shadowOffsetX;") + public native double getShadowOffsetX(); + + @JavaScriptBody(args = {}, body = "return this.fld_context.shadowOffsetY;") + public native double getShadowOffsetY(); + + @JavaScriptBody(args = {}, body = "return this.fld_context.lineCap;") + public native String getLineCap(); + + @JavaScriptBody(args = {"style"}, body = "this.fld_context.lineCap=style;") + public native void setLineCap(String style); + + @JavaScriptBody(args = {}, body = "return this.fld_context.lineJoin;") + public native String getLineJoin(); + + @JavaScriptBody(args = {"style"}, body = "this.fld_context.lineJoin=style;") + public native void setLineJoin(String style) ; + + @JavaScriptBody(args = {}, body = "return this.fld_context.lineWidth;") + public native double getLineWidth(); + + @JavaScriptBody(args = {"width"}, body = "this.fld_context.lineJoin=width;") + public native void setLineWidth(double width); + + @JavaScriptBody(args = {}, body = "return this.fld_context.miterLimit;") + public native double getMiterLimit(); + + @JavaScriptBody(args = {"limit"}, body = "this.fld_context.miterLimit=limit;") + public native void setMiterLimit(double limit); + + @JavaScriptBody(args = {}, body = "return this.fld_context.font;") + public native String getFont(); + + @JavaScriptBody(args = {"font"}, body = "this.fld_context.font=font;") + public native void setFont(String font); + + @JavaScriptBody(args = {}, body = "return this.fld_context.textAlign;") + public native String getTextAlign(); + + @JavaScriptBody(args = {"textalign"}, body = "this.fld_context.textAlign=textalign;") + public native void setTextAlign(String textAlign); + + @JavaScriptBody(args = {}, body = "return this.fld_context.textBaseline;") + public native String getTextBaseline(); + + @JavaScriptBody(args = {"textbaseline"}, body = "this.fld_context.textBaseline=textbaseline;") + public native void setTextBaseline(String textbaseline); + + @JavaScriptBody(args = {"text", "x", "y"}, body = "this.fld_context.fillText(text,x,y);") + public native void fillText(String text, double x, double y); + + @JavaScriptBody(args = {"text", "x", "y", "maxwidth"}, body = "this.fld_context.fillText(text,x,y,maxwidth);") + public void fillText(String text, double x, double y, double maxWidth) { + } + + public TextMetrics measureText(String text) { + return new TextMetrics(measureTextImpl(text)); + } + + @JavaScriptBody(args = {"text"}, + body = "return this.fld_context.measureText(text);") + private native Object measureTextImpl(String text); + + @JavaScriptBody(args = {"text", "x", "y"}, body = "this.fld_context.strokeText(text,x,y);") + public native void strokeText(String text, double x, double y); + + @JavaScriptBody(args = {"text", "x", "y", "maxWidth"}, body = "this.fld_context.strokeText(text,x,y,maxWidth);") + public native void strokeText(String text, double x, double y, double maxWidth) ; + + public ImageData createImageData(double x, double y) { + return new ImageData(createImageDataImpl(x, y)); + } + + @JavaScriptBody(args = {"x", "y"}, + body = "return this.fld_context.createImageData(x,y);") + private native Object createImageDataImpl(double x, double y); + + public ImageData createImageData(ImageData imageData) { + return new ImageData(createImageDataImpl(imageData.getWidth(), imageData.getHeight())); + } + + public ImageData getImageData(double x, double y, double width, double height) { + return new ImageData(getImageDataImpl(x, y, width, height)); + } + + @JavaScriptBody(args = {"x", "y", "width", "height"}, + body = "return this.fld_context.getImageData(x,y,width,height);") + private native Object getImageDataImpl(double x, double y, double width, double height); + + public void putImageData(ImageData imageData, double x, double y) { + putImageDataImpl(imageData.object(), x, y); + } + + @JavaScriptBody(args = {"imageData", "x", "y"}, + body = "this.fld_context.putImageData(imageData,x,y);") + private native void putImageDataImpl(Object imageData, double x, double y); + + public void putImageData(ImageData imageData, double x, double y, double dirtyx, double dirtyy, double dirtywidth, double dirtyheight) { + putImageDataImpl(imageData.object(), x, y, dirtyx, dirtyy, dirtywidth, dirtyheight); + } + + @JavaScriptBody(args = {"imageData", "x", "y", "dirtyx", "dirtyy", "dirtywidth", "dirtyheight"}, + body = "this.fld_context.putImageData(imageData,x,y, dirtyx, dirtyy, dirtywidth,dirtyheight);") + private native void putImageDataImpl(Object imageData, double x, double y, double dirtyx, double dirtyy, double dirtywidth, double dirtyheight); + + @JavaScriptBody(args = {"alpha"}, body = "this.fld_context.globalAlpha=alpha;") + public native void setGlobalAlpha(double alpha) ; + + @JavaScriptBody(args = {}, body = "return this.fld_context.globalAlpha;") + public native double getGlobalAlpha(); + + @JavaScriptBody(args = {"operation"}, body = "this.fld_context.globalCompositeOperation=operation;") + public native void setGlobalCompositeOperation(double alpha); + + @JavaScriptBody(args = {}, body = "return this.fld_context.globalCompositeOperation;") + public native double getGlobalCompositeOperation(); + + public LinearGradient createLinearGradient(double x0, double y0, double x1, double y1) { + return new LinearGradient(createLinearGradientImpl(context, x0, y0, x1, y1)); + } + + @JavaScriptBody(args = {"context", "x0", "y0", "x1", "y1"}, body = "return context.createLinearGradient(x0,y0,x1,y1);") + private native Object createLinearGradientImpl(Object context, double x0, double y0, double x1, double y1); + + public Pattern createPattern(Image image, String repeat) { + return new Pattern(createPatternImpl(context, image, repeat)); + } + + @JavaScriptBody(args = {"context", "image", "repeat"}, body = "return context.createPattern(image, repeat);") + private static native Object createPatternImpl(Object context, Image image, String repeat); + + public RadialGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1) { + return new RadialGradient(createRadialGradientImpl(context, x0, y0, r0, x1, y1, r1)); + } + + @JavaScriptBody(args = {"context", "x0", "y0", "r0", "x1", "y1", "r1"}, body = "return context.createRadialGradient(x0,y0,r0,x1,y1,r1);") + private static native Object createRadialGradientImpl(Object context, double x0, double y0, double r0, double x1, double y1, double r1); +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Image.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Image.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,36 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +/** + * + * @author Anton Epple + */ +public class Image extends Element{ + + public Image(String id) { + super(id); + } + + + + @Override + void dontSubclass() { + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ImageData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ImageData.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,89 @@ +/** + * 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. + */ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.apidesign.bck2brwsr.htmlpage.api; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Anton Epple + */ +public class ImageData { + + private Object imageData; + private Data data; + + public ImageData(Object imageData) { + this.imageData = imageData; + } + + public Data getData(){ + if (data == null){ + data = new Data(getDataImpl(imageData)); + } + return data; + } + + @JavaScriptBody(args = {"imageData"}, body = "return imageData.data") + public native Object getDataImpl(Object imageData); + + public double getWidth() { + return getWidthImpl(imageData); + } + + @JavaScriptBody(args = {"imageData"}, body = "return imagedata.width;") + private static native double getWidthImpl(Object imageData); + + public double getHeight() { + return getHeightImpl(imageData); + } + + @JavaScriptBody(args = {"imageData"}, body = "return imagedata.height;") + private static native double getHeightImpl(Object imageData); + + Object object() { + return imageData; + } + + public static class Data { + + Object data; + + public Data(Object data) { + this.data = data; + } + + public int get(int index) { + return getImpl(data, index); + } + + public void set(int index, int value) { + setImpl(data, index, value); + } + + @JavaScriptBody(args = {"data", "index", "value"}, body = "data[index]=value;") + private static native void setImpl(Object data, int index, int value); + + @JavaScriptBody(args = {"imagedata", "index"}, body = "return data[index];") + private static native int getImpl(Object data, int index); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Input.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Input.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,44 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +/** + * + * @author Jaroslav Tulach + */ +public final class Input extends Element { + public Input(String id) { + super(id); + } + + @Override + void dontSubclass() { + } + + public void setAutocomplete(boolean state) { + setAttribute(this, "autocomplete", state); + } + + public final String getValue() { + return (String)getAttribute(this, "value"); + } + + public final void setValue(String txt) { + setAttribute(this, "value", txt); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/LinearGradient.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/LinearGradient.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,45 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Anton Epple + */ +public class LinearGradient { + + private final Object gradient; + + LinearGradient(Object linearGradient) { + this.gradient = linearGradient; + } + + Object object() { + return gradient; + } + + public void addColorStop(double position, String color) { + addColorStopImpl(gradient, position, color); + } + + @JavaScriptBody(args = {"gradient", "position", "color"}, body = + "gradient.addColorStop(position,color)") + private static native void addColorStopImpl(Object gradient, double position, String color); +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/On.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/On.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,35 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Adds an onClick handler to an element identified by given id. + * Apply on a public static void method with no arguments. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.METHOD) +public @interface On { + OnEvent event(); + String[] id(); +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnController.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnController.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,43 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +/** Controller created via {@link OnEvent#of(org.apidesign.bck2brwsr.htmlpage.api.Element[])}. + * + * @author Jaroslav Tulach + */ +public final class OnController { + private final Element[] arr; + private final OnEvent event; + + OnController(OnEvent event, Element[] arr) { + this.event = event; + this.arr = arr; + } + + /** Registers a runnable to be performed on associated {@link OnEvent} + * and {@link Element}. + * + * @see OnEvent#of + */ + public void perform(Runnable r) { + for (Element e : arr) { + e.on(event, r); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnEvent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnEvent.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,103 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +/** Type of events to use in connection with {@link On} annotation. + * + * @author Jaroslav Tulach + */ +public enum OnEvent { + ABORT("onabort"), + BLUR("onblur"), + CAN_PLAY("oncanplay"), + CAN_PLAY_THROUGH("oncanplaythrough"), + CHANGE("onchange"), + CLICK("onclick"), + CONTEXT_MENU("oncontextmenu"), + DBL_CLICK("ondblclick"), + DRAG("ondrag"), + DRAG_END("ondragend"), + DRAG_ENTER("ondragenter"), + DRAG_LEAVE("ondragleave"), + DRAG_OVER("ondragover"), + DRAG_START("ondragstart"), + DROP("ondrop"), + DURATION_CHANGE("ondurationchange"), + EMPTIED("onemptied"), + ENDED("onended"), + ERROR("onerror"), + FOCUS("onfocus"), + FORM_CHANGE("onformchange"), + FORM_INPUT("onforminput"), + INPUT("oninput"), + INVALID("oninvalid"), + KEY_DOWN("onkeydown"), + KEY_PRESS("onkeypress"), + KEY_UP("onkeyup"), + LOAD("onload"), + LOADED_DATA("onloadeddata"), + LOADED_META_DATA("onloadedmetadata"), + LOAD_START("onloadstart"), + MOUSE_DOWN("onmousedown"), + MOUSE_MOVE("onmousemove"), + MOUSE_OUT("onmouseout"), + MOUSE_OVER("onmouseover"), + MOUSE_UP("onmouseup"), + MOUSE_WHEEL("onmousewheel"), + PAUSE("onpause"), + PLAY("onplay"), + PLAYING("onplaying"), + PROGRESS("onprogress"), + RATE_CHANGE("onratechange"), + READY_STATE_CHANGE("onreadystatechange"), + SCROLL("onscroll"), + SEEKED("onseeked"), + SEEKING("onseeking"), + SELECT("onselect"), + SHOW("onshow"), + STALLED("onstalled"), + SUBMIT("onsubmit"), + SUSPEND("onsuspend"), + TIME_UPDATE("ontimeupdate"), + VOLUME_CHANGE("onvolumechange"), + WAITING("onwaiting"); + + final String id; + + private OnEvent(String id) { + this.id = id; + } + + /** The name of property this event is referenced by from an {@link Element}. + * For {@link OnEvent#CHANGE}, it is onchange. + */ + public String getElementPropertyName() { + return id; + } + + /** What should happen when this even happen on one + * of associated elements. Continue by calling {@link OnController#perform(java.lang.Runnable)} + * method. + * + * @param elmnts one or more elements + * @return controller with perform method. + */ + public OnController of(Element... elmnts) { + return new OnController(this, elmnts); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Page.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Page.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,42 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Converts an XHTML page into a Java class that contains + * references to all IDs. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface Page { + /** Path to the XHTML page to read in */ + String xhtml(); + /** Name of a Java class to generate. It will contain constants for all + * found elements with IDs. + */ + String className() default ""; + /** List of properties generated into the page. + */ + Property[] properties() default {}; +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Paint.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Paint.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,30 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +/** + * + * @author Anton Epple + */ +public class Paint { + + + String asString(){ + return ""; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Pattern.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Pattern.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,35 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +/** + * + * @author Anton Epple + */ +public class Pattern { + + private Object pattern; + + public Pattern(Object pattern) { + this.pattern = pattern; + } + + Object object() { + return pattern; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,34 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Represents a property in a generated model of an HTML + * {@link Page}. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.SOURCE) +@Target({}) +public @interface Property { + String name(); + Class type(); +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/RadialGradient.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/RadialGradient.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,45 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Anton Epple + */ +public class RadialGradient { + + private Object gradient; + + public RadialGradient(Object radialGradient) { + this.gradient = radialGradient; + } + + public void addColorStop(double position, String color) { + addColorStopImpl(gradient, position, color); + } + + @JavaScriptBody(args = {"gradient", "position", "color"}, body = + "gradient.addColorStop(position,color)") + private static native void addColorStopImpl(Object gradient, double position, String color); + + Object object() { + return gradient; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/TextMetrics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/TextMetrics.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,48 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Anton Epple + */ +public class TextMetrics { + + private Object textMetrics; + + TextMetrics(Object measureTextImpl) { + this.textMetrics = measureTextImpl; + } + + @JavaScriptBody(args = {"textMetrics"}, body = "return textMetrics.width;") + private native double getWidth(Object textMetrics); + + @JavaScriptBody(args = {"textMetrics"}, body = "return textMetrics.height;") + private native double getHeight(Object textMetrics); + + public double getWidth() { + return getWidth(textMetrics); + } + + public double getHeight() { + return getHeight(textMetrics); + + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Timer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Timer.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,59 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +import java.io.Closeable; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Jaroslav Tulach + */ +public class Timer implements Closeable { + private final Object t; + + private Timer(Object t) { + this.t = t; + } + + /** Creates a timer that invokes provided runnable on a fixed interval + * + * @param r the runnable to execute + * @param time milliseconds to invoke the timer periodically + */ + public static Timer create(Runnable r, int time) { + return new Timer(interval(r, time)); + } + + @JavaScriptBody(args = { "r", "time" }, body = + "return window.setInterval(function() { r.run__V(); }, time);" + ) + private static native Object interval(Runnable r, int time); + + @JavaScriptBody(args = { "self" }, body = + "window.clearInterval(self);" + ) + private static native void close(Object self); + + /** Cancels this timer. + */ + @Override + public void close() { + close(t); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Title.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Title.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,36 @@ +/** + * 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.bck2brwsr.htmlpage.api; + +/** + * + * @author Jaroslav Tulach + */ +public class Title extends Element { + public Title(String id) { + super(id); + } + + @Override + void dontSubclass() { + } + + public final void setText(String text) { + setAttribute(this, "innerHTML", text); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,3587 @@ +// Knockout JavaScript library v2.2.1 +// (c) Steven Sanderson - http://knockoutjs.com/ +// License: MIT (http://www.opensource.org/licenses/mit-license.php) + +(function(){ +var DEBUG=true; +(function(window,document,navigator,jQuery,undefined){ +!function(factory) { + // Support three module loading scenarios + if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') { + // [1] CommonJS/Node.js + var target = module['exports'] || exports; // module.exports is for Node.js + factory(target); + } else if (typeof define === 'function' && define['amd']) { + // [2] AMD anonymous module + define(['exports'], factory); + } else { + // [3] No module loader (plain "); + }; + + if (jQueryTmplVersion > 0) { + jQuery['tmpl']['tag']['ko_code'] = { + open: "__.push($1 || '');" + }; + jQuery['tmpl']['tag']['ko_with'] = { + open: "with($1) {", + close: "} " + }; + } + }; + + ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine(); + + // Use this one by default *only if jquery.tmpl is referenced* + var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine(); + if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0) + ko.setTemplateEngine(jqueryTmplTemplateEngineInstance); + + ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine); +})(); +}); +})(window,document,navigator,window["jQuery"]); +})(); \ No newline at end of file diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,62 @@ +/** + * 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.bck2brwsr.htmlpage; + +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty; +import org.apidesign.bck2brwsr.htmlpage.api.OnEvent; +import org.apidesign.bck2brwsr.htmlpage.api.Page; +import org.apidesign.bck2brwsr.htmlpage.api.Property; +import org.apidesign.bck2brwsr.vmtest.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.HtmlFragment; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +@Page(xhtml="Knockout.xhtml", className="KnockoutModel", properties={ + @Property(name="name", type=String.class) +}) +public class KnockoutTest { + + @HtmlFragment( + "

    Loading Bck2Brwsr's Hello World...

    \n" + + "Your name: \n" + + "\n" + ) + @BrwsrTest public void modifyValueAssertChangeInModel() { + KnockoutModel m = new KnockoutModel(); + m.setName("Kukuc"); + m.applyBindings(); + assert "Kukuc".equals(m.INPUT.getValue()) : "Value is really kukuc: " + m.INPUT.getValue(); + m.INPUT.setValue("Jardo"); + m.triggerEvent(m.INPUT, OnEvent.CHANGE); + assert "Jardo".equals(m.getName()) : "Name property updated: " + m.getName(); + } + + @ComputedProperty + static String helloMessage(String name) { + return "Hello " + name + "!"; + } + + @Factory + public static Object[] create() { + return VMTest.create(KnockoutTest.class); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,119 @@ +/** + * 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.bck2brwsr.htmlpage; + +import java.util.ArrayList; +import java.util.List; +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty; +import org.apidesign.bck2brwsr.htmlpage.api.Page; +import org.apidesign.bck2brwsr.htmlpage.api.Property; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +@Page(xhtml = "Empty.html", className = "Model", properties = { + @Property(name = "value", type = int.class), + @Property(name = "unrelated", type = long.class) +}) +public class ModelTest { + private Model model; + private static Model leakedModel; + + @BeforeMethod + public void createModel() { + model = new Model(); + } + + @Test public void classGeneratedWithSetterGetter() { + model.setValue(10); + assertEquals(10, model.getValue(), "Value changed"); + } + + @Test public void computedMethod() { + model.setValue(4); + assertEquals(16, model.getPowerValue()); + } + + @Test public void derivedPropertiesAreNotified() { + MockKnockout my = new MockKnockout(); + MockKnockout.next = my; + + model.applyBindings(); + + model.setValue(33); + + assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated); + assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated); + assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated); + + my.mutated.clear(); + + model.setUnrelated(44); + assertEquals(my.mutated.size(), 1, "One property changed"); + assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated"); + } + + @Test public void computedPropertyCannotWriteToModel() { + leakedModel = model; + try { + String res = model.getNotAllowedWrite(); + fail("We should not be allowed to write to the model: " + res); + } catch (IllegalStateException ex) { + // OK, we can't read + } + } + + @Test public void computedPropertyCannotReadToModel() { + leakedModel = model; + try { + String res = model.getNotAllowedRead(); + fail("We should not be allowed to read from the model: " + res); + } catch (IllegalStateException ex) { + // OK, we can't read + } + } + + @ComputedProperty + static int powerValue(int value) { + return value * value; + } + + @ComputedProperty + static String notAllowedRead() { + return "Not allowed callback: " + leakedModel.getUnrelated(); + } + + @ComputedProperty + static String notAllowedWrite() { + leakedModel.setUnrelated(11); + return "Not allowed callback!"; + } + + static class MockKnockout extends Knockout { + List mutated = new ArrayList(); + + @Override + public void valueHasMutated(String prop) { + mutated.add(prop); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,63 @@ +/** + * 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.bck2brwsr.htmlpage; + +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*; +import org.apidesign.bck2brwsr.htmlpage.api.On; +import org.apidesign.bck2brwsr.htmlpage.api.Page; + +/** Trivial demo for the bck2brwsr project. First of all start + * with your XHTML page. Include there + * a script that will boot Java in your browser. + *

    + * Then use @Page annotation to + * generate a Java representation of elements with IDs in that page. + * Depending on the type of the elements, they will have different + * methods (e.g. PG_TITLE has setText, etc.). + * Use @OnClick annotation to associate behavior + * with existing elements. Use the generated elements + * (PG_TITLE, PG_TEXT) to modify the page. + *

    + * Everything is type-safe. As soon as somebody modifies the page and + * removes the IDs or re-assigns them to wrong elements. Java compiler + * will emit an error. + *

    + * Welcome to the type-safe HTML5 world! + * + * @author Jaroslav Tulach + */ +@Page(xhtml="TestPage.html") +public class PageController { + private static final TestPage PAGE = new TestPage(); + + @On(event = CLICK, id="pg.button") + static void updateTitle(TestPage ref) { + if (PAGE != ref) { + throw new IllegalStateException("Both references should be the same. " + ref + " != " + PAGE); + } + ref.PG_TITLE.setText("You want this window to be named " + ref.PG_TEXT.getValue()); + } + + @On(event = CLICK, id={ "pg.title", "pg.text" }) + static void click(String id) { + if (!id.equals("pg.title")) { + throw new IllegalStateException(); + } + PAGE.PG_TITLE.setText(id); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,142 @@ +/** + * 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.bck2brwsr.htmlpage; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Set; +import javax.script.Invocable; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import org.apidesign.vm4brwsr.Bck2Brwsr; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +public class ProcessPageTest { + + + @Test public void findsThreeIds() throws IOException { + InputStream is = ProcessPageTest.class.getResourceAsStream("TestPage.html"); + assertNotNull(is, "Sample HTML page found"); + ProcessPage res = ProcessPage.readPage(is); + final Set ids = res.ids(); + assertEquals(ids.size(), 3, "Three ids found: " + ids); + + assertEquals(res.tagNameForId("pg.title"), "title"); + assertEquals(res.tagNameForId("pg.button"), "button"); + assertEquals(res.tagNameForId("pg.text"), "input"); + } + + @Test public void testCompileAndRunPageController() throws Exception { + StringBuilder sb = new StringBuilder(); + sb.append( + "var window = new Object();\n" + + "var doc = new Object();\n" + + "doc.button = new Object();\n" + + "doc.title = new Object();\n" + + "doc.title.innerHTML = 'nothing';\n" + + "doc.text = new Object();\n" + + "doc.text.value = 'something';\n" + + "doc.getElementById = function(id) {\n" + + " switch(id) {\n" + + " case 'pg.button': return doc.button;\n" + + " case 'pg.title': return doc.title;\n" + + " case 'pg.text': return doc.text;\n" + + " }\n" + + " throw id;\n" + + " }\n" + + "\n" + + "function clickAndCheck() {\n" + + " doc.button.onclick();\n" + + " return doc.title.innerHTML.toString();\n" + + "};\n" + + "\n" + + "window.document = doc;\n" + ); + Invocable i = compileClass(sb, "org/apidesign/bck2brwsr/htmlpage/PageController"); + + Object ret = null; + try { + ret = i.invokeFunction("clickAndCheck"); + } catch (ScriptException ex) { + fail("Execution failed in " + sb, ex); + } catch (NoSuchMethodException ex) { + fail("Cannot find method in " + sb, ex); + } + assertEquals(ret, "You want this window to be named something", "We expect that the JavaCode performs all the wiring"); + } + + @Test public void clickWithArgumentCalled() throws Exception { + StringBuilder sb = new StringBuilder(); + sb.append( + "var window = new Object();\n" + + "var doc = new Object();\n" + + "doc.button = new Object();\n" + + "doc.title = new Object();\n" + + "doc.title.innerHTML = 'nothing';\n" + + "doc.text = new Object();\n" + + "doc.text.value = 'something';\n" + + "doc.getElementById = function(id) {\n" + + " switch(id) {\n" + + " case 'pg.button': return doc.button;\n" + + " case 'pg.title': return doc.title;\n" + + " case 'pg.text': return doc.text;\n" + + " }\n" + + " throw id;\n" + + " }\n" + + "\n" + + "function clickAndCheck() {\n" + + " doc.title.onclick();\n" + + " return doc.title.innerHTML.toString();\n" + + "};\n" + + "\n" + + "window.document = doc;\n" + ); + Invocable i = compileClass(sb, + "org/apidesign/bck2brwsr/htmlpage/PageController" + ); + + Object ret = null; + try { + ret = i.invokeFunction("clickAndCheck"); + } catch (ScriptException ex) { + fail("Execution failed in " + sb, ex); + } catch (NoSuchMethodException ex) { + fail("Cannot find method in " + sb, ex); + } + assertEquals(ret, "pg.title", "Title has been passed to the method argument"); + } + + static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException { + if (sb == null) { + sb = new StringBuilder(); + } + Bck2Brwsr.generate(sb, ProcessPageTest.class.getClassLoader(), names); + ScriptEngineManager sem = new ScriptEngineManager(); + ScriptEngine js = sem.getEngineByExtension("js"); + try { + Object res = js.eval(sb.toString()); + assertTrue(js instanceof Invocable, "It is invocable object: " + res); + return (Invocable) js; + } catch (ScriptException ex) { + fail("Could not compile:\n" + sb, ex); + return null; + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Empty.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Empty.html Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,29 @@ + + + + + + Empty + + + Empty page + + diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Knockout.xhtml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Knockout.xhtml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,25 @@ + + +

    +

    Loading Bck2Brwsr's Hello World...

    + Your name: + +

    diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,30 @@ + + + + + + Default Title + + + New title: + + + diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator-dynamic/nbactions.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/demo-calculator-dynamic/nbactions.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,29 @@ + + + + + run + + process-classes + org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr + + + diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator-dynamic/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/demo-calculator-dynamic/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,64 @@ + + + 4.0.0 + + org.apidesign.bck2brwsr + demo.calculator + 0.3-SNAPSHOT + jar + + JavaQuery Demo - Calculator + http://maven.apache.org + + + UTF-8 + + + + + org.apidesign.bck2brwsr + mojo + 0.3-SNAPSHOT + + + + brwsr + + + + + org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + + + org.apidesign.bck2brwsr + emul + 0.3-SNAPSHOT + + + org.apidesign.bck2brwsr + javaquery.api + 0.3-SNAPSHOT + + + org.testng + testng + 6.5.2 + test + + + diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,112 @@ +/** + * 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.bck2brwsr.demo.calc; + +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty; +import org.apidesign.bck2brwsr.htmlpage.api.On; +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*; +import org.apidesign.bck2brwsr.htmlpage.api.Page; +import org.apidesign.bck2brwsr.htmlpage.api.Property; + +/** HTML5 & Java demo showing the power of + * annotation processors + * as well as other goodies. + * + * @author Jaroslav Tulach + */ +@Page(xhtml="Calculator.xhtml", properties = { + @Property(name = "memory", type = double.class), + @Property(name = "display", type = double.class), + @Property(name = "operation", type = String.class), + @Property(name = "hover", type = boolean.class) +}) +public class Calc { + static { + new Calculator().applyBindings(); + } + + @On(event = CLICK, id="clear") + static void clear(Calculator c) { + c.setMemory(0); + c.setOperation(null); + c.setDisplay(0); + } + + @On(event = CLICK, id= { "plus", "minus", "mul", "div" }) + static void applyOp(Calculator c, String op) { + c.setMemory(c.getDisplay()); + c.setOperation(op); + c.setDisplay(0); + } + + @On(event = MOUSE_OVER, id= { "result" }) + static void attemptingIn(Calculator c, String op) { + c.setHover(true); + } + @On(event = MOUSE_OUT, id= { "result" }) + static void attemptingOut(Calculator c, String op) { + c.setHover(false); + } + + @On(event = CLICK, id="result") + static void computeTheValue(Calculator c) { + c.setDisplay(compute( + c.getOperation(), + c.getMemory(), + c.getDisplay() + )); + c.setMemory(0); + } + + private static double compute(String op, double memory, double display) { + switch (op) { + case "plus": return memory + display; + case "minus": return memory - display; + case "mul": return memory * display; + case "div": return memory / display; + default: throw new IllegalStateException(op); + } + } + + @On(event = CLICK, id={"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9"}) + static void addDigit(String digit, Calculator c) { + digit = digit.substring(1); + + double v = c.getDisplay(); + if (v == 0.0) { + c.setDisplay(Integer.parseInt(digit)); + } else { + String txt = Double.toString(v); + if (txt.endsWith(".0")) { + txt = txt.substring(0, txt.length() - 2); + } + txt = txt + digit; + c.setDisplay(Double.parseDouble(txt)); + } + } + + @ComputedProperty + public static String displayPreview( + double display, boolean hover, double memory, String operation + ) { + if (!hover) { + return "Type numbers and perform simple operations! Press '=' to get result."; + } + return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,159 @@ + + + + + + Simple Calculator in HTML5 and Java + + + + +

    Java and HTML5 - Together at Last!

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + + + +
    +
    +    package org.apidesign.bck2brwsr.mavenhtml;
    +
    +    import org.apidesign.bck2brwsr.htmlpage.api.OnClick;
    +    import org.apidesign.bck2brwsr.htmlpage.api.Page;
    +
    +    /** HTML5 & Java demo showing the power of annotation processors
    +     * as well as other goodies, including type-safe association between
    +     * an XHTML page and Java.
    +     * 
    +     * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    +     */
    +    @Page(xhtml="Calculator.xhtml")
    +    public class App {
    +        private static double memory;
    +        private static String operation;
    +
    +        @OnClick(id="clear")
    +        static void clear() {
    +            memory = 0;
    +            operation = null;
    +            Calculator.DISPLAY.setValue("0");
    +        }
    +
    +        @OnClick(id= { "plus", "minus", "mul", "div" })
    +        static void applyOp(String op) {
    +            memory = getValue();
    +            operation = op;
    +            Calculator.DISPLAY.setValue("0");
    +        }
    +
    +        @OnClick(id="result")
    +        static void computeTheValue() {
    +            switch (operation) {
    +                case "plus": setValue(memory + getValue()); break;
    +                case "minus": setValue(memory - getValue()); break;
    +                case "mul": setValue(memory * getValue()); break;
    +                case "div": setValue(memory / getValue()); break;
    +                default: throw new IllegalStateException(operation);
    +            }
    +        }
    +
    +        @OnClick(id={"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9"}) 
    +        static void addDigit(String digit) {
    +            digit = digit.substring(1);
    +            String v = Calculator.DISPLAY.getValue();
    +            if (getValue() == 0.0) {
    +                Calculator.DISPLAY.setValue(digit);
    +            } else {
    +                Calculator.DISPLAY.setValue(v + digit);
    +            }
    +        }
    +
    +        private static void setValue(double v) {
    +            StringBuilder sb = new StringBuilder();
    +            sb.append(v);
    +            Calculator.DISPLAY.setValue(sb.toString());
    +        }
    +
    +        private static double getValue() {
    +            try {
    +                return Double.parseDouble(Calculator.DISPLAY.getValue());
    +            } catch (NumberFormatException ex) {
    +                Calculator.DISPLAY.setValue("err");
    +                return 0.0;
    +            }
    +        }
    +    }
    +
    +    
    + + diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator-dynamic/src/test/java/org/apidesign/bck2brwsr/demo/calc/CalcTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/demo-calculator-dynamic/src/test/java/org/apidesign/bck2brwsr/demo/calc/CalcTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,46 @@ +/** + * 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.bck2brwsr.demo.calc; + +import static org.testng.Assert.*; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** Demonstrating POJO testing of HTML page model. + * + * @author Jaroslav Tulach + */ +public class CalcTest { + private Calculator model; + + + @BeforeMethod + public void initModel() { + model = new Calculator().applyBindings(); + } + + @Test + public void testSomeMethod() { + model.setDisplay(10); + Calc.applyOp(model, "plus"); + assertEquals(0.0, model.getDisplay(), "Cleared after pressing +"); + model.setDisplay(5); + Calc.computeTheValue(model); + assertEquals(15.0, model.getDisplay(), "Shows fifteen"); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator/nbactions.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/demo-calculator/nbactions.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,29 @@ + + + + + run + + process-classes + org.codehaus.mojo:exec-maven-plugin:1.2.1:exec + + + diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/demo-calculator/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,73 @@ + + + 4.0.0 + + org.apidesign.bck2brwsr + demo.static.calculator + 0.3-SNAPSHOT + jar + + JavaQuery Demo - Calculator - Static Compilation + http://maven.apache.org + + + UTF-8 + + + + + org.apidesign.bck2brwsr + mojo + 0.3-SNAPSHOT + + + + j2js + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + + exec + + + + + xdg-open + + ${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + + + org.apidesign.bck2brwsr + emul + 0.3-SNAPSHOT + + + org.apidesign.bck2brwsr + javaquery.api + 0.3-SNAPSHOT + + + diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,112 @@ +/** + * 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.bck2brwsr.demo.calc.staticcompilation; + +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty; +import org.apidesign.bck2brwsr.htmlpage.api.On; +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*; +import org.apidesign.bck2brwsr.htmlpage.api.Page; +import org.apidesign.bck2brwsr.htmlpage.api.Property; + +/** HTML5 & Java demo showing the power of + * annotation processors + * as well as other goodies. + * + * @author Jaroslav Tulach + */ +@Page(xhtml="Calculator.xhtml", properties = { + @Property(name = "memory", type = double.class), + @Property(name = "display", type = double.class), + @Property(name = "operation", type = String.class), + @Property(name = "hover", type = boolean.class) +}) +public class Calc { + static { + new Calculator().applyBindings(); + } + + @On(event = CLICK, id="clear") + static void clear(Calculator c) { + c.setMemory(0); + c.setOperation(null); + c.setDisplay(0); + } + + @On(event = CLICK, id= { "plus", "minus", "mul", "div" }) + static void applyOp(Calculator c, String op) { + c.setMemory(c.getDisplay()); + c.setOperation(op); + c.setDisplay(0); + } + + @On(event = MOUSE_OVER, id= { "result" }) + static void attemptingIn(Calculator c, String op) { + c.setHover(true); + } + @On(event = MOUSE_OUT, id= { "result" }) + static void attemptingOut(Calculator c, String op) { + c.setHover(false); + } + + @On(event = CLICK, id="result") + static void computeTheValue(Calculator c) { + c.setDisplay(compute( + c.getOperation(), + c.getMemory(), + c.getDisplay() + )); + c.setMemory(0); + } + + private static double compute(String op, double memory, double display) { + switch (op) { + case "plus": return memory + display; + case "minus": return memory - display; + case "mul": return memory * display; + case "div": return memory / display; + default: throw new IllegalStateException(op); + } + } + + @On(event = CLICK, id={"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9"}) + static void addDigit(String digit, Calculator c) { + digit = digit.substring(1); + + double v = c.getDisplay(); + if (v == 0.0) { + c.setDisplay(Integer.parseInt(digit)); + } else { + String txt = Double.toString(v); + if (txt.endsWith(".0")) { + txt = txt.substring(0, txt.length() - 2); + } + txt = txt + digit; + c.setDisplay(Double.parseDouble(txt)); + } + } + + @ComputedProperty + public static String displayPreview( + double display, boolean hover, double memory, String operation + ) { + if (!hover) { + return "Type numbers and perform simple operations! Press '=' to get result."; + } + return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,154 @@ + + + + + + Simple Calculator in HTML5 and Java + + + + +

    Java and HTML5 - Together at Last!

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + +

    Bck2Brwsr Execution Harness

    + + + +
    + + + + diff -r 029e6eed60e9 -r 388e48c0a37a mojo/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,86 @@ + + + 4.0.0 + + org.apidesign + bck2brwsr + 0.3-SNAPSHOT + + org.apidesign.bck2brwsr + mojo + 0.3-SNAPSHOT + maven-plugin + Bck2Brwsr Maven Project + http://maven.apache.org + + + + org.apache.maven.plugins + maven-plugin-plugin + 3.1 + + + java-annotations + + true + + + + mojo-descriptor + process-classes + + descriptor + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + + + + + org.apache.maven + maven-plugin-api + 3.0.4 + jar + + + org.apache.maven.plugin-tools + maven-plugin-annotations + 3.0 + jar + + + ${project.groupId} + vm4brwsr + 0.3-SNAPSHOT + + + emul + org.apidesign.bck2brwsr + + + + + org.apache.maven + maven-core + 3.0.2 + jar + + + ${project.groupId} + launcher + ${project.version} + + + diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,122 @@ +/** + * 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.bck2brwsr.mojo; + +import org.apache.maven.plugin.AbstractMojo; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apidesign.vm4brwsr.Bck2Brwsr; + +/** Compiles classes into JavaScript. */ +@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES) +public class Bck2BrswrMojo extends AbstractMojo { + public Bck2BrswrMojo() { + } + /** Root of the class files */ + @Parameter(defaultValue="${project.build.directory}/classes") + private File classes; + /** File to generate. Defaults bootjava.js in the first non-empty + package under the classes directory */ + @Parameter + private File javascript; + + @Parameter(defaultValue="${project}") + private MavenProject prj; + + + + @Override + public void execute() throws MojoExecutionException { + if (!classes.isDirectory()) { + throw new MojoExecutionException("Can't find " + classes); + } + + if (javascript == null) { + javascript = new File(findNonEmptyFolder(classes), "bootjava.js"); + } + + List arr = new ArrayList(); + long newest = collectAllClasses("", classes, arr); + + if (javascript.lastModified() > newest) { + return; + } + + try { + URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts()); + FileWriter w = new FileWriter(javascript); + Bck2Brwsr.generate(w, url, arr.toArray(new String[0])); + w.close(); + } catch (IOException ex) { + throw new MojoExecutionException("Can't compile", ex); + } + } + + private static File findNonEmptyFolder(File dir) throws MojoExecutionException { + if (!dir.isDirectory()) { + throw new MojoExecutionException("Not a directory " + dir); + } + File[] arr = dir.listFiles(); + if (arr.length == 1 && arr[0].isDirectory()) { + return findNonEmptyFolder(arr[0]); + } + return dir; + } + + private static long collectAllClasses(String prefix, File toCheck, List arr) { + File[] files = toCheck.listFiles(); + if (files != null) { + long newest = 0L; + for (File f : files) { + long lastModified = collectAllClasses(prefix + f.getName() + "/", f, arr); + if (newest < lastModified) { + newest = lastModified; + } + } + return newest; + } else if (toCheck.getName().endsWith(".class")) { + arr.add(prefix.substring(0, prefix.length() - 7)); + return toCheck.lastModified(); + } else { + return 0L; + } + } + + private static URLClassLoader buildClassLoader(File root, Collection deps) throws MalformedURLException { + List arr = new ArrayList(); + arr.add(root.toURI().toURL()); + for (Artifact a : deps) { + arr.add(a.getFile().toURI().toURL()); + } + return new URLClassLoader(arr.toArray(new URL[0]), Bck2BrswrMojo.class.getClassLoader()); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,92 @@ +/** + * 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.bck2brwsr.mojo; + +import java.io.Closeable; +import org.apache.maven.plugin.AbstractMojo; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apidesign.bck2brwsr.launcher.Launcher; + +/** Executes given HTML page in a browser. */ +@Mojo(name="brwsr", defaultPhase=LifecyclePhase.DEPLOY) +public class BrswrMojo extends AbstractMojo { + public BrswrMojo() { + } + /** Resource to show as initial page */ + @Parameter + private String startpage; + + @Parameter(defaultValue="${project}") + private MavenProject prj; + + /** Root of the class files */ + @Parameter(defaultValue="${project.build.directory}/classes") + private File classes; + + @Override + public void execute() throws MojoExecutionException { + if (startpage == null) { + throw new MojoExecutionException("You have to provide a start page"); + } + + try { + URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts()); + + Closeable httpServer; + try { + httpServer = Launcher.showURL(url, startpage()); + } catch (Exception ex) { + throw new MojoExecutionException("Can't open " + startpage(), ex); + } + System.in.read(); + httpServer.close(); + } catch (IOException ex) { + throw new MojoExecutionException("Can't show the browser", ex); + } + } + + private String startpage() { + return startpage; + } + + private static URLClassLoader buildClassLoader(File root, Collection deps) throws MalformedURLException { + List arr = new ArrayList(); + arr.add(root.toURI().toURL()); + for (Artifact a : deps) { + final File f = a.getFile(); + if (f != null) { + arr.add(f.toURI().toURL()); + } + } + return new URLClassLoader(arr.toArray(new URL[0]), BrswrMojo.class.getClassLoader()); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/META-INF/maven/archetype-metadata.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,48 @@ + + + + + + src/main/java + + **/App.java + + + + src/main/resources + + **/*.xhtml + + + + src/test/java + + **/*Test.java + + + + + + nbactions.xml + + + + \ No newline at end of file diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/nbactions.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/resources/archetype-resources/nbactions.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,10 @@ + + + + run + + process-classes + org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr + + + diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/resources/archetype-resources/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,69 @@ + + + 4.0.0 + + ${groupId} + ${artifactId} + ${version} + jar + + ${artifactId} + + + UTF-8 + + + + + org.apidesign.bck2brwsr + mojo + 0.3-SNAPSHOT + + + + brwsr + + + + + ${package.replace('.','/')}/index.xhtml + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + + + org.apidesign.bck2brwsr + emul + 0.3-SNAPSHOT + + + org.apidesign.bck2brwsr + javaquery.api + 0.3-SNAPSHOT + + + org.testng + testng + 6.5.2 + test + + + ${project.groupId} + vmtest + 0.3-SNAPSHOT + test + + + diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/main/java/App.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/resources/archetype-resources/src/main/java/App.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,34 @@ +package ${package}; + +import org.apidesign.bck2brwsr.htmlpage.api.*; +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*; +import org.apidesign.bck2brwsr.htmlpage.api.Page; +import org.apidesign.bck2brwsr.htmlpage.api.Property; +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty; + +/** Edit the index.xhtml file. Use 'id' to name certain HTML elements. + * Use this class to define behavior of the elements. + */ +@Page(xhtml="index.xhtml", className="Index", properties={ + @Property(name="name", type=String.class) +}) +public class App { + static { + Index model = new Index(); + model.setName("World"); + model.applyBindings(); + } + + @On(event = CLICK, id="hello") + static void hello(Index m) { + GraphicsContext g = m.CANVAS.getContext(); + g.clearRect(0, 0, 1000, 1000); + g.setFont("italic 40px Calibri"); + g.fillText(m.getHelloMessage(), 10, 40); + } + + @ComputedProperty + static String helloMessage(String name) { + return "Hello " + name + "!"; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,22 @@ + + + + + Bck2Brwsr's Hello World + + +

    Loading Bck2Brwsr's Hello World...

    + Your name: + +

    + + +

    + + + + + + diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/test/java/AppTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/resources/archetype-resources/src/test/java/AppTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,26 @@ +package ${package}; + +import static org.testng.Assert.*; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** Demonstrating POJO testing of HTML page model. Runs in good old HotSpot + * as it does not reference any HTML elements or browser functionality. Just + * operates on the page model. + * + * @author Jaroslav Tulach + */ +public class AppTest { + private Index model; + + + @BeforeMethod + public void initModel() { + model = new Index().applyBindings(); + } + + @Test public void testHelloMessage() { + model.setName("Joe"); + assertEquals(model.getHelloMessage(), "Hello Joe!", "Cleared after pressing +"); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,40 @@ +package ${package}; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** Bck2brwsr cares about compatibility with real Java. Whatever API is + * supported by bck2brwsr, it needs to behave the same way as when running + * in HotSpot VM. + *

    + * There can be bugs, however. To help us fix them, we kindly ask you to + * write an "inconsistency" test. A test that compares behavior of the API + * between real VM and bck2brwsr VM. This class is skeleton of such test. + * + * @author Jaroslav Tulach + */ +public class InconsistencyTest { + /** A method to demonstrate inconsistency between bck2brwsr and HotSpot. + * Make calls to an API that behaves strangely, return some result at + * the end. No need to use any assert. + * + * @return value to compare between HotSpot and bck2brwsr + */ + @Compare + public int checkStringHashCode() throws Exception { + return "Is string hashCode the same?".hashCode(); + } + + /** Factory method that creates a three tests for each method annotated with + * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in + * HotSpot, one in Rhino and the last one compares the results. + * + * @see org.apidesign.bck2brwsr.vmtest.VMTest + */ + @Factory + public static Object[] create() { + return VMTest.create(InconsistencyTest.class); + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a mojo/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mojo/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,46 @@ +package ${package}; + +import org.apidesign.bck2brwsr.htmlpage.api.OnEvent; +import org.apidesign.bck2brwsr.vmtest.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.HtmlFragment; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** Sometimes it is useful to run tests inside of the real browser. + * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest} + * and that is it. If your code references elements on the HTML page, + * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which + * will be made available on the page before your test starts. + * + * @author Jaroslav Tulach + */ +public class IntegrationTest { + + /** Write to testing code here. Use assert (but not TestNG's + * Assert, as TestNG is not compiled with target 1.6 yet). + */ + @HtmlFragment( + "

    Loading Bck2Brwsr's Hello World...

    \n" + + "Your name: \n" + + "\n" + + "

    \n" + + " \n" + + "

    \n" + ) + @BrwsrTest + public void modifyValueAssertChangeInModel() { + Index m = new Index(); + m.setName("Joe Hacker"); + m.applyBindings(); + assert "Joe Hacker".equals(m.INPUT.getValue()) : "Value is really Joe Hacker: " + m.INPUT.getValue(); + m.INPUT.setValue("Happy Joe"); + m.triggerEvent(m.INPUT, OnEvent.CHANGE); + assert "Happy Joe".equals(m.getName()) : "Name property updated to Happy Joe: " + m.getName(); + } + + @Factory + public static Object[] create() { + return VMTest.create(IntegrationTest.class); + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a pom.xml --- a/pom.xml Thu Oct 11 06:15:22 2012 -0700 +++ b/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -3,14 +3,20 @@ 4.0.0 org.apidesign bck2brwsr - 1.0-SNAPSHOT + 0.3-SNAPSHOT pom Back 2 Browser - vm - htmlpage + vm emul core + dew + mojo + javaquery + javap + benchmarks + launcher + vmtest @@ -43,6 +49,40 @@ + + + + false + com.mycila.maven-license-plugin + maven-license-plugin + 1.9.0 + + + blah + + check + + + + + true + ${basedir} +
    COPYING
    + true + + emul/** + javap/** + * + .*/** + mojo/src/main/resources/archetype-resources/** + dew/src/main/resources/org/apidesign/bck2brwsr/dew/** + vmtest/src/test/resources/** + javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout*.js + +
    +
    +
    +
    @@ -75,4 +115,4 @@ COPYING - \ No newline at end of file + diff -r 029e6eed60e9 -r 388e48c0a37a vm/nb-configuration.xml --- a/vm/nb-configuration.xml Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ - - - - - - - all - - diff -r 029e6eed60e9 -r 388e48c0a37a vm/pom.xml --- a/vm/pom.xml Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -4,12 +4,12 @@ org.apidesign bck2brwsr - 1.0-SNAPSHOT + 0.3-SNAPSHOT org.apidesign.bck2brwsr vm4brwsr - 0.1-SNAPSHOT + 0.3-SNAPSHOT jar Java VM for Browser @@ -54,19 +54,20 @@ - org.apidesign.vm4brwsr.GenJS + org.apidesign.vm4brwsr.Main - - com.mycila.maven-license-plugin - maven-license-plugin - 1.9.0 - -
    src/header.txt
    -
    -
    + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + @@ -82,21 +83,21 @@
    - org.netbeans.api - org-netbeans-modules-classfile + ${project.groupId} + core + 0.3-SNAPSHOT jar - org.apidesign.bck2brwsr - core - 1.0-SNAPSHOT - jar + ${project.groupId} + emul + 0.3-SNAPSHOT + test - org.apidesign.bck2brwsr - emul - 1.0-SNAPSHOT - test + ${project.groupId} + javap + 0.3-SNAPSHOT
    diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/header.txt --- a/vm/src/header.txt Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -Java 4 Browser Bytecode Translator -Copyright (C) 2012-${year} 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. diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,106 @@ +/** + * 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; +import java.net.URL; +import java.util.Enumeration; + +/** Build your own virtual machine! Use methods in this class to generate + * a skeleton JVM in JavaScript that contains pre-compiled classes of your + * choice. The generated script defines one JavaScript method that can + * be used to bootstrap and load the virtual machine:
    + * var vm = bck2brwsr();
    + * var main = vm.loadClass('org.your.pkg.Main');
    + * main.main__V_3Ljava_lang_String_2(null);
    + * 
    + * In case one wants to initialize the virtual machine with ability to + * load classes lazily when needed, one can provide a loader function to + * when creating the virtual machine:
    + * var vm = bck2brwsr(function(resource) { 
    + *   return null; // byte[] for the resource
    + * });
    + * 
    + * In this scenario, when a request for an unknown class is made, the loader + * function is asked for its byte code and the system dynamically transforms + * it to JavaScript. + * + * @author Jaroslav Tulach + */ +public final class Bck2Brwsr { + private Bck2Brwsr() { + } + + /** Generates virtual machine from bytes served by a resources + * provider. + * + * @param out the output to write the generated JavaScript to + * @param resources provider of class files to use + * @param classes additional classes to include in the generated script + * @throws IOException I/O exception can be thrown when something goes wrong + */ + public static void generate(Appendable out, Resources resources, String... classes) throws IOException { + StringArray arr = StringArray.asList(classes); + arr.add(VM.class.getName().replace('.', '/')); + VM.compile(resources, out, arr); + } + + /** Generates virtual machine from bytes served by a class loader. + * + * @param out the output to write the generated JavaScript to + * @param loader class loader to load needed classes from + * @param classes additional classes to include in the generated script + * @throws IOException I/O exception can be thrown when something goes wrong + */ + public static void generate(Appendable out, final ClassLoader loader, String... classes) throws IOException { + class R implements Resources { + @Override + public InputStream get(String name) throws IOException { + Enumeration en = loader.getResources(name); + URL u = null; + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u == null) { + throw new IOException("Can't find " + name); + } + return u.openStream(); + } + } + generate(out, new R(), classes); + } + + /** Provider of resources (classes and other files). The + * {@link #generate(java.lang.Appendable, org.apidesign.vm4brwsr.Bck2Brwsr.Resources, java.lang.String[]) + * generator method} will call back here for all classes needed during + * translation to JavaScript. + */ + public interface Resources { + /** Loads given resource (class or other file like image). The + * resource name to load bytes for the {@link String} class + * would be "java/lang/String.class". + * + * @param resource path to resource to load + * @return the input stream for the resource + * @throws IOException can be thrown if the loading fails on some error + * or the file cannot be found + */ + public InputStream get(String resource) throws IOException; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,698 +1,1179 @@ -/* -Java 4 Browser Bytecode Translator -Copyright (C) 2012-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. -*/ +/** + * 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; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import org.apidesign.bck2brwsr.core.ExtraJavaScript; import org.apidesign.bck2brwsr.core.JavaScriptBody; -import org.netbeans.modules.classfile.Annotation; -import org.netbeans.modules.classfile.AnnotationComponent; -import org.netbeans.modules.classfile.ArrayElementValue; -import static org.netbeans.modules.classfile.ByteCodes.*; -import org.netbeans.modules.classfile.CPClassInfo; -import org.netbeans.modules.classfile.CPEntry; -import org.netbeans.modules.classfile.CPFieldInfo; -import org.netbeans.modules.classfile.CPMethodInfo; -import org.netbeans.modules.classfile.CPStringInfo; -import org.netbeans.modules.classfile.ClassFile; -import org.netbeans.modules.classfile.ClassName; -import org.netbeans.modules.classfile.Code; -import org.netbeans.modules.classfile.ElementValue; -import org.netbeans.modules.classfile.Method; -import org.netbeans.modules.classfile.Parameter; -import org.netbeans.modules.classfile.PrimitiveElementValue; -import org.netbeans.modules.classfile.Variable; +import org.apidesign.javap.AnnotationParser; +import org.apidesign.javap.ClassData; +import org.apidesign.javap.FieldData; +import org.apidesign.javap.MethodData; +import org.apidesign.javap.StackMapIterator; +import static org.apidesign.javap.RuntimeConstants.*; +import org.apidesign.javap.TrapData; +import org.apidesign.javap.TrapDataIterator; /** Translator of the code inside class files to JavaScript. * * @author Jaroslav Tulach */ -public final class ByteCodeToJavaScript { - private final ClassFile jc; - private final Appendable out; - private final Collection references; +abstract class ByteCodeToJavaScript { + private ClassData jc; + final Appendable out; - private ByteCodeToJavaScript( - ClassFile jc, Appendable out, Collection references - ) { - this.jc = jc; + protected ByteCodeToJavaScript(Appendable out) { this.out = out; - this.references = references; + } + + /* Collects additional required resources. + * + * @param internalClassName classes that were referenced and should be loaded in order the + * generated JavaScript code works properly. The names are in internal + * JVM form so String is java/lang/String. + */ + protected abstract boolean requireReference(String internalClassName); + + /* + * @param resourcePath name of resources to read + */ + protected abstract void requireScript(String resourcePath) throws IOException; + + /** Allows subclasses to redefine what field a function representing a + * class gets assigned. By default it returns the suggested name followed + * by " = "; + * + * @param className suggested name of the class + */ + /* protected */ String assignClass(String className) { + return className + " = "; + } + /* protected */ String accessClass(String classOperation) { + return classOperation; + } + + /** Prints out a debug message. + * + * @param msg the message + * @return true if the message has been printed + * @throws IOException + */ + boolean debug(String msg) throws IOException { + out.append(msg); + return true; } /** * Converts a given class file to a JavaScript version. * * @param classFile input stream with code of the .class file - * @param out a {@link StringBuilder} or similar to generate the output to - * @param references a write only collection where the system adds list of - * other classes that were referenced and should be loaded in order the - * generated JavaScript code works properly. The names are in internal - * JVM form so String is java/lang/String. Can be null - * if one is not interested in knowing references - * @param scripts write only collection with names of resources to read * @return the initialization code for this class, if any. Otherwise null * * @throws IOException if something goes wrong during read or write or translating */ - public static String compile( - InputStream classFile, Appendable out, - Collection references, - Collection scripts - ) throws IOException { - ClassFile jc = new ClassFile(classFile, true); - final ClassName extraAnn = ClassName.getClassName(ExtraJavaScript.class.getName().replace('.', '/')); - Annotation a = jc.getAnnotation(extraAnn); - if (a != null) { - final ElementValue annVal = a.getComponent("resource").getValue(); - String res = ((PrimitiveElementValue)annVal).getValue().getValue().toString(); - scripts.add(res); - final AnnotationComponent process = a.getComponent("processByteCode"); - if (process != null && "const=0".equals(process.getValue().toString())) { + public String compile(InputStream classFile) throws IOException { + this.jc = new ClassData(classFile); + if (jc.getMajor_version() < 50) { + throw new IOException("Can't compile " + jc.getClassName() + ". Class file version " + jc.getMajor_version() + "." + + jc.getMinor_version() + " - recompile with -target 1.6 (at least)." + ); + } + byte[] arrData = jc.findAnnotationData(true); + String[] arr = findAnnotation(arrData, jc, + "org.apidesign.bck2brwsr.core.ExtraJavaScript", + "resource", "processByteCode" + ); + if (arr != null) { + requireScript(arr[0]); + if ("0".equals(arr[1])) { return null; } } - - ByteCodeToJavaScript compiler = new ByteCodeToJavaScript( - jc, out, references + String[] proto = findAnnotation(arrData, jc, + "org.apidesign.bck2brwsr.core.JavaScriptPrototype", + "container", "prototype" ); - List toInitilize = new ArrayList(); - for (Method m : jc.getMethods()) { - if (m.isStatic()) { - compiler.generateStaticMethod(m, toInitilize); - } else { - compiler.generateInstanceMethod(m); + StringArray toInitilize = new StringArray(); + final String className = className(jc); + out.append("\n\n").append(assignClass(className)); + out.append("function CLS() {"); + out.append("\n if (!CLS.prototype.$instOf_").append(className).append(") {"); + for (FieldData v : jc.getFields()) { + if (v.isStatic()) { + out.append("\n CLS.").append(v.getName()).append(initField(v)); } } - for (Variable v : jc.getVariables()) { - if (v.isStatic()) { - compiler.generateStaticField(v); + if (proto == null) { + String sc = jc.getSuperClassName(); // with _ + out.append("\n var pp = "). + append(accessClass(sc.replace('/', '_'))).append("(true);"); + out.append("\n var p = CLS.prototype = pp;"); + out.append("\n var c = p;"); + out.append("\n var sprcls = pp.constructor.$class;"); + } else { + out.append("\n var p = CLS.prototype = ").append(proto[1]).append(";"); + if (proto[0] == null) { + proto[0] = "p"; + } + out.append("\n var c = ").append(proto[0]).append(";"); + out.append("\n var sprcls = null;"); + } + for (MethodData m : jc.getMethods()) { + byte[] onlyArr = m.findAnnotationData(true); + String[] only = findAnnotation(onlyArr, jc, + "org.apidesign.bck2brwsr.core.JavaScriptOnly", + "name", "value" + ); + if (only != null) { + if (only[0] != null && only[1] != null) { + out.append("\n p.").append(only[0]).append(" = ") + .append(only[1]).append(";"); + } + continue; + } + String prefix; + String mn; + if (m.isStatic()) { + prefix = "\n c."; + mn = generateStaticMethod(prefix, m, toInitilize); + } else { + if (m.isConstructor()) { + prefix = "\n CLS."; + mn = generateInstanceMethod(prefix, m); + } else { + prefix = "\n c."; + mn = generateInstanceMethod(prefix, m); + } + } + byte[] runAnno = m.findAnnotationData(false); + if (runAnno != null) { + out.append(prefix).append(mn).append(".anno = {"); + generateAnno(jc, out, runAnno); + out.append("\n };"); + } + out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";"); + } + out.append("\n c.constructor = CLS;"); + out.append("\n c.$instOf_").append(className).append(" = true;"); + for (String superInterface : jc.getSuperInterfaces()) { + out.append("\n c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;"); + } + out.append("\n CLS.$class = "); + out.append(accessClass("java_lang_Class(true);")); + out.append("\n CLS.$class.jvmName = '").append(jc.getClassName()).append("';"); + out.append("\n CLS.$class.superclass = sprcls;"); + out.append("\n CLS.$class.access = ").append(jc.getAccessFlags()+";"); + out.append("\n CLS.$class.cnstr = CLS;"); + byte[] classAnno = jc.findAnnotationData(false); + if (classAnno != null) { + out.append("\n CLS.$class.anno = {"); + generateAnno(jc, out, classAnno); + out.append("\n };"); + } + out.append("\n }"); + out.append("\n if (arguments.length === 0) {"); + out.append("\n if (!(this instanceof CLS)) {"); + out.append("\n return new CLS();"); + out.append("\n }"); + for (FieldData v : jc.getFields()) { + byte[] onlyArr = v.findAnnotationData(true); + String[] only = findAnnotation(onlyArr, jc, + "org.apidesign.bck2brwsr.core.JavaScriptOnly", + "name", "value" + ); + if (only != null) { + if (only[0] != null && only[1] != null) { + out.append("\n p.").append(only[0]).append(" = ") + .append(only[1]).append(";"); + } + continue; + } + if (!v.isStatic()) { + out.append("\n this.fld_"). + append(v.getName()).append(initField(v)); } } - - final String className = jc.getName().getInternalName().replace('/', '_'); - out.append("\nfunction ").append(className); - out.append("() {"); - for (Variable v : jc.getVariables()) { - if (!v.isStatic()) { - out.append("\n this." + v.getName() + " = 0;"); - } - } - out.append("\n}\n\nfunction ").append(className).append("_proto() {"); - out.append("\n if (").append(className). - append(".prototype.$instOf_").append(className).append(") {"); - out.append("\n return ").append(className).append(".prototype;"); + out.append("\n return this;"); out.append("\n }"); - ClassName sc = jc.getSuperClass(); - if (sc != null) { - out.append("\n ").append(sc.getInternalName().replace('/', '_')).append("_proto();"); - out.append("\n ").append(className) - .append(".prototype = new ").append(sc.getInternalName().replace('/', '_')).append(';'); - } - for (Method m : jc.getMethods()) { - if (!m.isStatic() && !m.isPrivate() && !m.getName().contains("")) { - compiler.generateMethodReference("\n " + className + ".prototype.", m); - } - } - out.append("\n " + className + ".prototype.$instOf_").append(className).append(" = true;"); - for (ClassName superInterface : jc.getInterfaces()) { - out.append("\n " + className + ".prototype.$instOf_").append(superInterface.getInternalName().replace('/', '_')).append(" = true;"); - } - out.append("\n return ").append(className).append(".prototype;"); - out.append("\n}"); - out.append("\n").append(className).append("_proto();"); + out.append("\n return arguments[0] ? new CLS() : CLS.prototype;"); + out.append("\n};"); StringBuilder sb = new StringBuilder(); - for (String init : toInitilize) { + for (String init : toInitilize.toArray()) { sb.append("\n").append(init).append("();"); } return sb.toString(); } - private void generateStaticMethod(Method m, List toInitilize) throws IOException { - if (javaScriptBody(m, true)) { + private String generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException { + String jsb = javaScriptBody(prefix, m, true); + if (jsb != null) { + return jsb; + } + final String mn = findMethodName(m, new StringBuilder()); + if (mn.equals("class__V")) { + toInitilize.add(accessClass(className(jc)) + "(false)." + mn); + } + generateMethod(prefix, mn, m); + return mn; + } + + private String generateInstanceMethod(String prefix, MethodData m) throws IOException { + String jsb = javaScriptBody(prefix, m, false); + if (jsb != null) { + return jsb; + } + final String mn = findMethodName(m, new StringBuilder()); + generateMethod(prefix, mn, m); + return mn; + } + + private void generateMethod(String prefix, String name, MethodData m) + throws IOException { + final StackMapIterator stackMapIterator = m.createStackMapIterator(); + TrapDataIterator trap = m.getTrapDataIterator(); + final LocalsMapper lmapper = + new LocalsMapper(stackMapIterator.getArguments()); + + out.append(prefix).append(name).append(" = function("); + lmapper.outputArguments(out, m.isStatic()); + out.append(") {").append("\n"); + + final byte[] byteCodes = m.getCode(); + if (byteCodes == null) { + out.append(" throw 'no code found for ") + .append(jc.getClassName()).append('.') + .append(m.getName()).append("';\n"); + out.append("};"); return; } - final String mn = findMethodName(m); - out.append("\nfunction ").append( - jc.getName().getInternalName().replace('/', '_') - ).append('_').append(mn); - if (mn.equals("classV")) { - toInitilize.add(jc.getName().getInternalName().replace('/', '_') + '_' + mn); + + final StackMapper smapper = new StackMapper(); + + if (!m.isStatic()) { + out.append(" var ").append(" lcA0 = this;\n"); } - out.append('('); - String space = ""; - List args = m.getParameters(); - for (int index = 0, i = 0; i < args.size(); i++) { - out.append(space); - out.append("arg").append(String.valueOf(index)); - space = ","; - final String desc = findDescriptor(args.get(i).getDescriptor()); - if ("D".equals(desc) || "J".equals(desc)) { - index += 2; - } else { - index++; - } - } - out.append(") {").append("\n"); - final Code code = m.getCode(); - if (code != null) { - int len = code.getMaxLocals(); - for (int index = args.size(), i = args.size(); i < len; i++) { - out.append(" var "); - out.append("arg").append(String.valueOf(i)).append(";\n"); - } - out.append(" var stack = new Array();\n"); - produceCode(code.getByteCodes()); - } else { - out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n"); - } - out.append("}"); - } - - private void generateMethodReference(String prefix, Method m) throws IOException { - final String name = findMethodName(m); - out.append(prefix).append(name).append(" = ") - .append(jc.getName().getInternalName().replace('/', '_')) - .append('_').append(name).append(";"); - } - - private void generateInstanceMethod(Method m) throws IOException { - if (javaScriptBody(m, false)) { - return; - } - out.append("\nfunction ").append( - jc.getName().getInternalName().replace('/', '_') - ).append('_').append(findMethodName(m)); - out.append("(arg0"); - String space = ","; - List args = m.getParameters(); - for (int index = 1, i = 0; i < args.size(); i++) { - out.append(space); - out.append("arg").append(String.valueOf(index)); - final String desc = findDescriptor(args.get(i).getDescriptor()); - if ("D".equals(desc) || "J".equals(desc)) { - index += 2; - } else { - index++; - } - } - out.append(") {").append("\n"); - final Code code = m.getCode(); - if (code != null) { - int len = code.getMaxLocals(); - for (int index = args.size(), i = args.size(); i < len; i++) { - out.append(" var "); - out.append("arg").append(String.valueOf(i + 1)).append(";\n"); - } - out.append(";\n var stack = new Array();\n"); - produceCode(code.getByteCodes()); - } else { - out.append(" /* no code found for ").append(m.getTypeSignature()).append(" */\n"); - } - out.append("}"); - } - private void produceCode(byte[] byteCodes) throws IOException { + int lastStackFrame = -1; + TrapData[] previousTrap = null; + out.append("\n var gt = 0;\n for(;;) switch(gt) {\n"); for (int i = 0; i < byteCodes.length; i++) { int prev = i; - out.append(" case " + i).append(": "); - final int c = (byteCodes[i] + 256) % 256; + stackMapIterator.advanceTo(i); + boolean changeInCatch = trap.advanceTo(i); + if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) { + if (previousTrap != null) { + generateCatch(previousTrap); + previousTrap = null; + } + } + if (lastStackFrame != stackMapIterator.getFrameIndex()) { + lastStackFrame = stackMapIterator.getFrameIndex(); + lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals()); + smapper.syncWithFrameStack(stackMapIterator.getFrameStack()); + out.append(" case " + i).append(": "); + changeInCatch = true; + } else { + debug(" /* " + i + " */ "); + } + if (changeInCatch && trap.useTry()) { + out.append("try {"); + previousTrap = trap.current(); + } + final int c = readByte(byteCodes, i); switch (c) { - case bc_aload_0: - case bc_iload_0: - case bc_lload_0: - case bc_fload_0: - case bc_dload_0: - out.append("stack.push(arg0);"); + case opc_aload_0: + emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(0)); break; - case bc_aload_1: - case bc_iload_1: - case bc_lload_1: - case bc_fload_1: - case bc_dload_1: - out.append("stack.push(arg1);"); + case opc_iload_0: + emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(0)); break; - case bc_aload_2: - case bc_iload_2: - case bc_lload_2: - case bc_fload_2: - case bc_dload_2: - out.append("stack.push(arg2);"); + case opc_lload_0: + emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(0)); break; - case bc_aload_3: - case bc_iload_3: - case bc_lload_3: - case bc_fload_3: - case bc_dload_3: - out.append("stack.push(arg3);"); + case opc_fload_0: + emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(0)); break; - case bc_iload: - case bc_lload: - case bc_fload: - case bc_dload: - case bc_aload: { - final int indx = (byteCodes[++i] + 256) % 256; - out.append("stack.push(arg").append(indx + ");"); + case opc_dload_0: + emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(0)); + break; + case opc_aload_1: + emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(1)); + break; + case opc_iload_1: + emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(1)); + break; + case opc_lload_1: + emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(1)); + break; + case opc_fload_1: + emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(1)); + break; + case opc_dload_1: + emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(1)); + break; + case opc_aload_2: + emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(2)); + break; + case opc_iload_2: + emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(2)); + break; + case opc_lload_2: + emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(2)); + break; + case opc_fload_2: + emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(2)); + break; + case opc_dload_2: + emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(2)); + break; + case opc_aload_3: + emit(out, "var @1 = @2;", smapper.pushA(), lmapper.getA(3)); + break; + case opc_iload_3: + emit(out, "var @1 = @2;", smapper.pushI(), lmapper.getI(3)); + break; + case opc_lload_3: + emit(out, "var @1 = @2;", smapper.pushL(), lmapper.getL(3)); + break; + case opc_fload_3: + emit(out, "var @1 = @2;", smapper.pushF(), lmapper.getF(3)); + break; + case opc_dload_3: + emit(out, "var @1 = @2;", smapper.pushD(), lmapper.getD(3)); + break; + case opc_iload: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + smapper.pushI(), lmapper.getI(indx)); break; } - case bc_istore: - case bc_lstore: - case bc_fstore: - case bc_dstore: - case bc_astore: { - final int indx = (byteCodes[++i] + 256) % 256; - out.append("arg" + indx).append(" = stack.pop()"); + case opc_lload: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + smapper.pushL(), lmapper.getL(indx)); break; } - case bc_astore_0: - case bc_istore_0: - case bc_lstore_0: - case bc_fstore_0: - case bc_dstore_0: - out.append("arg0 = stack.pop();"); + case opc_fload: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + smapper.pushF(), lmapper.getF(indx)); break; - case bc_astore_1: - case bc_istore_1: - case bc_lstore_1: - case bc_fstore_1: - case bc_dstore_1: - out.append("arg1 = stack.pop();"); + } + case opc_dload: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + smapper.pushD(), lmapper.getD(indx)); break; - case bc_astore_2: - case bc_istore_2: - case bc_lstore_2: - case bc_fstore_2: - case bc_dstore_2: - out.append("arg2 = stack.pop();"); + } + case opc_aload: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + smapper.pushA(), lmapper.getA(indx)); break; - case bc_astore_3: - case bc_istore_3: - case bc_lstore_3: - case bc_fstore_3: - case bc_dstore_3: - out.append("arg3 = stack.pop();"); + } + case opc_istore: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + lmapper.setI(indx), smapper.popI()); break; - case bc_iadd: - case bc_ladd: - case bc_fadd: - case bc_dadd: - out.append("stack.push(stack.pop() + stack.pop());"); + } + case opc_lstore: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + lmapper.setL(indx), smapper.popL()); break; - case bc_isub: - case bc_lsub: - case bc_fsub: - case bc_dsub: - out.append("{ var tmp = stack.pop(); stack.push(stack.pop() - tmp); }"); + } + case opc_fstore: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + lmapper.setF(indx), smapper.popF()); break; - case bc_imul: - case bc_lmul: - case bc_fmul: - case bc_dmul: - out.append("stack.push(stack.pop() * stack.pop());"); + } + case opc_dstore: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + lmapper.setD(indx), smapper.popD()); break; - case bc_idiv: - case bc_ldiv: - out.append("{ var tmp = stack.pop(); stack.push(Math.floor(stack.pop() / tmp)); }"); + } + case opc_astore: { + final int indx = readByte(byteCodes, ++i); + emit(out, "var @1 = @2;", + lmapper.setA(indx), smapper.popA()); break; - case bc_fdiv: - case bc_ddiv: - out.append("{ var tmp = stack.pop(); stack.push(stack.pop() / tmp); }"); + } + case opc_astore_0: + emit(out, "var @1 = @2;", lmapper.setA(0), smapper.popA()); break; - case bc_iand: - case bc_land: - out.append("stack.push(stack.pop() & stack.pop());"); + case opc_istore_0: + emit(out, "var @1 = @2;", lmapper.setI(0), smapper.popI()); break; - case bc_ior: - case bc_lor: - out.append("stack.push(stack.pop() | stack.pop());"); + case opc_lstore_0: + emit(out, "var @1 = @2;", lmapper.setL(0), smapper.popL()); break; - case bc_ixor: - case bc_lxor: - out.append("stack.push(stack.pop() ^ stack.pop());"); + case opc_fstore_0: + emit(out, "var @1 = @2;", lmapper.setF(0), smapper.popF()); break; - case bc_ineg: - case bc_lneg: - case bc_fneg: - case bc_dneg: - out.append("stack.push(- stack.pop());"); + case opc_dstore_0: + emit(out, "var @1 = @2;", lmapper.setD(0), smapper.popD()); break; - case bc_ishl: - case bc_lshl: - out.append("{ var v = stack.pop(); stack.push(stack.pop() << v); }"); + case opc_astore_1: + emit(out, "var @1 = @2;", lmapper.setA(1), smapper.popA()); break; - case bc_ishr: - case bc_lshr: - out.append("{ var v = stack.pop(); stack.push(stack.pop() >> v); }"); + case opc_istore_1: + emit(out, "var @1 = @2;", lmapper.setI(1), smapper.popI()); break; - case bc_iushr: - case bc_lushr: - out.append("{ var v = stack.pop(); stack.push(stack.pop() >>> v); }"); + case opc_lstore_1: + emit(out, "var @1 = @2;", lmapper.setL(1), smapper.popL()); break; - case bc_iinc: { - final int varIndx = (byteCodes[++i] + 256) % 256; - final int incrBy = (byteCodes[++i] + 256) % 256; + case opc_fstore_1: + emit(out, "var @1 = @2;", lmapper.setF(1), smapper.popF()); + break; + case opc_dstore_1: + emit(out, "var @1 = @2;", lmapper.setD(1), smapper.popD()); + break; + case opc_astore_2: + emit(out, "var @1 = @2;", lmapper.setA(2), smapper.popA()); + break; + case opc_istore_2: + emit(out, "var @1 = @2;", lmapper.setI(2), smapper.popI()); + break; + case opc_lstore_2: + emit(out, "var @1 = @2;", lmapper.setL(2), smapper.popL()); + break; + case opc_fstore_2: + emit(out, "var @1 = @2;", lmapper.setF(2), smapper.popF()); + break; + case opc_dstore_2: + emit(out, "var @1 = @2;", lmapper.setD(2), smapper.popD()); + break; + case opc_astore_3: + emit(out, "var @1 = @2;", lmapper.setA(3), smapper.popA()); + break; + case opc_istore_3: + emit(out, "var @1 = @2;", lmapper.setI(3), smapper.popI()); + break; + case opc_lstore_3: + emit(out, "var @1 = @2;", lmapper.setL(3), smapper.popL()); + break; + case opc_fstore_3: + emit(out, "var @1 = @2;", lmapper.setF(3), smapper.popF()); + break; + case opc_dstore_3: + emit(out, "var @1 = @2;", lmapper.setD(3), smapper.popD()); + break; + case opc_iadd: + emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI()); + break; + case opc_ladd: + emit(out, "@1 += @2;", smapper.getL(1), smapper.popL()); + break; + case opc_fadd: + emit(out, "@1 += @2;", smapper.getF(1), smapper.popF()); + break; + case opc_dadd: + emit(out, "@1 += @2;", smapper.getD(1), smapper.popD()); + break; + case opc_isub: + emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI()); + break; + case opc_lsub: + emit(out, "@1 -= @2;", smapper.getL(1), smapper.popL()); + break; + case opc_fsub: + emit(out, "@1 -= @2;", smapper.getF(1), smapper.popF()); + break; + case opc_dsub: + emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD()); + break; + case opc_imul: + emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI()); + break; + case opc_lmul: + emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL()); + break; + case opc_fmul: + emit(out, "@1 *= @2;", smapper.getF(1), smapper.popF()); + break; + case opc_dmul: + emit(out, "@1 *= @2;", smapper.getD(1), smapper.popD()); + break; + case opc_idiv: + emit(out, "@1 = Math.floor(@1 / @2);", + smapper.getI(1), smapper.popI()); + break; + case opc_ldiv: + emit(out, "@1 = Math.floor(@1 / @2);", + smapper.getL(1), smapper.popL()); + break; + case opc_fdiv: + emit(out, "@1 /= @2;", smapper.getF(1), smapper.popF()); + break; + case opc_ddiv: + emit(out, "@1 /= @2;", smapper.getD(1), smapper.popD()); + break; + case opc_irem: + emit(out, "@1 %= @2;", smapper.getI(1), smapper.popI()); + break; + case opc_lrem: + emit(out, "@1 %= @2;", smapper.getL(1), smapper.popL()); + break; + case opc_frem: + emit(out, "@1 %= @2;", smapper.getF(1), smapper.popF()); + break; + case opc_drem: + emit(out, "@1 %= @2;", smapper.getD(1), smapper.popD()); + break; + case opc_iand: + emit(out, "@1 &= @2;", smapper.getI(1), smapper.popI()); + break; + case opc_land: + emit(out, "@1 &= @2;", smapper.getL(1), smapper.popL()); + break; + case opc_ior: + emit(out, "@1 |= @2;", smapper.getI(1), smapper.popI()); + break; + case opc_lor: + emit(out, "@1 |= @2;", smapper.getL(1), smapper.popL()); + break; + case opc_ixor: + emit(out, "@1 ^= @2;", smapper.getI(1), smapper.popI()); + break; + case opc_lxor: + emit(out, "@1 ^= @2;", smapper.getL(1), smapper.popL()); + break; + case opc_ineg: + emit(out, "@1 = -@1;", smapper.getI(0)); + break; + case opc_lneg: + emit(out, "@1 = -@1;", smapper.getL(0)); + break; + case opc_fneg: + emit(out, "@1 = -@1;", smapper.getF(0)); + break; + case opc_dneg: + emit(out, "@1 = -@1;", smapper.getD(0)); + break; + case opc_ishl: + emit(out, "@1 <<= @2;", smapper.getI(1), smapper.popI()); + break; + case opc_lshl: + emit(out, "@1 <<= @2;", smapper.getL(1), smapper.popI()); + break; + case opc_ishr: + emit(out, "@1 >>= @2;", smapper.getI(1), smapper.popI()); + break; + case opc_lshr: + emit(out, "@1 >>= @2;", smapper.getL(1), smapper.popI()); + break; + case opc_iushr: + emit(out, "@1 >>>= @2;", smapper.getI(1), smapper.popI()); + break; + case opc_lushr: + emit(out, "@1 >>>= @2;", smapper.getL(1), smapper.popI()); + break; + case opc_iinc: { + final int varIndx = readByte(byteCodes, ++i); + final int incrBy = byteCodes[++i]; if (incrBy == 1) { - out.append("arg" + varIndx).append("++;"); + emit(out, "@1++;", lmapper.getI(varIndx)); } else { - out.append("arg" + varIndx).append(" += " + incrBy).append(";"); + emit(out, "@1 += @2;", + lmapper.getI(varIndx), + Integer.toString(incrBy)); } break; } - case bc_return: - out.append("return;"); + case opc_return: + emit(out, "return;"); break; - case bc_ireturn: - case bc_lreturn: - case bc_freturn: - case bc_dreturn: - case bc_areturn: - out.append("return stack.pop();"); + case opc_ireturn: + emit(out, "return @1;", smapper.popI()); break; - case bc_i2l: - case bc_i2f: - case bc_i2d: - case bc_l2i: + case opc_lreturn: + emit(out, "return @1;", smapper.popL()); + break; + case opc_freturn: + emit(out, "return @1;", smapper.popF()); + break; + case opc_dreturn: + emit(out, "return @1;", smapper.popD()); + break; + case opc_areturn: + emit(out, "return @1;", smapper.popA()); + break; + case opc_i2l: + emit(out, "var @2 = @1;", smapper.popI(), smapper.pushL()); + break; + case opc_i2f: + emit(out, "var @2 = @1;", smapper.popI(), smapper.pushF()); + break; + case opc_i2d: + emit(out, "var @2 = @1;", smapper.popI(), smapper.pushD()); + break; + case opc_l2i: + emit(out, "var @2 = @1;", smapper.popL(), smapper.pushI()); + break; // max int check? - case bc_l2f: - case bc_l2d: - case bc_f2d: - case bc_d2f: - out.append("/* number conversion */"); + case opc_l2f: + emit(out, "var @2 = @1;", smapper.popL(), smapper.pushF()); break; - case bc_f2i: - case bc_f2l: - case bc_d2i: - case bc_d2l: - out.append("stack.push(Math.floor(stack.pop()));"); + case opc_l2d: + emit(out, "var @2 = @1;", smapper.popL(), smapper.pushD()); break; - case bc_i2b: - case bc_i2c: - case bc_i2s: - out.append("/* number conversion */"); + case opc_f2d: + emit(out, "var @2 = @1;", smapper.popF(), smapper.pushD()); break; - case bc_aconst_null: - out.append("stack.push(null);"); + case opc_d2f: + emit(out, "var @2 = @1;", smapper.popD(), smapper.pushF()); break; - case bc_iconst_m1: - out.append("stack.push(-1);"); + case opc_f2i: + emit(out, "var @2 = Math.floor(@1);", + smapper.popF(), smapper.pushI()); break; - case bc_iconst_0: - case bc_dconst_0: - case bc_lconst_0: - case bc_fconst_0: - out.append("stack.push(0);"); + case opc_f2l: + emit(out, "var @2 = Math.floor(@1);", + smapper.popF(), smapper.pushL()); break; - case bc_iconst_1: - case bc_lconst_1: - case bc_fconst_1: - case bc_dconst_1: - out.append("stack.push(1);"); + case opc_d2i: + emit(out, "var @2 = Math.floor(@1);", + smapper.popD(), smapper.pushI()); break; - case bc_iconst_2: - case bc_fconst_2: - out.append("stack.push(2);"); + case opc_d2l: + emit(out, "var @2 = Math.floor(@1);", + smapper.popD(), smapper.pushL()); break; - case bc_iconst_3: - out.append("stack.push(3);"); + case opc_i2b: + emit(out, "var @1 = @1.toInt8();", smapper.getI(0)); break; - case bc_iconst_4: - out.append("stack.push(4);"); + case opc_i2c: + out.append("{ /* number conversion */ }"); break; - case bc_iconst_5: - out.append("stack.push(5);"); + case opc_i2s: + emit(out, "var @1 = @1.toInt16();", smapper.getI(0)); break; - case bc_ldc: { - int indx = byteCodes[++i]; - CPEntry entry = jc.getConstantPool().get(indx); - String v = encodeConstant(entry); - out.append("stack.push(").append(v).append(");"); + case opc_aconst_null: + emit(out, "var @1 = null;", smapper.pushA()); + break; + case opc_iconst_m1: + emit(out, "var @1 = -1;", smapper.pushI()); + break; + case opc_iconst_0: + emit(out, "var @1 = 0;", smapper.pushI()); + break; + case opc_dconst_0: + emit(out, "var @1 = 0;", smapper.pushD()); + break; + case opc_lconst_0: + emit(out, "var @1 = 0;", smapper.pushL()); + break; + case opc_fconst_0: + emit(out, "var @1 = 0;", smapper.pushF()); + break; + case opc_iconst_1: + emit(out, "var @1 = 1;", smapper.pushI()); + break; + case opc_lconst_1: + emit(out, "var @1 = 1;", smapper.pushL()); + break; + case opc_fconst_1: + emit(out, "var @1 = 1;", smapper.pushF()); + break; + case opc_dconst_1: + emit(out, "var @1 = 1;", smapper.pushD()); + break; + case opc_iconst_2: + emit(out, "var @1 = 2;", smapper.pushI()); + break; + case opc_fconst_2: + emit(out, "var @1 = 2;", smapper.pushF()); + break; + case opc_iconst_3: + emit(out, "var @1 = 3;", smapper.pushI()); + break; + case opc_iconst_4: + emit(out, "var @1 = 4;", smapper.pushI()); + break; + case opc_iconst_5: + emit(out, "var @1 = 5;", smapper.pushI()); + break; + case opc_ldc: { + int indx = readByte(byteCodes, ++i); + String v = encodeConstant(indx); + int type = VarType.fromConstantType(jc.getTag(indx)); + emit(out, "var @1 = @2;", smapper.pushT(type), v); break; } - case bc_ldc_w: - case bc_ldc2_w: { + case opc_ldc_w: + case opc_ldc2_w: { int indx = readIntArg(byteCodes, i); - CPEntry entry = jc.getConstantPool().get(indx); i += 2; - String v = encodeConstant(entry); - out.append("stack.push(").append(v).append(");"); + String v = encodeConstant(indx); + int type = VarType.fromConstantType(jc.getTag(indx)); + emit(out, "var @1 = @2;", smapper.pushT(type), v); break; } - case bc_lcmp: - case bc_fcmpl: - case bc_fcmpg: - case bc_dcmpl: - case bc_dcmpg: { - out.append("{ var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); }"); + case opc_lcmp: + emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);", + smapper.popL(), smapper.popL(), smapper.pushI()); break; - } - case bc_if_icmpeq: { - i = generateIf(byteCodes, i, "=="); + case opc_fcmpl: + case opc_fcmpg: + emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);", + smapper.popF(), smapper.popF(), smapper.pushI()); break; - } - case bc_ifeq: { + case opc_dcmpl: + case opc_dcmpg: + emit(out, "var @3 = (@2 == @1) ? 0 : ((@2 < @1) ? -1 : 1);", + smapper.popD(), smapper.popD(), smapper.pushI()); + break; + case opc_if_acmpeq: + i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(), + "==="); + break; + case opc_if_acmpne: + i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(), + "!="); + break; + case opc_if_icmpeq: + i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), + "=="); + break; + case opc_ifeq: { int indx = i + readIntArg(byteCodes, i); - out.append("if (stack.pop() == 0) { gt = " + indx); - out.append("; continue; }"); + emit(out, "if (@1 == 0) { gt = @2; continue; }", + smapper.popI(), Integer.toString(indx)); i += 2; break; } - case bc_ifne: { + case opc_ifne: { int indx = i + readIntArg(byteCodes, i); - out.append("if (stack.pop() != 0) { gt = " + indx); - out.append("; continue; }"); + emit(out, "if (@1 != 0) { gt = @2; continue; }", + smapper.popI(), Integer.toString(indx)); i += 2; break; } - case bc_iflt: { + case opc_iflt: { int indx = i + readIntArg(byteCodes, i); - out.append("if (stack.pop() < 0) { gt = " + indx); - out.append("; continue; }"); + emit(out, "if (@1 < 0) { gt = @2; continue; }", + smapper.popI(), Integer.toString(indx)); i += 2; break; } - case bc_ifle: { + case opc_ifle: { int indx = i + readIntArg(byteCodes, i); - out.append("if (stack.pop() <= 0) { gt = " + indx); - out.append("; continue; }"); + emit(out, "if (@1 <= 0) { gt = @2; continue; }", + smapper.popI(), Integer.toString(indx)); i += 2; break; } - case bc_ifgt: { + case opc_ifgt: { int indx = i + readIntArg(byteCodes, i); - out.append("if (stack.pop() > 0) { gt = " + indx); - out.append("; continue; }"); + emit(out, "if (@1 > 0) { gt = @2; continue; }", + smapper.popI(), Integer.toString(indx)); i += 2; break; } - case bc_ifge: { + case opc_ifge: { int indx = i + readIntArg(byteCodes, i); - out.append("if (stack.pop() >= 0) { gt = " + indx); - out.append("; continue; }"); + emit(out, "if (@1 >= 0) { gt = @2; continue; }", + smapper.popI(), Integer.toString(indx)); i += 2; break; } - case bc_ifnonnull: { + case opc_ifnonnull: { int indx = i + readIntArg(byteCodes, i); - out.append("if (stack.pop()) { gt = " + indx); - out.append("; continue; }"); + emit(out, "if (@1 !== null) { gt = @2; continue; }", + smapper.popA(), Integer.toString(indx)); i += 2; break; } - case bc_ifnull: { + case opc_ifnull: { int indx = i + readIntArg(byteCodes, i); - out.append("if (!stack.pop()) { gt = " + indx); - out.append("; continue; }"); + emit(out, "if (@1 === null) { gt = @2; continue; }", + smapper.popA(), Integer.toString(indx)); i += 2; break; } - case bc_if_icmpne: - i = generateIf(byteCodes, i, "!="); + case opc_if_icmpne: + i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), + "!="); break; - case bc_if_icmplt: - i = generateIf(byteCodes, i, ">"); + case opc_if_icmplt: + i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), + "<"); break; - case bc_if_icmple: - i = generateIf(byteCodes, i, ">="); + case opc_if_icmple: + i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), + "<="); break; - case bc_if_icmpgt: - i = generateIf(byteCodes, i, "<"); + case opc_if_icmpgt: + i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), + ">"); break; - case bc_if_icmpge: - i = generateIf(byteCodes, i, "<="); + case opc_if_icmpge: + i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(), + ">="); break; - case bc_goto: { + case opc_goto: { int indx = i + readIntArg(byteCodes, i); - out.append("gt = " + indx).append("; continue;"); + emit(out, "gt = @1; continue;", Integer.toString(indx)); i += 2; break; } - case bc_invokeinterface: { - i = invokeVirtualMethod(byteCodes, i) + 2; + case opc_lookupswitch: { + int table = i / 4 * 4 + 4; + int dflt = i + readInt4(byteCodes, table); + table += 4; + int n = readInt4(byteCodes, table); + table += 4; + out.append("switch (").append(smapper.popI()).append(") {\n"); + while (n-- > 0) { + int cnstnt = readInt4(byteCodes, table); + table += 4; + int offset = i + readInt4(byteCodes, table); + table += 4; + out.append(" case " + cnstnt).append(": gt = " + offset).append("; continue;\n"); + } + out.append(" default: gt = " + dflt).append("; continue;\n}"); + i = table - 1; break; } - case bc_invokevirtual: - i = invokeVirtualMethod(byteCodes, i); + case opc_tableswitch: { + int table = i / 4 * 4 + 4; + int dflt = i + readInt4(byteCodes, table); + table += 4; + int low = readInt4(byteCodes, table); + table += 4; + int high = readInt4(byteCodes, table); + table += 4; + out.append("switch (").append(smapper.popI()).append(") {\n"); + while (low <= high) { + int offset = i + readInt4(byteCodes, table); + table += 4; + out.append(" case " + low).append(": gt = " + offset).append("; continue;\n"); + low++; + } + out.append(" default: gt = " + dflt).append("; continue;\n}"); + i = table - 1; break; - case bc_invokespecial: - i = invokeStaticMethod(byteCodes, i, false); + } + case opc_invokeinterface: { + i = invokeVirtualMethod(byteCodes, i, smapper) + 2; break; - case bc_invokestatic: - i = invokeStaticMethod(byteCodes, i, true); + } + case opc_invokevirtual: + i = invokeVirtualMethod(byteCodes, i, smapper); break; - case bc_new: { + case opc_invokespecial: + i = invokeStaticMethod(byteCodes, i, smapper, false); + break; + case opc_invokestatic: + i = invokeStaticMethod(byteCodes, i, smapper, true); + break; + case opc_new: { int indx = readIntArg(byteCodes, i); - CPClassInfo ci = jc.getConstantPool().getClass(indx); - out.append("stack.push("); - out.append("new ").append(ci.getClassName().getInternalName().replace('/','_')); - out.append(");"); - addReference(ci.getClassName().getInternalName()); + String ci = jc.getClassName(indx); + emit(out, "var @1 = new @2;", + smapper.pushA(), accessClass(ci.replace('/', '_'))); + addReference(ci); i += 2; break; } - case bc_newarray: { - int type = byteCodes[i++]; - out.append("stack.push(new Array(stack.pop()));"); + case opc_newarray: + int atype = readByte(byteCodes, ++i); + String jvmType; + switch (atype) { + case 4: jvmType = "[Z"; break; + case 5: jvmType = "[C"; break; + case 6: jvmType = "[F"; break; + case 7: jvmType = "[D"; break; + case 8: jvmType = "[B"; break; + case 9: jvmType = "[S"; break; + case 10: jvmType = "[I"; break; + case 11: jvmType = "[J"; break; + default: throw new IllegalStateException("Array type: " + atype); + } + emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);", + smapper.popI(), smapper.pushA(), jvmType); + break; + case opc_anewarray: { + int type = readIntArg(byteCodes, i); + i += 2; + String typeName = jc.getClassName(type); + if (typeName.startsWith("[")) { + typeName = "[" + typeName; + } else { + typeName = "[L" + typeName + ";"; + } + emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);", + smapper.popI(), smapper.pushA(), typeName); break; } - case bc_anewarray: { - i += 2; // skip type of array - out.append("stack.push(new Array(stack.pop()));"); + case opc_multianewarray: { + int type = readIntArg(byteCodes, i); + i += 2; + String typeName = jc.getClassName(type); + int dim = readByte(byteCodes, ++i); + StringBuilder dims = new StringBuilder(); + dims.append('['); + for (int d = 0; d < dim; d++) { + if (d != 0) { + dims.append(","); + } + dims.append(smapper.popI()); + } + dims.append(']'); + emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);", + dims.toString(), smapper.pushA(), typeName); break; } - case bc_arraylength: - out.append("stack.push(stack.pop().length);"); + case opc_arraylength: + emit(out, "var @2 = @1.length;", + smapper.popA(), smapper.pushI()); break; - case bc_iastore: - case bc_lastore: - case bc_fastore: - case bc_dastore: - case bc_aastore: - case bc_bastore: - case bc_castore: - case bc_sastore: { - out.append("{ var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; }"); + case opc_lastore: + emit(out, "@3.at(@2, @1);", + smapper.popL(), smapper.popI(), smapper.popA()); + break; + case opc_fastore: + emit(out, "@3.at(@2, @1);", + smapper.popF(), smapper.popI(), smapper.popA()); + break; + case opc_dastore: + emit(out, "@3.at(@2, @1);", + smapper.popD(), smapper.popI(), smapper.popA()); + break; + case opc_aastore: + emit(out, "@3.at(@2, @1);", + smapper.popA(), smapper.popI(), smapper.popA()); + break; + case opc_iastore: + case opc_bastore: + case opc_castore: + case opc_sastore: + emit(out, "@3.at(@2, @1);", + smapper.popI(), smapper.popI(), smapper.popA()); + break; + case opc_laload: + emit(out, "var @3 = @2.at(@1);", + smapper.popI(), smapper.popA(), smapper.pushL()); + break; + case opc_faload: + emit(out, "var @3 = @2.at(@1);", + smapper.popI(), smapper.popA(), smapper.pushF()); + break; + case opc_daload: + emit(out, "var @3 = @2.at(@1);", + smapper.popI(), smapper.popA(), smapper.pushD()); + break; + case opc_aaload: + emit(out, "var @3 = @2.at(@1);", + smapper.popI(), smapper.popA(), smapper.pushA()); + break; + case opc_iaload: + case opc_baload: + case opc_caload: + case opc_saload: + emit(out, "var @3 = @2.at(@1);", + smapper.popI(), smapper.popA(), smapper.pushI()); + break; + case opc_pop: + case opc_pop2: + smapper.pop(1); + debug("/* pop */"); + break; + case opc_dup: { + final Variable v = smapper.get(0); + emit(out, "var @1 = @2;", smapper.pushT(v.getType()), v); break; } - case bc_iaload: - case bc_laload: - case bc_faload: - case bc_daload: - case bc_aaload: - case bc_baload: - case bc_caload: - case bc_saload: { - out.append("{ var indx = stack.pop(); stack.push(stack.pop()[indx]); }"); + case opc_dup2: { + if (smapper.get(0).isCategory2()) { + final Variable v = smapper.get(0); + emit(out, "var @1 = @2;", + smapper.pushT(v.getType()), v); + } else { + final Variable v1 = smapper.get(0); + final Variable v2 = smapper.get(1); + emit(out, "var @1 = @2, @3 = @4;", + smapper.pushT(v2.getType()), v2, + smapper.pushT(v1.getType()), v1); + } break; } - case bc_pop2: - out.append("stack.pop();"); - case bc_pop: - out.append("stack.pop();"); + case opc_dup_x1: { + final Variable vi1 = smapper.pop(); + final Variable vi2 = smapper.pop(); + final Variable vo3 = smapper.pushT(vi1.getType()); + final Variable vo2 = smapper.pushT(vi2.getType()); + final Variable vo1 = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @3 = @4, @5 = @6;", + vo1, vi1, vo2, vi2, vo3, vo1); break; - case bc_dup: - out.append("stack.push(stack[stack.length - 1]);"); + } + case opc_dup_x2: { + if (smapper.get(1).isCategory2()) { + final Variable vi1 = smapper.pop(); + final Variable vi2 = smapper.pop(); + final Variable vo3 = smapper.pushT(vi1.getType()); + final Variable vo2 = smapper.pushT(vi2.getType()); + final Variable vo1 = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @3 = @4, @5 = @6;", + vo1, vi1, vo2, vi2, vo3, vo1); + } else { + final Variable vi1 = smapper.pop(); + final Variable vi2 = smapper.pop(); + final Variable vi3 = smapper.pop(); + final Variable vo4 = smapper.pushT(vi1.getType()); + final Variable vo3 = smapper.pushT(vi3.getType()); + final Variable vo2 = smapper.pushT(vi2.getType()); + final Variable vo1 = smapper.pushT(vi1.getType()); + + emit(out, "var @1 = @2, @3 = @4, @5 = @6, @7 = @8;", + vo1, vi1, vo2, vi2, vo3, vi3, vo4, vo1); + } break; - case bc_bipush: - out.append("stack.push(" + byteCodes[++i] + ");"); + } + case opc_bipush: + emit(out, "var @1 = @2;", + smapper.pushI(), Integer.toString(byteCodes[++i])); break; - case bc_sipush: - out.append("stack.push(" + readIntArg(byteCodes, i) + ");"); + case opc_sipush: + emit(out, "var @1 = @2;", + smapper.pushI(), + Integer.toString(readIntArg(byteCodes, i))); i += 2; break; - case bc_getfield: { + case opc_getfield: { int indx = readIntArg(byteCodes, i); - CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx); - out.append("stack.push(stack.pop().").append(fi.getFieldName()).append(");"); + String[] fi = jc.getFieldInfoName(indx); + final int type = VarType.fromFieldType(fi[2].charAt(0)); + emit(out, "var @2 = @1.fld_@3;", + smapper.popA(), smapper.pushT(type), fi[1]); i += 2; break; } - case bc_getstatic: { + case opc_getstatic: { int indx = readIntArg(byteCodes, i); - CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx); - final String in = fi.getClassName().getInternalName(); - out.append("stack.push(").append(in.replace('/', '_')); - out.append('_').append(fi.getFieldName()).append(");"); + String[] fi = jc.getFieldInfoName(indx); + final int type = VarType.fromFieldType(fi[2].charAt(0)); + emit(out, "var @1 = @2(false).constructor.@3;", + smapper.pushT(type), + accessClass(fi[0].replace('/', '_')), fi[1]); i += 2; - addReference(in); + addReference(fi[0]); break; } - case bc_putstatic: { + case opc_putfield: { int indx = readIntArg(byteCodes, i); - CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx); - final String in = fi.getClassName().getInternalName(); - out.append(in.replace('/', '_')); - out.append('_').append(fi.getFieldName()).append(" = stack.pop();"); - i += 2; - addReference(in); - break; - } - case bc_putfield: { - int indx = readIntArg(byteCodes, i); - CPFieldInfo fi = (CPFieldInfo) jc.getConstantPool().get(indx); - out.append("{ var v = stack.pop(); stack.pop().") - .append(fi.getFieldName()).append(" = v; }"); + String[] fi = jc.getFieldInfoName(indx); + final int type = VarType.fromFieldType(fi[2].charAt(0)); + emit(out, "@2.fld_@3 = @1;", + smapper.popT(type), smapper.popA(), fi[1]); i += 2; break; } - case bc_checkcast: { + case opc_putstatic: { int indx = readIntArg(byteCodes, i); - CPClassInfo ci = jc.getConstantPool().getClass(indx); - final String type = ci.getClassName().getType(); + String[] fi = jc.getFieldInfoName(indx); + final int type = VarType.fromFieldType(fi[2].charAt(0)); + emit(out, "@1(false).constructor.@2 = @3;", + accessClass(fi[0].replace('/', '_')), fi[1], + smapper.popT(type)); + i += 2; + addReference(fi[0]); + break; + } + case opc_checkcast: { + int indx = readIntArg(byteCodes, i); + final String type = jc.getClassName(indx); if (!type.startsWith("[")) { // no way to check arrays right now - out.append("if(stack[stack.length - 1].$instOf_") - .append(type.replace('/', '_')) - .append(" != 1) throw {};"); // XXX proper exception + // XXX proper exception + emit(out, + "if (@1 !== null && !@1.$instOf_@2) throw {};", + smapper.getA(0), type.replace('/', '_')); } i += 2; break; } - case bc_instanceof: { + case opc_instanceof: { int indx = readIntArg(byteCodes, i); - CPClassInfo ci = jc.getConstantPool().getClass(indx); - out.append("stack.push(stack.pop().$instOf_") - .append(ci.getClassName().getInternalName().replace('/', '_')) - .append(" ? 1 : 0);"); + final String type = jc.getClassName(indx); + emit(out, "var @2 = @1.$instOf_@3 ? 1 : 0;", + smapper.popA(), smapper.pushI(), + type.replace('/', '_')); i += 2; break; } - + case opc_athrow: { + final Variable v = smapper.popA(); + smapper.clear(); + + emit(out, "{ var @1 = @2; throw @2; }", + smapper.pushA(), v); + break; + } + + case opc_monitorenter: { + out.append("/* monitor enter */"); + smapper.popA(); + break; + } + + case opc_monitorexit: { + out.append("/* monitor exit */"); + smapper.popA(); + break; + } + + default: { + emit(out, "throw 'unknown bytecode @1';", + Integer.toString(c)); + } } - out.append(" //"); - for (int j = prev; j <= i; j++) { - out.append(" "); - final int cc = (byteCodes[j] + 256) % 256; - out.append(Integer.toString(cc)); + if (debug(" //")) { + for (int j = prev; j <= i; j++) { + out.append(" "); + final int cc = readByte(byteCodes, j); + out.append(Integer.toString(cc)); + } } - out.append("\n"); + out.append("\n"); + } + if (previousTrap != null) { + generateCatch(previousTrap); } out.append(" }\n"); + out.append("};"); } - private int generateIf(byte[] byteCodes, int i, final String test) throws IOException { + private int generateIf(byte[] byteCodes, int i, + final Variable v2, final Variable v1, + final String test) throws IOException { int indx = i + readIntArg(byteCodes, i); - out.append("if (stack.pop() ").append(test).append(" stack.pop()) { gt = " + indx); - out.append("; continue; }"); + out.append("if (").append(v1) + .append(' ').append(test).append(' ') + .append(v2).append(") { gt = " + indx) + .append("; continue; }"); return i + 2; } @@ -701,12 +1182,22 @@ final int indxLo = byteCodes[offsetInstruction + 2]; return (indxHi & 0xffffff00) | (indxLo & 0xff); } + private int readInt4(byte[] byteCodes, int offsetInstruction) { + final int d = byteCodes[offsetInstruction + 0] << 24; + final int c = byteCodes[offsetInstruction + 1] << 16; + final int b = byteCodes[offsetInstruction + 2] << 8; + final int a = byteCodes[offsetInstruction + 3]; + return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff); + } + private int readByte(byte[] byteCodes, int offsetInstruction) { + return byteCodes[offsetInstruction] & 0xff; + } - private static int countArgs(String descriptor, boolean[] hasReturnType, StringBuilder sig) { - int cnt = 0; + private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) { int i = 0; Boolean count = null; boolean array = false; + sig.append("__"); int firstPos = sig.length(); while (i < descriptor.length()) { char ch = descriptor.charAt(i++); @@ -717,9 +1208,6 @@ case ')': count = false; continue; - case 'A': - array = true; - break; case 'B': case 'C': case 'D': @@ -729,63 +1217,76 @@ case 'S': case 'Z': if (count) { - cnt++; if (array) { - sig.append('A'); + sig.append("_3"); } sig.append(ch); + if (ch == 'J' || ch == 'D') { + cnt.append('1'); + } else { + cnt.append('0'); + } } else { - hasReturnType[0] = true; sig.insert(firstPos, ch); if (array) { - sig.insert(firstPos, 'A'); + returnType[0] = '['; + sig.insert(firstPos, "_3"); + } else { + returnType[0] = ch; } } array = false; continue; case 'V': assert !count; - hasReturnType[0] = false; + returnType[0] = 'V'; sig.insert(firstPos, 'V'); continue; case 'L': int next = descriptor.indexOf(';', i); + String realSig = mangleSig(descriptor, i - 1, next + 1); if (count) { - cnt++; if (array) { - sig.append('A'); + sig.append("_3"); } - sig.append(ch); - sig.append(descriptor.substring(i, next).replace('/', '_')); + sig.append(realSig); + cnt.append('0'); } else { - sig.insert(firstPos, descriptor.substring(i, next).replace('/', '_')); - sig.insert(firstPos, ch); + sig.insert(firstPos, realSig); if (array) { - sig.insert(firstPos, 'A'); + sig.insert(firstPos, "_3"); } - hasReturnType[0] = true; + returnType[0] = 'L'; } i = next + 1; + array = false; continue; case '[': - //arrays++; + array = true; continue; default: - break; // invalid character + throw new IllegalStateException("Invalid char: " + ch); } } - return cnt; + } + + private static String mangleSig(String txt, int first, int last) { + StringBuilder sb = new StringBuilder(); + for (int i = first; i < last; i++) { + final char ch = txt.charAt(i); + switch (ch) { + case '/': sb.append('_'); break; + case '_': sb.append("_1"); break; + case ';': sb.append("_2"); break; + case '[': sb.append("_3"); break; + default: sb.append(ch); break; + } + } + return sb.toString(); } - private void generateStaticField(Variable v) throws IOException { - out.append("\nvar ") - .append(jc.getName().getInternalName().replace('/', '_')) - .append('_').append(v.getName()).append(" = 0;"); - } - - private String findMethodName(Method m) { + private static String findMethodName(MethodData m, StringBuilder cnt) { StringBuilder name = new StringBuilder(); - String descr = m.getDescriptor(); if ("".equals(m.getName())) { // NOI18N name.append("cons"); // NOI18N } else if ("".equals(m.getName())) { // NOI18N @@ -794,97 +1295,106 @@ name.append(m.getName()); } - boolean hasReturn[] = { false }; - countArgs(findDescriptor(m.getDescriptor()), hasReturn, name); + countArgs(m.getInternalSig(), new char[1], name, cnt); return name.toString(); } - private String findMethodName(CPMethodInfo mi, int[] cnt, boolean[] hasReturn) { + static String findMethodName(String[] mi, StringBuilder cnt, char[] returnType) { StringBuilder name = new StringBuilder(); - String descr = mi.getDescriptor(); - if ("".equals(mi.getName())) { // NOI18N + String descr = mi[2];//mi.getDescriptor(); + String nm= mi[1]; + if ("".equals(nm)) { // NOI18N name.append("cons"); // NOI18N } else { - name.append(mi.getName()); + name.append(nm); } - cnt[0] = countArgs(findDescriptor(mi.getDescriptor()), hasReturn, name); + countArgs(descr, returnType, name, cnt); return name.toString(); } - private int invokeStaticMethod(byte[] byteCodes, int i, boolean isStatic) + private int invokeStaticMethod(byte[] byteCodes, int i, final StackMapper mapper, boolean isStatic) throws IOException { int methodIndex = readIntArg(byteCodes, i); - CPMethodInfo mi = (CPMethodInfo) jc.getConstantPool().get(methodIndex); - boolean[] hasReturn = { false }; - int[] cnt = { 0 }; - String mn = findMethodName(mi, cnt, hasReturn); - out.append("{ "); - for (int j = cnt[0] - 1; j >= 0; j--) { - out.append("var v" + j).append(" = stack.pop(); "); + String[] mi = jc.getFieldInfoName(methodIndex); + char[] returnType = { 'V' }; + StringBuilder cnt = new StringBuilder(); + String mn = findMethodName(mi, cnt, returnType); + + final int numArguments = isStatic ? cnt.length() : cnt.length() + 1; + final Variable[] vars = new Variable[numArguments]; + + for (int j = numArguments - 1; j >= 0; --j) { + vars[j] = mapper.pop(); } - - if (hasReturn[0]) { - out.append("stack.push("); + + if (returnType[0] != 'V') { + out.append("var ") + .append(mapper.pushT(VarType.fromFieldType(returnType[0]))) + .append(" = "); } - final String in = mi.getClassName().getInternalName(); - out.append(in.replace('/', '_')); - out.append('_'); + + final String in = mi[0]; + out.append(accessClass(in.replace('/', '_'))); + out.append("(false)."); + if (mn.startsWith("cons_")) { + out.append("constructor."); + } out.append(mn); - out.append('('); - String sep = ""; - if (!isStatic) { - out.append("stack.pop()"); - sep = ", "; + if (isStatic) { + out.append('('); + } else { + out.append(".call("); } - for (int j = 0; j < cnt[0]; j++) { - out.append(sep); - out.append("v" + j); - sep = ", "; + if (numArguments > 0) { + out.append(vars[0]); + for (int j = 1; j < numArguments; ++j) { + out.append(", "); + out.append(vars[j]); + } } - out.append(")"); - if (hasReturn[0]) { - out.append(")"); - } - out.append("; }"); + out.append(");"); i += 2; addReference(in); return i; } - private int invokeVirtualMethod(byte[] byteCodes, int i) + private int invokeVirtualMethod(byte[] byteCodes, int i, final StackMapper mapper) throws IOException { int methodIndex = readIntArg(byteCodes, i); - CPMethodInfo mi = (CPMethodInfo) jc.getConstantPool().get(methodIndex); - boolean[] hasReturn = { false }; - int[] cnt = { 0 }; - String mn = findMethodName(mi, cnt, hasReturn); - out.append("{ "); - for (int j = cnt[0] - 1; j >= 0; j--) { - out.append("var v" + j).append(" = stack.pop(); "); + String[] mi = jc.getFieldInfoName(methodIndex); + char[] returnType = { 'V' }; + StringBuilder cnt = new StringBuilder(); + String mn = findMethodName(mi, cnt, returnType); + + final int numArguments = cnt.length() + 1; + final Variable[] vars = new Variable[numArguments]; + + for (int j = numArguments - 1; j >= 0; --j) { + vars[j] = mapper.pop(); } - out.append("var self = stack.pop(); "); - if (hasReturn[0]) { - out.append("stack.push("); + + if (returnType[0] != 'V') { + out.append("var ") + .append(mapper.pushT(VarType.fromFieldType(returnType[0]))) + .append(" = "); } - out.append("self."); + + out.append(vars[0]).append('.'); out.append(mn); out.append('('); - out.append("self"); - for (int j = 0; j < cnt[0]; j++) { - out.append(", "); - out.append("v" + j); + String sep = ""; + for (int j = 1; j < numArguments; ++j) { + out.append(sep); + out.append(vars[j]); + sep = ", "; } - out.append(")"); - if (hasReturn[0]) { - out.append(")"); - } - out.append("; }"); + out.append(");"); i += 2; return i; } - - private void addReference(String cn) { - if (references != null) { - references.add(cn); + + private void addReference(String cn) throws IOException { + if (requireReference(cn)) { + debug(" /* needs " + cn + " */"); } } @@ -902,61 +1412,220 @@ } } - private String encodeConstant(CPEntry entry) { - final String v; - if (entry instanceof CPClassInfo) { - v = "new java_lang_Class"; - } else if (entry instanceof CPStringInfo) { - v = "\"" + entry.getValue().toString().replace("\"", "\\\"") + "\""; - } else { - v = entry.getValue().toString(); + private String encodeConstant(int entryIndex) throws IOException { + String[] classRef = { null }; + String s = jc.stringValue(entryIndex, classRef); + if (classRef[0] != null) { + addReference(classRef[0]); + s = accessClass(s.replace('/', '_')) + "(false).constructor.$class"; } - return v; + return s; } - private String findDescriptor(String d) { - return d.replace('[', 'A'); + private String javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException { + byte[] arr = m.findAnnotationData(true); + if (arr == null) { + return null; + } + final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;"; + class P extends AnnotationParser { + public P() { + super(false); + } + + int cnt; + String[] args = new String[30]; + String body; + + @Override + protected void visitAttr(String type, String attr, String at, String value) { + if (type.equals(jvmType)) { + if ("body".equals(attr)) { + body = value; + } else if ("args".equals(attr)) { + args[cnt++] = value; + } else { + throw new IllegalArgumentException(attr); + } + } + } + } + P p = new P(); + p.parse(arr, jc); + if (p.body == null) { + return null; + } + StringBuilder cnt = new StringBuilder(); + final String mn = findMethodName(m, cnt); + out.append(prefix).append(mn); + out.append(" = function("); + String space = ""; + int index = 0; + for (int i = 0; i < cnt.length(); i++) { + out.append(space); + space = outputArg(out, p.args, index); + index++; + } + out.append(") {").append("\n"); + out.append(p.body); + out.append("\n}\n"); + return mn; + } + private static String className(ClassData jc) { + //return jc.getName().getInternalName().replace('/', '_'); + return jc.getClassName().replace('/', '_'); + } + + private static String[] findAnnotation( + byte[] arr, ClassData cd, final String className, + final String... attrNames + ) throws IOException { + if (arr == null) { + return null; + } + final String[] values = new String[attrNames.length]; + final boolean[] found = { false }; + final String jvmType = "L" + className.replace('.', '/') + ";"; + AnnotationParser ap = new AnnotationParser(false) { + @Override + protected void visitAttr(String type, String attr, String at, String value) { + if (type.equals(jvmType)) { + found[0] = true; + for (int i = 0; i < attrNames.length; i++) { + if (attrNames[i].equals(attr)) { + values[i] = value; + } + } + } + } + + }; + ap.parse(arr, cd); + return found[0] ? values : null; } - private boolean javaScriptBody(Method m, boolean isStatic) throws IOException { - final ClassName extraAnn = ClassName.getClassName(JavaScriptBody.class.getName().replace('.', '/')); - Annotation a = m.getAnnotation(extraAnn); - if (a != null) { - final ElementValue annVal = a.getComponent("body").getValue(); - String body = ((PrimitiveElementValue) annVal).getValue().getValue().toString(); + private CharSequence initField(FieldData v) { + final String is = v.getInternalSig(); + if (is.length() == 1) { + switch (is.charAt(0)) { + case 'S': + case 'J': + case 'B': + case 'Z': + case 'C': + case 'I': return " = 0;"; + case 'F': + case 'D': return " = 0.0;"; + default: + throw new IllegalStateException(is); + } + } + return " = null;"; + } + + private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException { + AnnotationParser ap = new AnnotationParser(true) { + int anno; + int cnt; - final ArrayElementValue arrVal = (ArrayElementValue) a.getComponent("args").getValue(); - final int len = arrVal.getValues().length; - String[] names = new String[len]; - for (int i = 0; i < len; i++) { - names[i] = ((PrimitiveElementValue) arrVal.getValues()[i]).getValue().getValue().toString(); + @Override + protected void visitAnnotationStart(String type) throws IOException { + if (anno++ > 0) { + out.append(","); + } + out.append('"').append(type).append("\" : {\n"); + cnt = 0; } - out.append("\nfunction ").append( - jc.getName().getInternalName().replace('/', '_')).append('_').append(findMethodName(m)); - out.append("("); - String space; - int index; - if (!isStatic) { - out.append(names[0]); - space = ","; - index = 1; + + @Override + protected void visitAnnotationEnd(String type) throws IOException { + out.append("\n}\n"); + } + + @Override + protected void visitAttr(String type, String attr, String attrType, String value) + throws IOException { + if (attr == null) { + return; + } + if (cnt++ > 0) { + out.append(",\n"); + } + out.append(attr).append("__").append(attrType).append(" : ").append(value); + } + }; + ap.parse(data, cd); + } + + private static String outputArg(Appendable out, String[] args, int indx) throws IOException { + final String name = args[indx]; + if (name == null) { + return ""; + } + if (name.contains(",")) { + throw new IOException("Wrong parameter with ',': " + name); + } + out.append(name); + return ","; + } + + private static void emit(final Appendable out, + final String format, + final CharSequence... params) throws IOException { + final int length = format.length(); + + int processed = 0; + int paramOffset = format.indexOf('@'); + while ((paramOffset != -1) && (paramOffset < (length - 1))) { + final char paramChar = format.charAt(paramOffset + 1); + if ((paramChar >= '1') && (paramChar <= '9')) { + final int paramIndex = paramChar - '0' - 1; + + out.append(format, processed, paramOffset); + out.append(params[paramIndex]); + + ++paramOffset; + processed = paramOffset + 1; + } + + paramOffset = format.indexOf('@', paramOffset + 1); + } + + out.append(format, processed, length); + } + + private void generateCatch(TrapData[] traps) throws IOException { + out.append("} catch (e) {\n"); + int finallyPC = -1; + for (TrapData e : traps) { + if (e == null) { + break; + } + if (e.catch_cpx != 0) { //not finally + final String classInternalName = jc.getClassName(e.catch_cpx); + addReference(classInternalName); + if ("java/lang/Throwable".equals(classInternalName)) { + out.append("if (e.$instOf_java_lang_Throwable) {"); + out.append(" var stA0 = e;"); + out.append("} else {"); + out.append(" var stA0 = vm.java_lang_Throwable(true);"); + out.append(" vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());"); + out.append("}"); + out.append("gt=" + e.handler_pc + "; continue;"); + } else { + out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {"); + out.append("gt=" + e.handler_pc + "; var stA0 = e; continue;"); + out.append("}\n"); + } } else { - space = ""; - index = 0; + finallyPC = e.handler_pc; } - List args = m.getParameters(); - for (int i = 0; i < args.size(); i++) { - out.append(space); - out.append(names[index]); - final String desc = findDescriptor(args.get(i).getDescriptor()); - index++; - space = ","; - } - out.append(") {").append("\n"); - out.append(body); - out.append("\n}\n"); - return true; } - return false; + if (finallyPC == -1) { + out.append("throw e;"); + } else { + out.append("gt=" + finallyPC + "; var stA0 = e; continue;"); + } + out.append("\n}"); } } diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +0,0 @@ -package org.apidesign.vm4brwsr; - -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.Writer; -import java.net.URL; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** Generator of JavaScript from bytecode of classes on classpath of the VM. - * - * @author Jaroslav Tulach - */ -final class GenJS { - private GenJS() {} - - public static void main(String... args) throws IOException { - if (args.length < 2) { - System.err.println("Usage: java -cp ... -jar ... java/lang/Class org/your/App ..."); - return; - } - - Writer w = new BufferedWriter(new FileWriter(args[0])); - List classes = Arrays.asList(args).subList(1, args.length); - compile(w, classes); - w.close(); - } - - static void compile(Appendable out, String... names) throws IOException { - compile(out, Arrays.asList(names)); - } - static void compile(Appendable out, List names) throws IOException { - for (String baseClass : names) { - Map processed = new HashMap(); - LinkedList toProcess = new LinkedList(); - toProcess.add(baseClass); - for (;;) { - String name = null; - Iterator it = toProcess.iterator(); - while (it.hasNext() && name == null) { - String n = it.next(); - if (processed.get(n) != null) { - continue; - } - name = n; - } - if (name == null) { - break; - } - if (name.startsWith("java/") - && !name.equals("java/lang/Object") - && !name.equals("java/lang/Class") - && !name.equals("java/lang/Number") - && !name.equals("java/lang/Integer") - && !name.equals("java/lang/Throwable") - && !name.equals("java/lang/Exception") - && !name.equals("java/lang/RuntimeException") - && !name.equals("java/lang/UnsupportedOperationException") - && !name.equals("java/lang/String") - && !name.equals("java/lang/String$CaseInsensitiveComparator") - && !name.equals("java/lang/StringBuilder") - && !name.equals("java/lang/AbstractStringBuilder") - ) { - processed.put(name, ""); - continue; - } - InputStream is = loadClass(name); - if (is == null) { - throw new IOException("Can't find class " + name); - } - LinkedList scripts = new LinkedList(); - try { - String initCode = ByteCodeToJavaScript.compile(is, out, toProcess, scripts); - processed.put(name, initCode == null ? "" : initCode); - } catch (RuntimeException ex) { - if (out instanceof CharSequence) { - CharSequence seq = (CharSequence)out; - int lastBlock = seq.length(); - while (lastBlock-- >= 0) { - if (seq.charAt(lastBlock) == '{') { - break; - } - } - throw new IOException("Error while compiling " + name + "\n" - + seq.subSequence(lastBlock + 1, seq.length()), ex - ); - } else { - throw new IOException("Error while compiling " + name + "\n" - + out, ex - ); - } - } - for (String resource : scripts) { - InputStream emul = GenJS.class.getResourceAsStream(resource); - if (emul == null) { - throw new IOException("Can't find " + resource); - } - readResource(emul, out); - } - } - - Collections.reverse(toProcess); - - for (String clazz : toProcess) { - String initCode = processed.remove(clazz); - if (initCode != null) { - out.append(initCode).append("\n"); - } - } - } - - } - private static void readResource(InputStream emul, Appendable out) throws IOException { - try { - int state = 0; - for (;;) { - int ch = emul.read(); - if (ch == -1) { - break; - } - if (ch < 0 || ch > 255) { - throw new IOException("Invalid char in emulation " + ch); - } - switch (state) { - case 0: - if (ch == '/') { - state = 1; - } else { - out.append((char)ch); - } - break; - case 1: - if (ch == '*') { - state = 2; - } else { - out.append('/').append((char)ch); - state = 0; - } - break; - case 2: - if (ch == '*') { - state = 3; - } - break; - case 3: - if (ch == '/') { - state = 0; - } else { - state = 2; - } - break; - } - } - } finally { - emul.close(); - } - } - - private static InputStream loadClass(String name) throws IOException { - Enumeration en = ClassLoader.getSystemClassLoader().getResources(name + ".class"); - URL u = null; - while (en.hasMoreElements()) { - u = en.nextElement(); - } - if (u == null) { - throw new IOException("Can't find " + name); - } - return u.openStream(); - } - -} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,142 @@ +/** + * 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 org.apidesign.javap.RuntimeConstants; +import org.apidesign.javap.TypeArray; + +final class LocalsMapper { + private final TypeArray argTypeRecords; + private final TypeArray localTypeRecords; + + public LocalsMapper(final TypeArray stackMapArgs) { + final TypeArray initTypeRecords = new TypeArray(); + updateRecords(initTypeRecords, stackMapArgs); + + argTypeRecords = initTypeRecords; + localTypeRecords = new TypeArray(initTypeRecords); + } + + public void outputArguments(final Appendable out, boolean isStatic) throws IOException { + final int argRecordCount = argTypeRecords.getSize(); + int first = isStatic ? 0 : 1; + if (argRecordCount > first) { + Variable variable = getVariable(argTypeRecords, first); + out.append(variable); + + int i = first + (variable.isCategory2() ? 2 : 1); + while (i < argRecordCount) { + variable = getVariable(argTypeRecords, i); + out.append(", "); + out.append(variable); + i += variable.isCategory2() ? 2 : 1; + } + } + } + + public void syncWithFrameLocals(final TypeArray frameLocals) { + updateRecords(localTypeRecords, frameLocals); + } + + public Variable setI(final int index) { + return setT(index, VarType.INTEGER); + } + + public Variable setL(final int index) { + return setT(index, VarType.LONG); + } + + public Variable setF(final int index) { + return setT(index, VarType.FLOAT); + } + + public Variable setD(final int index) { + return setT(index, VarType.DOUBLE); + } + + public Variable setA(final int index) { + return setT(index, VarType.REFERENCE); + } + + public Variable setT(final int index, final int type) { + updateRecord(localTypeRecords, index, type); + return Variable.getLocalVariable(type, index); + } + + public Variable getI(final int index) { + return getT(index, VarType.INTEGER); + } + + public Variable getL(final int index) { + return getT(index, VarType.LONG); + } + + public Variable getF(final int index) { + return getT(index, VarType.FLOAT); + } + + public Variable getD(final int index) { + return getT(index, VarType.DOUBLE); + } + + public Variable getA(final int index) { + return getT(index, VarType.REFERENCE); + } + + public Variable getT(final int index, final int type) { + final int oldRecordValue = localTypeRecords.get(index); + if ((oldRecordValue & 0xff) != type) { + throw new IllegalStateException("Type mismatch"); + } + + return Variable.getLocalVariable(type, index); + } + + private static void updateRecords(final TypeArray typeRecords, + final TypeArray stackMapTypes) { + final int srcSize = stackMapTypes.getSize(); + for (int i = 0, dstIndex = 0; i < srcSize; ++i) { + final int smType = stackMapTypes.get(i); + if (smType == RuntimeConstants.ITEM_Bogus) { + ++dstIndex; + continue; + } + final int varType = VarType.fromStackMapType(smType); + updateRecord(typeRecords, dstIndex, varType); + dstIndex += VarType.isCategory2(varType) ? 2 : 1; + } + } + + private static void updateRecord(final TypeArray typeRecords, + final int index, final int type) { + if (typeRecords.getSize() < (index + 1)) { + typeRecords.setSize(index + 1); + } + + final int oldRecordValue = typeRecords.get(index); + final int usedTypesMask = + (oldRecordValue >> 8) | (1 << type); + typeRecords.set(index, (usedTypesMask << 8) | type); + } + + private static Variable getVariable(final TypeArray typeRecords, + final int index) { + return Variable.getLocalVariable(typeRecords.get(index) & 0xff, index); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/Main.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,50 @@ +/** + * 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.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; + +/** Generator of JavaScript from bytecode of classes on classpath of the VM + * with a Main method. + * + * @author Jaroslav Tulach + */ +final class Main { + private Main() {} + + public static void main(String... args) throws IOException { + if (args.length < 2) { + System.err.println("Bck2Brwsr Translator from Java(tm) to JavaScript, (c) Jaroslav Tulach 2012"); + System.err.println("Usage: java -cp ... -jar ... java/lang/Class org/your/App ..."); + return; + } + + Writer w = new BufferedWriter(new FileWriter(args[0])); + StringArray classes = StringArray.asList(args); + classes.delete(0); + try { + Bck2Brwsr.generate(w, Main.class.getClassLoader(), + classes.toArray()); + } finally { + w.close(); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,194 @@ +/** + * 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 org.apidesign.javap.TypeArray; + +final class StackMapper { + private final TypeArray stackTypeIndexPairs; + private int[] typeCounters; + private int[] typeMaxCounters; + + public StackMapper() { + stackTypeIndexPairs = new TypeArray(); + typeCounters = new int[VarType.LAST + 1]; + typeMaxCounters = new int[VarType.LAST + 1]; + } + + public void clear() { + for (int type = 0; type <= VarType.LAST; ++type) { + typeCounters[type] = 0; + } + stackTypeIndexPairs.clear(); + } + + public void syncWithFrameStack(final TypeArray frameStack) { + clear(); + + final int size = frameStack.getSize(); + for (int i = 0; i < size; ++i) { + pushTypeImpl(VarType.fromStackMapType(frameStack.get(i))); + } + } + + public Variable pushI() { + return pushT(VarType.INTEGER); + } + + public Variable pushL() { + return pushT(VarType.LONG); + } + + public Variable pushF() { + return pushT(VarType.FLOAT); + } + + public Variable pushD() { + return pushT(VarType.DOUBLE); + } + + public Variable pushA() { + return pushT(VarType.REFERENCE); + } + + public Variable pushT(final int type) { + return getVariable(pushTypeImpl(type)); + } + + public Variable popI() { + return popT(VarType.INTEGER); + } + + public Variable popL() { + return popT(VarType.LONG); + } + + public Variable popF() { + return popT(VarType.FLOAT); + } + + public Variable popD() { + return popT(VarType.DOUBLE); + } + + public Variable popA() { + return popT(VarType.REFERENCE); + } + + public Variable popT(final int type) { + final Variable variable = getT(0, type); + popImpl(1); + return variable; + } + + public Variable pop() { + final Variable variable = get(0); + popImpl(1); + return variable; + } + + public void pop(final int count) { + final int stackSize = stackTypeIndexPairs.getSize(); + if (count > stackSize) { + throw new IllegalStateException("Stack underflow"); + } + popImpl(count); + } + + public Variable getI(final int indexFromTop) { + return getT(indexFromTop, VarType.INTEGER); + } + + public Variable getL(final int indexFromTop) { + return getT(indexFromTop, VarType.LONG); + } + + public Variable getF(final int indexFromTop) { + return getT(indexFromTop, VarType.FLOAT); + } + + public Variable getD(final int indexFromTop) { + return getT(indexFromTop, VarType.DOUBLE); + } + + public Variable getA(final int indexFromTop) { + return getT(indexFromTop, VarType.REFERENCE); + } + + public Variable getT(final int indexFromTop, final int type) { + final int stackSize = stackTypeIndexPairs.getSize(); + if (indexFromTop >= stackSize) { + throw new IllegalStateException("Stack underflow"); + } + final int stackValue = + stackTypeIndexPairs.get(stackSize - indexFromTop - 1); + if ((stackValue & 0xff) != type) { + throw new IllegalStateException("Type mismatch"); + } + + return getVariable(stackValue); + } + + public Variable get(final int indexFromTop) { + final int stackSize = stackTypeIndexPairs.getSize(); + if (indexFromTop >= stackSize) { + throw new IllegalStateException("Stack underflow"); + } + final int stackValue = + stackTypeIndexPairs.get(stackSize - indexFromTop - 1); + + return getVariable(stackValue); + } + + private int pushTypeImpl(final int type) { + final int count = typeCounters[type]; + final int value = (count << 8) | (type & 0xff); + incCounter(type); + stackTypeIndexPairs.add(value); + + return value; + } + + private void popImpl(final int count) { + final int stackSize = stackTypeIndexPairs.getSize(); + for (int i = stackSize - count; i < stackSize; ++i) { + final int value = stackTypeIndexPairs.get(i); + decCounter(value & 0xff); + } + + stackTypeIndexPairs.setSize(stackSize - count); + } + + private void incCounter(final int type) { + final int newValue = ++typeCounters[type]; + if (typeMaxCounters[type] < newValue) { + typeMaxCounters[type] = newValue; + } + } + + private void decCounter(final int type) { + --typeCounters[type]; + } + + public Variable getVariable(final int typeAndIndex) { + final int type = typeAndIndex & 0xff; + final int index = typeAndIndex >> 8; + + return Variable.getStackVariable(type, index); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,97 @@ +/** + * 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; + +/** + * + * @author Jaroslav Tulach + */ +class StringArray { + private String[] arr; + + public StringArray() { + } + + private StringArray(String[] arr) { + this.arr = arr; + } + + public void add(String s) { + if (arr == null) { + arr = new String[1]; + } else { + String[] tmp = new String[arr.length + 1]; + for (int i = 0; i < arr.length; i++) { + tmp[i] = arr[i]; + } + arr = tmp; + } + arr[arr.length - 1] = s; + } + + public String[] toArray() { + return arr == null ? new String[0] : arr; + } + + static StringArray asList(String... names) { + return new StringArray(names); + } + + void reverse() { + for (int i = 0, j = arr.length; i < j; i++) { + String s = arr[i]; + arr[i] = arr[--j]; + arr[j] = s; + } + } + + boolean contains(String n) { + if (arr == null) { + return false; + } + for (int i = 0; i < arr.length; i++) { + if (n.equals(arr[i])) { + return true; + } + } + return false; + } + + void delete(int indx) { + if (arr == null || indx < 0 || indx >= arr.length) { + return; + } + String[] tmp = new String[arr.length - 1]; + for (int i = 0, j = 0; i < arr.length; i++) { + if (i != indx) { + tmp[j++] = arr[i]; + } + } + arr = tmp; + } + + int indexOf(String ic) { + for (int i = 0; i < arr.length; i++) { + if (ic.equals(arr[i])) { + return i; + } + } + return -1; + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/VM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,220 @@ +/** + * 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; + +/** Generator of JavaScript from bytecode of classes on classpath of the VM. + * + * @author Jaroslav Tulach + */ +class VM extends ByteCodeToJavaScript { + public VM(Appendable out) { + super(out); + } + + static { + // uses VMLazy to load dynamic classes + VMLazy.init(); + } + + @Override + boolean debug(String msg) throws IOException { + return false; + } + + static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException { + new VM(out).doCompile(l, names); + } + protected void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException { + out.append("(function VM(global) {"); + out.append("\n var vm = {};"); + StringArray processed = new StringArray(); + StringArray initCode = new StringArray(); + for (String baseClass : names.toArray()) { + references.add(baseClass); + for (;;) { + String name = null; + for (String n : references.toArray()) { + if (processed.contains(n)) { + continue; + } + name = n; + } + if (name == null) { + break; + } + InputStream is = loadClass(l, name); + if (is == null) { + throw new IOException("Can't find class " + name); + } + try { + String ic = compile(is); + processed.add(name); + initCode.add(ic == null ? "" : ic); + } catch (RuntimeException ex) { + if (out instanceof CharSequence) { + CharSequence seq = (CharSequence)out; + int lastBlock = seq.length(); + while (lastBlock-- > 0) { + if (seq.charAt(lastBlock) == '{') { + break; + } + } + throw new IOException("Error while compiling " + name + "\n" + + seq.subSequence(lastBlock + 1, seq.length()), ex + ); + } else { + throw new IOException("Error while compiling " + name + "\n" + + out, ex + ); + } + } + } + + for (String resource : scripts.toArray()) { + while (resource.startsWith("/")) { + resource = resource.substring(1); + } + InputStream emul = l.get(resource); + if (emul == null) { + throw new IOException("Can't find " + resource); + } + readResource(emul, out); + } + scripts = new StringArray(); + + StringArray toInit = StringArray.asList(references.toArray()); + toInit.reverse(); + + for (String ic : toInit.toArray()) { + int indx = processed.indexOf(ic); + if (indx >= 0) { + out.append(initCode.toArray()[indx]).append("\n"); + initCode.toArray()[indx] = ""; + } + } + } + out.append( + " global.bck2brwsr = function() {\n" + + " var args = arguments;\n" + + " var loader = {};\n" + + " loader.vm = vm;\n" + + " loader.loadClass = function(name) {\n" + + " var attr = name.replace__Ljava_lang_String_2CC('.','_');\n" + + " var fn = vm[attr];\n" + + " if (fn) return fn(false);\n" + + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n" + + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n" + + " load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n" + + " }\n" + + " if (args[0]) {\n" + + " vm.loadClass = loader.loadClass;\n" + + " vm.loadBytes = function(name) {\n" + + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n" + + " return args[0](name);\n" + + " }\n" + + " }\n" + + " return loader;\n" + + " };\n"); + out.append("}(this));"); + } + private static void readResource(InputStream emul, Appendable out) throws IOException { + try { + int state = 0; + for (;;) { + int ch = emul.read(); + if (ch == -1) { + break; + } + if (ch < 0 || ch > 255) { + throw new IOException("Invalid char in emulation " + ch); + } + switch (state) { + case 0: + if (ch == '/') { + state = 1; + } else { + out.append((char)ch); + } + break; + case 1: + if (ch == '*') { + state = 2; + } else { + out.append('/').append((char)ch); + state = 0; + } + break; + case 2: + if (ch == '*') { + state = 3; + } + break; + case 3: + if (ch == '/') { + state = 0; + } else { + state = 2; + } + break; + } + } + } finally { + emul.close(); + } + } + + private static InputStream loadClass(Bck2Brwsr.Resources l, String name) throws IOException { + return l.get(name + ".class"); // NOI18N + } + + static String toString(String name) throws IOException { + StringBuilder sb = new StringBuilder(); +// compile(sb, name); + return sb.toString().toString(); + } + + private StringArray scripts = new StringArray(); + private StringArray references = new StringArray(); + + @Override + protected boolean requireReference(String cn) { + if (references.contains(cn)) { + return false; + } + references.add(cn); + return true; + } + + @Override + protected void requireScript(String resourcePath) { + scripts.add(resourcePath); + } + + @Override + String assignClass(String className) { + return "vm." + className + " = "; + } + + @Override + String accessClass(String className) { + return "vm." + className; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,158 @@ +/** + * 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.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Jaroslav Tulach + */ +final class VMLazy { + private final Object loader; + private final Object[] args; + + private VMLazy(Object loader, Object[] args) { + this.loader = loader; + this.args = args; + } + + static void init() { + } + + @JavaScriptBody(args={"l", "res", "args" }, body = "" + + "\ntry {" + + "\n return args[0](res.toString());" + + "\n} catch (x) {" + + "\n throw Object.getOwnPropertyNames(l.vm).toString() + x.toString();" + + "\n}") + private static native byte[] read(Object l, String res, Object[] args); + + static Object load(Object loader, String name, Object[] arguments) + throws IOException, ClassNotFoundException { + return new VMLazy(loader, arguments).load(name, false); + } + + private Object load(String name, boolean instance) + throws IOException, ClassNotFoundException { + String res = name.replace('.', '/') + ".class"; + byte[] arr = read(loader, res, args); + if (arr == null) { + throw new ClassNotFoundException(name); + } +// beingDefined(loader, name); + StringBuilder out = new StringBuilder(); + out.append("var loader = arguments[0];\n"); + out.append("var vm = loader.vm;\n"); + int prelude = out.length(); + String initCode = new Gen(this, out).compile(new ByteArrayInputStream(arr)); + String code = out.toString().toString(); +// dump("Loading " + name); + dump(code); + String under = name.replace('.', '_'); + Object fn = applyCode(loader, under, code, instance); + + if (!initCode.isEmpty()) { + out.setLength(prelude); + out.append(initCode); + code = out.toString().toString(); + dump(code); + applyCode(loader, null, code, false); + } + + return fn; + } + +// @JavaScriptBody(args = "s", body = "java.lang.System.out.println(s.toString());") + static void dump(String s) { + } + +/* possibly not needed: + @JavaScriptBody(args = {"loader", "n" }, body = + "var cls = n.replace__Ljava_lang_String_2CC(n, '.','_').toString();" + + "loader.vm[cls] = true;\n" + ) + private static native void beingDefined(Object loader, String name); +*/ + + + @JavaScriptBody(args = {"loader", "name", "script", "instance" }, body = + "try {\n" + + " new Function(script)(loader, name);\n" + + "} catch (ex) {\n" + + " throw 'Cannot compile ' + ex + ' line: ' + ex.lineNumber + ' script:\\n' + script;\n" + + "}\n" + + "return name != null ? vm[name](instance) : null;\n" + ) + private static native Object applyCode(Object loader, String name, String script, boolean instance); + + + private static final class Gen extends ByteCodeToJavaScript { + private final VMLazy lazy; + + public Gen(VMLazy vm, Appendable out) { + super(out); + this.lazy = vm; + } + + @JavaScriptBody(args = {"n"}, + body = + "var cls = n.replace__Ljava_lang_String_2CC('/','_').toString();" + + "\nvar dot = n.replace__Ljava_lang_String_2CC('/','.').toString();" + + "\nvar lazy = this.fld_lazy;" + + "\nvar loader = lazy.fld_loader;" + + "\nvar vm = loader.vm;" + + "\nif (vm[cls]) return false;" + + "\nvm[cls] = function() {" + + "\n var instance = arguments.length == 0 || arguments[0] === true;" + + "\n return lazy.load__Ljava_lang_Object_2Ljava_lang_String_2Z(dot, instance);" + + "\n};" + + "\nreturn true;") + @Override + protected boolean requireReference(String internalClassName) { + throw new UnsupportedOperationException(); + } + + @Override + protected void requireScript(String resourcePath) throws IOException { + InputStream is = getClass().getResourceAsStream(resourcePath); + StringBuilder sb = new StringBuilder(); + for (;;) { + int ch = is.read(); + if (ch == -1) { + break; + } + sb.append((char)ch); + } + applyCode(lazy.loader, null, sb.toString(), false); + } + + @Override + String assignClass(String className) { + return "vm[arguments[1]]="; + } + + @Override + String accessClass(String classOperation) { + return "vm." + classOperation; + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/VarType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,110 @@ +/** + * 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 org.apidesign.javap.RuntimeConstants; + +final class VarType { + public static final int INTEGER = 0; + public static final int LONG = 1; + public static final int FLOAT = 2; + public static final int DOUBLE = 3; + public static final int REFERENCE = 4; + + public static final int LAST = REFERENCE; + + private VarType() { + } + + public static boolean isCategory2(final int varType) { + return (varType == LONG) || (varType == DOUBLE); + } + + public static int fromStackMapType(final int smType) { + switch (smType & 0xff) { + case RuntimeConstants.ITEM_Integer: + return VarType.INTEGER; + case RuntimeConstants.ITEM_Float: + return VarType.FLOAT; + case RuntimeConstants.ITEM_Double: + return VarType.DOUBLE; + case RuntimeConstants.ITEM_Long: + return VarType.LONG; + case RuntimeConstants.ITEM_Object: + return VarType.REFERENCE; + + case RuntimeConstants.ITEM_Bogus: + case RuntimeConstants.ITEM_Null: + case RuntimeConstants.ITEM_InitObject: + case RuntimeConstants.ITEM_NewObject: + /* unclear how to handle for now */ + default: + throw new IllegalStateException("Unhandled stack map type"); + } + } + + public static int fromConstantType(final byte constantTag) { + switch (constantTag) { + case RuntimeConstants.CONSTANT_INTEGER: + return VarType.INTEGER; + case RuntimeConstants.CONSTANT_FLOAT: + return VarType.FLOAT; + case RuntimeConstants.CONSTANT_LONG: + return VarType.LONG; + case RuntimeConstants.CONSTANT_DOUBLE: + return VarType.DOUBLE; + + case RuntimeConstants.CONSTANT_CLASS: + case RuntimeConstants.CONSTANT_UTF8: + case RuntimeConstants.CONSTANT_UNICODE: + case RuntimeConstants.CONSTANT_STRING: + return VarType.REFERENCE; + + case RuntimeConstants.CONSTANT_FIELD: + case RuntimeConstants.CONSTANT_METHOD: + case RuntimeConstants.CONSTANT_INTERFACEMETHOD: + case RuntimeConstants.CONSTANT_NAMEANDTYPE: + /* unclear how to handle for now */ + default: + throw new IllegalStateException("Unhandled constant tag"); + } + } + + public static int fromFieldType(final char fieldType) { + switch (fieldType) { + case 'B': + case 'C': + case 'S': + case 'Z': + case 'I': + return VarType.INTEGER; + case 'J': + return VarType.LONG; + case 'F': + return VarType.FLOAT; + case 'D': + return VarType.DOUBLE; + case 'L': + case '[': + return VarType.REFERENCE; + + default: + throw new IllegalStateException("Unhandled field type"); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/java/org/apidesign/vm4brwsr/Variable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Variable.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,100 @@ +/** + * 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; + +final class Variable implements CharSequence { + private static final String STACK_VAR_PREFIX = "st"; + private static final String LOCAL_VAR_PREFIX = "lc"; + + private final String name; + private final int type; + private final int index; + + private static final char[] TYPE_IDS = { 'I', 'L', 'F', 'D', 'A' }; + + private Variable(final String prefix, final int type, final int index) { + this.name = prefix + TYPE_IDS[type] + index; + this.type = type; + this.index = index; + } + + public static Variable getStackVariable( + final int type, final int index) { + // TODO: precreate frequently used variables + return new Variable(STACK_VAR_PREFIX, type, index); + } + + public static Variable getLocalVariable( + final int type, final int index) { + // TODO: precreate frequently used variables + return new Variable(LOCAL_VAR_PREFIX, type, index); + } + + public String getName() { + return name; + } + + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + + public boolean isCategory2() { + return VarType.isCategory2(type); + } + + @Override + public int length() { + return name.length(); + } + + @Override + public char charAt(final int index) { + return name.charAt(index); + } + + @Override + public CharSequence subSequence(final int start, final int end) { + return name.subSequence(start, end); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(final Object other) { + if (this == other) { + return true; + } + if (!(other instanceof Variable)) { + return false; + } + + return name.equals(((Variable) other).name); + } + + @Override + public String toString() { + return name; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/main/resources/org/apidesign/vm4brwsr/emulation/java_lang_String.js --- a/vm/src/main/resources/org/apidesign/vm4brwsr/emulation/java_lang_String.js Thu Oct 11 06:15:22 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3296 +0,0 @@ -/* */ - - -/* -function java_lang_String_consV(arg0) { - var arg1; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg0); // 42 - case 5: stack.push(0); // 3 - case 6: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 9: stack.push(arg0); // 42 - case 10: stack.push(0); // 3 - case 11: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 14: stack.push(arg0); // 42 - case 15: stack.push(0); // 3 - case 16: stack.push(new Array(stack.pop())); // 188 5 - case 18: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 21: return; // 177 - } -} -function java_lang_String_consVLjava_lang_String(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg1); // 43 - case 5: stack.push(stack.pop().count); // 180 1 97 - case 8: arg2 = stack.pop(); // 61 - case 9: stack.push(arg1); // 43 - case 10: stack.push(stack.pop().value); // 180 1 100 - case 13: arg3 = stack.pop(); // 78 - case 14: stack.push(arg3); // 45 - case 15: stack.push(stack.pop().length); // 190 - case 16: stack.push(arg2); // 28 - case 17: if (stack.pop() >= stack.pop()) { gt = 41; continue; } // 164 0 24 - case 20: stack.push(arg1); // 43 - case 21: stack.push(stack.pop().offset); // 180 1 99 - case 24: arg5 = stack.pop() // 54 5 - case 26: stack.push(arg3); // 45 - case 27: stack.push(arg5); // 21 5 - case 29: stack.push(arg5); // 21 5 - case 31: stack.push(arg2); // 28 - case 32: stack.push(stack.pop() + stack.pop()); // 96 - case 33: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_Arrays_copyOfRangeACACAIAI(v0, v1, v2)); } // 184 1 173 - case 36: arg4 = stack.pop() // 58 4 - case 38: gt = 44; continue; // 167 0 6 - case 41: stack.push(arg3); // 45 - case 42: arg4 = stack.pop() // 58 4 - case 44: stack.push(arg0); // 42 - case 45: stack.push(0); // 3 - case 46: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 49: stack.push(arg0); // 42 - case 50: stack.push(arg2); // 28 - case 51: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 54: stack.push(arg0); // 42 - case 55: stack.push(arg4); // 25 4 - case 57: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 60: return; // 177 - } -} -*/ -function java_lang_String_consVAC(arg0,arg1) { - arg0.r = arg1.join(""); -} -/* -function java_lang_String_consVACII(arg0,arg1,arg2,arg3) { - var arg4; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg2); // 28 - case 5: if (stack.pop() >= 0) { gt = 17; continue; } // 156 0 12 - case 8: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 11: stack.push(stack[stack.length - 1]); // 89 - case 12: stack.push(arg2); // 28 - case 13: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 16: // 191 - case 17: stack.push(arg3); // 29 - case 18: if (stack.pop() >= 0) { gt = 30; continue; } // 156 0 12 - case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 24: stack.push(stack[stack.length - 1]); // 89 - case 25: stack.push(arg3); // 29 - case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 29: // 191 - case 30: stack.push(arg2); // 28 - case 31: stack.push(arg1); // 43 - case 32: stack.push(stack.pop().length); // 190 - case 33: stack.push(arg3); // 29 - case 34: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 35: if (stack.pop() >= stack.pop()) { gt = 49; continue; } // 164 0 14 - case 38: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 41: stack.push(stack[stack.length - 1]); // 89 - case 42: stack.push(arg2); // 28 - case 43: stack.push(arg3); // 29 - case 44: stack.push(stack.pop() + stack.pop()); // 96 - case 45: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 48: // 191 - case 49: stack.push(arg0); // 42 - case 50: stack.push(0); // 3 - case 51: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 54: stack.push(arg0); // 42 - case 55: stack.push(arg3); // 29 - case 56: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 59: stack.push(arg0); // 42 - case 60: stack.push(arg1); // 43 - case 61: stack.push(arg2); // 28 - case 62: stack.push(arg2); // 28 - case 63: stack.push(arg3); // 29 - case 64: stack.push(stack.pop() + stack.pop()); // 96 - case 65: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_Arrays_copyOfRangeACACAIAI(v0, v1, v2)); } // 184 1 173 - case 68: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 71: return; // 177 - } -} -function java_lang_String_consVAIII(arg0,arg1,arg2,arg3) { - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg2); // 28 - case 5: if (stack.pop() >= 0) { gt = 17; continue; } // 156 0 12 - case 8: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 11: stack.push(stack[stack.length - 1]); // 89 - case 12: stack.push(arg2); // 28 - case 13: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 16: // 191 - case 17: stack.push(arg3); // 29 - case 18: if (stack.pop() >= 0) { gt = 30; continue; } // 156 0 12 - case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 24: stack.push(stack[stack.length - 1]); // 89 - case 25: stack.push(arg3); // 29 - case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 29: // 191 - case 30: stack.push(arg2); // 28 - case 31: stack.push(arg1); // 43 - case 32: stack.push(stack.pop().length); // 190 - case 33: stack.push(arg3); // 29 - case 34: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 35: if (stack.pop() >= stack.pop()) { gt = 49; continue; } // 164 0 14 - case 38: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 41: stack.push(stack[stack.length - 1]); // 89 - case 42: stack.push(arg2); // 28 - case 43: stack.push(arg3); // 29 - case 44: stack.push(stack.pop() + stack.pop()); // 96 - case 45: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 48: // 191 - case 49: stack.push(0); // 3 - case 50: arg4 = stack.pop() // 54 4 - case 52: stack.push(1); // 4 - case 53: arg5 = stack.pop() // 54 5 - case 55: stack.push(arg3); // 29 - case 56: stack.push(arg5); // 21 5 - case 58: stack.push(stack.pop() + stack.pop()); // 96 - case 59: stack.push(new Array(stack.pop())); // 188 5 - case 61: arg6 = stack.pop() // 58 6 - case 63: stack.push(arg2); // 28 - case 64: arg7 = stack.pop() // 54 7 - case 66: stack.push(0); // 3 - case 67: arg8 = stack.pop() // 54 8 - case 69: stack.push(0); // 3 - case 70: arg9 = stack.pop() // 54 9 - case 72: stack.push(arg9); // 21 9 - case 74: stack.push(arg3); // 29 - case 75: if (stack.pop() <= stack.pop()) { gt = 255; continue; } // 162 0 180 - case 78: stack.push(arg1); // 43 - case 79: stack.push(arg7); // 21 7 - case 81: arg7++; // 132 7 1 - case 84: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 46 - case 85: arg10 = stack.pop() // 54 10 - case 87: stack.push(arg10); // 21 10 - case 89: if (stack.pop() >= 0) { gt = 100; continue; } // 156 0 11 - case 92: stack.push(new java_lang_IllegalArgumentException); // 187 0 193 - case 95: stack.push(stack[stack.length - 1]); // 89 - case 96: { java_lang_IllegalArgumentException_consV(stack.pop()); } // 183 1 123 - case 99: // 191 - case 100: stack.push(arg5); // 21 5 - case 102: if (stack.pop() > 0) { gt = 195; continue; } // 157 0 93 - case 105: stack.push(arg8); // 21 8 - case 107: stack.push(1); // 4 - case 108: stack.push(stack.pop() + stack.pop()); // 96 - case 109: stack.push(arg6); // 25 6 - case 111: stack.push(stack.pop().length); // 190 - case 112: if (stack.pop() > stack.pop()) { gt = 195; continue; } // 161 0 83 - case 115: stack.push(arg4); // 21 4 - case 117: if (stack.pop() != 0) { gt = 153; continue; } // 154 0 36 - case 120: stack.push(arg5); // 21 5 - case 122: // 116 - case 123: stack.push(1); // 4 - case 124: stack.push(stack.pop() + stack.pop()); // 96 - case 125: stack.push(arg3); // 29 - case 126: stack.push(stack.pop() * stack.pop()); // 104 - case 127: stack.push(10); // 16 10 - case 129: // 120 - case 130: stack.push(arg9); // 21 9 - case 132: { var tmp = stack.pop(); stack.push(Math.floor(stack.pop() / tmp)); } // 108 - case 133: arg4 = stack.pop() // 54 4 - case 135: stack.push(arg4); // 21 4 - case 137: stack.push(10); // 16 10 - case 139: // 122 - case 140: arg4 = stack.pop() // 54 4 - case 142: stack.push(arg4); // 21 4 - case 144: if (stack.pop() > 0) { gt = 159; continue; } // 157 0 15 - case 147: stack.push(1); // 4 - case 148: arg4 = stack.pop() // 54 4 - case 150: gt = 159; continue; // 167 0 9 - case 153: stack.push(arg4); // 21 4 - case 155: stack.push(2); // 5 - case 156: stack.push(stack.pop() * stack.pop()); // 104 - case 157: arg4 = stack.pop() // 54 4 - case 159: stack.push(arg6); // 25 6 - case 161: stack.push(stack.pop().length); // 190 - case 162: stack.push(arg4); // 21 4 - case 164: stack.push(stack.pop() + stack.pop()); // 96 - case 165: stack.push(arg3); // 29 - case 166: stack.push(2); // 5 - case 167: stack.push(stack.pop() * stack.pop()); // 104 - case 168: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Math_minIII(v0, v1)); } // 184 1 127 - case 171: arg11 = stack.pop() // 54 11 - case 173: stack.push(arg11); // 21 11 - case 175: stack.push(arg6); // 25 6 - case 177: stack.push(stack.pop().length); // 190 - case 178: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 179: stack.push(arg3); // 29 - case 180: stack.push(arg9); // 21 9 - case 182: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 183: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 184: arg5 = stack.pop() // 54 5 - case 186: stack.push(arg6); // 25 6 - case 188: stack.push(arg11); // 21 11 - case 190: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_Arrays_copyOfACACAI(v0, v1)); } // 184 1 172 - case 193: arg6 = stack.pop() // 58 6 - case 195: stack.push(arg10); // 21 10 - case 197: stack.push(65536); // 18 3 - case 199: if (stack.pop() <= stack.pop()) { gt = 216; continue; } // 162 0 17 - case 202: stack.push(arg6); // 25 6 - case 204: stack.push(arg8); // 21 8 - case 206: arg8++; // 132 8 1 - case 209: stack.push(arg10); // 21 10 - case 211: // number conversion // 146 - case 212: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 213: gt = 249; continue; // 167 0 36 - case 216: stack.push(arg10); // 21 10 - case 218: stack.push(1114111); // 18 4 - case 220: if (stack.pop() < stack.pop()) { gt = 241; continue; } // 163 0 21 - case 223: stack.push(arg10); // 21 10 - case 225: stack.push(arg6); // 25 6 - case 227: stack.push(arg8); // 21 8 - case 229: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_Character_toSurrogatesVIACAI(v0, v1, v2); } // 184 1 112 - case 232: arg8 += 2; // 132 8 2 - case 235: arg5 += 255; // 132 5 255 - case 238: gt = 249; continue; // 167 0 11 - case 241: stack.push(new java_lang_IllegalArgumentException); // 187 0 193 - case 244: stack.push(stack[stack.length - 1]); // 89 - case 245: { java_lang_IllegalArgumentException_consV(stack.pop()); } // 183 1 123 - case 248: // 191 - case 249: arg9++; // 132 9 1 - case 252: gt = 72; continue; // 167 255 76 - case 255: stack.push(arg0); // 42 - case 256: stack.push(0); // 3 - case 257: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 260: stack.push(arg0); // 42 - case 261: stack.push(arg6); // 25 6 - case 263: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 266: stack.push(arg0); // 42 - case 267: stack.push(arg8); // 21 8 - case 269: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 272: return; // 177 - } -} -function java_lang_String_consVABIII(arg0,arg1,arg2,arg3,arg4) { - var arg5; - var arg6; - var arg7; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg1); // 43 - case 5: stack.push(arg3); // 29 - case 6: stack.push(arg4); // 21 4 - case 8: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_checkBoundsVABAIAI(v0, v1, v2); } // 184 1 140 - case 11: stack.push(arg4); // 21 4 - case 13: stack.push(new Array(stack.pop())); // 188 5 - case 15: arg5 = stack.pop() // 58 5 - case 17: stack.push(arg2); // 28 - case 18: if (stack.pop() != 0) { gt = 55; continue; } // 154 0 37 - case 21: stack.push(arg4); // 21 4 - case 23: arg6 = stack.pop() // 54 6 - case 25: stack.push(arg6); // 21 6 - case 27: arg6 += 255; // 132 6 255 - case 30: if (stack.pop() <= 0) { gt = 52; continue; } // 158 0 22 - case 33: stack.push(arg5); // 25 5 - case 35: stack.push(arg6); // 21 6 - case 37: stack.push(arg1); // 43 - case 38: stack.push(arg6); // 21 6 - case 40: stack.push(arg3); // 29 - case 41: stack.push(stack.pop() + stack.pop()); // 96 - case 42: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 51 - case 43: stack.push(255); // 17 0 255 - case 46: stack.push(stack.pop() & stack.pop()); // 126 - case 47: // number conversion // 146 - case 48: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 49: gt = 25; continue; // 167 255 232 - case 52: gt = 93; continue; // 167 0 41 - case 55: stack.push(arg2); // 28 - case 56: stack.push(8); // 16 8 - case 58: // 120 - case 59: arg2 = stack.pop(); // 61 - case 60: stack.push(arg4); // 21 4 - case 62: arg6 = stack.pop() // 54 6 - case 64: stack.push(arg6); // 21 6 - case 66: arg6 += 255; // 132 6 255 - case 69: if (stack.pop() <= 0) { gt = 93; continue; } // 158 0 24 - case 72: stack.push(arg5); // 25 5 - case 74: stack.push(arg6); // 21 6 - case 76: stack.push(arg2); // 28 - case 77: stack.push(arg1); // 43 - case 78: stack.push(arg6); // 21 6 - case 80: stack.push(arg3); // 29 - case 81: stack.push(stack.pop() + stack.pop()); // 96 - case 82: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 51 - case 83: stack.push(255); // 17 0 255 - case 86: stack.push(stack.pop() & stack.pop()); // 126 - case 87: stack.push(stack.pop() | stack.pop()); // 128 - case 88: // number conversion // 146 - case 89: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 90: gt = 64; continue; // 167 255 230 - case 93: stack.push(arg0); // 42 - case 94: stack.push(0); // 3 - case 95: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 98: stack.push(arg0); // 42 - case 99: stack.push(arg4); // 21 4 - case 101: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 104: stack.push(arg0); // 42 - case 105: stack.push(arg5); // 25 5 - case 107: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 110: return; // 177 - } -} -function java_lang_String_consVABI(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(arg2); // 28 - case 3: stack.push(0); // 3 - case 4: stack.push(arg1); // 43 - case 5: stack.push(stack.pop().length); // 190 - case 6: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVABAIAIAI(stack.pop(), v0, v1, v2, v3); } // 183 1 141 - case 9: return; // 177 - } -} -function java_lang_String_checkBoundsVABII(arg0,arg1,arg2) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg2); // 28 - case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12 - case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: stack.push(arg2); // 28 - case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 12: // 191 - case 13: stack.push(arg1); // 27 - case 14: if (stack.pop() >= 0) { gt = 26; continue; } // 156 0 12 - case 17: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 20: stack.push(stack[stack.length - 1]); // 89 - case 21: stack.push(arg1); // 27 - case 22: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 25: // 191 - case 26: stack.push(arg1); // 27 - case 27: stack.push(arg0); // 42 - case 28: stack.push(stack.pop().length); // 190 - case 29: stack.push(arg2); // 28 - case 30: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 31: if (stack.pop() >= stack.pop()) { gt = 45; continue; } // 164 0 14 - case 34: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 37: stack.push(stack[stack.length - 1]); // 89 - case 38: stack.push(arg1); // 27 - case 39: stack.push(arg2); // 28 - case 40: stack.push(stack.pop() + stack.pop()); // 96 - case 41: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 44: // 191 - case 45: return; // 177 - } -} -function java_lang_String_consVABIILjava_lang_String(arg0,arg1,arg2,arg3,arg4) { - var arg5; - var arg6; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg4); // 25 4 - case 6: if (stack.pop()) { gt = 19; continue; } // 199 0 13 - case 9: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 12: stack.push(stack[stack.length - 1]); // 89 - case 13: stack.push("charsetName"); // 18 7 - case 15: { var v0 = stack.pop(); java_lang_NullPointerException_consVLjava_lang_String(stack.pop(), v0); } // 183 1 129 - case 18: // 191 - case 19: stack.push(arg1); // 43 - case 20: stack.push(arg2); // 28 - case 21: stack.push(arg3); // 29 - case 22: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_checkBoundsVABAIAI(v0, v1, v2); } // 184 1 140 - case 25: stack.push(arg4); // 25 4 - case 27: stack.push(arg1); // 43 - case 28: stack.push(arg2); // 28 - case 29: stack.push(arg3); // 29 - case 30: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_decodeACLjava_lang_StringABAIAI(v0, v1, v2, v3)); } // 184 1 165 - case 33: arg5 = stack.pop() // 58 5 - case 35: stack.push(arg0); // 42 - case 36: stack.push(0); // 3 - case 37: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 40: stack.push(arg0); // 42 - case 41: stack.push(arg5); // 25 5 - case 43: stack.push(stack.pop().length); // 190 - case 44: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 47: stack.push(arg0); // 42 - case 48: stack.push(arg5); // 25 5 - case 50: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 53: return; // 177 - } -} -function java_lang_String_consVABIILjava_nio_charset_Charset(arg0,arg1,arg2,arg3,arg4) { - var arg5; - var arg6; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg4); // 25 4 - case 6: if (stack.pop()) { gt = 19; continue; } // 199 0 13 - case 9: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 12: stack.push(stack[stack.length - 1]); // 89 - case 13: stack.push("charset"); // 18 6 - case 15: { var v0 = stack.pop(); java_lang_NullPointerException_consVLjava_lang_String(stack.pop(), v0); } // 183 1 129 - case 18: // 191 - case 19: stack.push(arg1); // 43 - case 20: stack.push(arg2); // 28 - case 21: stack.push(arg3); // 29 - case 22: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_checkBoundsVABAIAI(v0, v1, v2); } // 184 1 140 - case 25: stack.push(arg4); // 25 4 - case 27: stack.push(arg1); // 43 - case 28: stack.push(arg2); // 28 - case 29: stack.push(arg3); // 29 - case 30: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_decodeACLjava_nio_charset_CharsetABAIAI(v0, v1, v2, v3)); } // 184 1 167 - case 33: arg5 = stack.pop() // 58 5 - case 35: stack.push(arg0); // 42 - case 36: stack.push(0); // 3 - case 37: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 40: stack.push(arg0); // 42 - case 41: stack.push(arg5); // 25 5 - case 43: stack.push(stack.pop().length); // 190 - case 44: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 47: stack.push(arg0); // 42 - case 48: stack.push(arg5); // 25 5 - case 50: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 53: return; // 177 - } -} -function java_lang_String_consVABLjava_lang_String(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(0); // 3 - case 3: stack.push(arg1); // 43 - case 4: stack.push(stack.pop().length); // 190 - case 5: stack.push(arg2); // 44 - case 6: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVABAIAIALjava_lang_String(stack.pop(), v0, v1, v2, v3); } // 183 1 154 - case 9: return; // 177 - } -} -function java_lang_String_consVABLjava_nio_charset_Charset(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(0); // 3 - case 3: stack.push(arg1); // 43 - case 4: stack.push(stack.pop().length); // 190 - case 5: stack.push(arg2); // 44 - case 6: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVABAIAIALjava_nio_charset_Charset(stack.pop(), v0, v1, v2, v3); } // 183 1 156 - case 9: return; // 177 - } -} -function java_lang_String_consVABII(arg0,arg1,arg2,arg3) { - var arg4; - var arg5; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg1); // 43 - case 5: stack.push(arg2); // 28 - case 6: stack.push(arg3); // 29 - case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_checkBoundsVABAIAI(v0, v1, v2); } // 184 1 140 - case 10: stack.push(arg1); // 43 - case 11: stack.push(arg2); // 28 - case 12: stack.push(arg3); // 29 - case 13: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_decodeACABAIAI(v0, v1, v2)); } // 184 1 163 - case 16: arg4 = stack.pop() // 58 4 - case 18: stack.push(arg0); // 42 - case 19: stack.push(0); // 3 - case 20: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 23: stack.push(arg0); // 42 - case 24: stack.push(arg4); // 25 4 - case 26: stack.push(stack.pop().length); // 190 - case 27: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 30: stack.push(arg0); // 42 - case 31: stack.push(arg4); // 25 4 - case 33: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 36: return; // 177 - } -} -function java_lang_String_consVAB(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(0); // 3 - case 3: stack.push(arg1); // 43 - case 4: stack.push(stack.pop().length); // 190 - case 5: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVABAIAI(stack.pop(), v0, v1, v2); } // 183 1 139 - case 8: return; // 177 - } -} -function java_lang_String_consVLjava_lang_StringBuffer(arg0,arg1) { - var arg2; - var arg3; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg1); // 43 - case 5: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 161 - case 8: arg2 = stack.pop(); // 77 - case 9: stack.push(arg0); // 42 - case 10: stack.push(arg2); // 44 - case 11: stack.push(stack.pop().value); // 180 1 100 - case 14: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 17: stack.push(arg0); // 42 - case 18: stack.push(arg2); // 44 - case 19: stack.push(stack.pop().count); // 180 1 97 - case 22: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 25: stack.push(arg0); // 42 - case 26: stack.push(arg2); // 44 - case 27: stack.push(stack.pop().offset); // 180 1 99 - case 30: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 33: return; // 177 - } -} -function java_lang_String_consVLjava_lang_StringBuilder(arg0,arg1) { - var arg2; - var arg3; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg1); // 43 - case 5: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 162 - case 8: arg2 = stack.pop(); // 77 - case 9: stack.push(arg0); // 42 - case 10: stack.push(arg2); // 44 - case 11: stack.push(stack.pop().value); // 180 1 100 - case 14: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 17: stack.push(arg0); // 42 - case 18: stack.push(arg2); // 44 - case 19: stack.push(stack.pop().count); // 180 1 97 - case 22: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 25: stack.push(arg0); // 42 - case 26: stack.push(arg2); // 44 - case 27: stack.push(stack.pop().offset); // 180 1 99 - case 30: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 33: return; // 177 - } -} -function java_lang_String_consVIIAC(arg0,arg1,arg2,arg3) { - var arg4; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { java_lang_Object_consV(stack.pop()); } // 183 1 130 - case 4: stack.push(arg0); // 42 - case 5: stack.push(arg3); // 45 - case 6: { var v = stack.pop(); stack.pop().value = v; } // 181 1 100 - case 9: stack.push(arg0); // 42 - case 10: stack.push(arg1); // 27 - case 11: { var v = stack.pop(); stack.pop().offset = v; } // 181 1 99 - case 14: stack.push(arg0); // 42 - case 15: stack.push(arg2); // 28 - case 16: { var v = stack.pop(); stack.pop().count = v; } // 181 1 97 - case 19: return; // 177 - } -} -*/ - -function java_lang_String_charAtCI(arg0,arg1) { - return arg0.toString().charAt(arg1); -} -function java_lang_String_lengthI(arg0) { - return arg0.toString().length; -} -function java_lang_String_isEmptyZ(arg0) { - return arg0.toString().length === 0; -} - -/* -function java_lang_String_codePointAtII(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() < 0) { gt = 12; continue; } // 155 0 11 - case 4: stack.push(arg1); // 27 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: if (stack.pop() > stack.pop()) { gt = 21; continue; } // 161 0 12 - case 12: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 15: stack.push(stack[stack.length - 1]); // 89 - case 16: stack.push(arg1); // 27 - case 17: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 20: // 191 - case 21: stack.push(arg0); // 42 - case 22: stack.push(stack.pop().value); // 180 1 100 - case 25: stack.push(arg0); // 42 - case 26: stack.push(stack.pop().offset); // 180 1 99 - case 29: stack.push(arg1); // 27 - case 30: stack.push(stack.pop() + stack.pop()); // 96 - case 31: stack.push(arg0); // 42 - case 32: stack.push(stack.pop().offset); // 180 1 99 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().count); // 180 1 97 - case 39: stack.push(stack.pop() + stack.pop()); // 96 - case 40: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointAtImplAIACAIAI(v0, v1, v2)); } // 184 1 113 - case 43: return stack.pop(); // 172 - } -} -function java_lang_String_codePointBeforeII(arg0,arg1) { - var arg2; - var arg3; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: stack.push(1); // 4 - case 2: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 3: arg2 = stack.pop(); // 61 - case 4: stack.push(arg2); // 28 - case 5: if (stack.pop() < 0) { gt = 16; continue; } // 155 0 11 - case 8: stack.push(arg2); // 28 - case 9: stack.push(arg0); // 42 - case 10: stack.push(stack.pop().count); // 180 1 97 - case 13: if (stack.pop() > stack.pop()) { gt = 25; continue; } // 161 0 12 - case 16: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 19: stack.push(stack[stack.length - 1]); // 89 - case 20: stack.push(arg1); // 27 - case 21: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 24: // 191 - case 25: stack.push(arg0); // 42 - case 26: stack.push(stack.pop().value); // 180 1 100 - case 29: stack.push(arg0); // 42 - case 30: stack.push(stack.pop().offset); // 180 1 99 - case 33: stack.push(arg1); // 27 - case 34: stack.push(stack.pop() + stack.pop()); // 96 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().offset); // 180 1 99 - case 39: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointBeforeImplAIACAIAI(v0, v1, v2)); } // 184 1 114 - case 42: return stack.pop(); // 172 - } -} -function java_lang_String_codePointCountIII(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() < 0) { gt = 17; continue; } // 155 0 16 - case 4: stack.push(arg2); // 28 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: if (stack.pop() < stack.pop()) { gt = 17; continue; } // 163 0 8 - case 12: stack.push(arg1); // 27 - case 13: stack.push(arg2); // 28 - case 14: if (stack.pop() >= stack.pop()) { gt = 25; continue; } // 164 0 11 - case 17: stack.push(new java_lang_IndexOutOfBoundsException); // 187 0 194 - case 20: stack.push(stack[stack.length - 1]); // 89 - case 21: { java_lang_IndexOutOfBoundsException_consV(stack.pop()); } // 183 1 124 - case 24: // 191 - case 25: stack.push(arg0); // 42 - case 26: stack.push(stack.pop().value); // 180 1 100 - case 29: stack.push(arg0); // 42 - case 30: stack.push(stack.pop().offset); // 180 1 99 - case 33: stack.push(arg1); // 27 - case 34: stack.push(stack.pop() + stack.pop()); // 96 - case 35: stack.push(arg2); // 28 - case 36: stack.push(arg1); // 27 - case 37: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 38: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_codePointCountImplAIACAIAI(v0, v1, v2)); } // 184 1 115 - case 41: return stack.pop(); // 172 - } -} -function java_lang_String_offsetByCodePointsIII(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() < 0) { gt = 12; continue; } // 155 0 11 - case 4: stack.push(arg1); // 27 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: if (stack.pop() >= stack.pop()) { gt = 20; continue; } // 164 0 11 - case 12: stack.push(new java_lang_IndexOutOfBoundsException); // 187 0 194 - case 15: stack.push(stack[stack.length - 1]); // 89 - case 16: { java_lang_IndexOutOfBoundsException_consV(stack.pop()); } // 183 1 124 - case 19: // 191 - case 20: stack.push(arg0); // 42 - case 21: stack.push(stack.pop().value); // 180 1 100 - case 24: stack.push(arg0); // 42 - case 25: stack.push(stack.pop().offset); // 180 1 99 - case 28: stack.push(arg0); // 42 - case 29: stack.push(stack.pop().count); // 180 1 97 - case 32: stack.push(arg0); // 42 - case 33: stack.push(stack.pop().offset); // 180 1 99 - case 36: stack.push(arg1); // 27 - case 37: stack.push(stack.pop() + stack.pop()); // 96 - case 38: stack.push(arg2); // 28 - case 39: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_offsetByCodePointsImplAIACAIAIAIAI(v0, v1, v2, v3, v4)); } // 184 1 116 - case 42: stack.push(arg0); // 42 - case 43: stack.push(stack.pop().offset); // 180 1 99 - case 46: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 47: return stack.pop(); // 172 - } -} -*/ - -// public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { -function java_lang_String_getCharsVIIACAI(arg0,arg1,arg2,arg3,arg4) { - var s = arg0.toString(); - while (arg1 < arg2) { - arg3[arg4++] = s[arg1++]; - } -} - -/* -function java_lang_String_getBytesVIIABI(arg0,arg1,arg2,arg3,arg4) { - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12 - case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: stack.push(arg1); // 27 - case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 12: // 191 - case 13: stack.push(arg2); // 28 - case 14: stack.push(arg0); // 42 - case 15: stack.push(stack.pop().count); // 180 1 97 - case 18: if (stack.pop() >= stack.pop()) { gt = 30; continue; } // 164 0 12 - case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 24: stack.push(stack[stack.length - 1]); // 89 - case 25: stack.push(arg2); // 28 - case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 29: // 191 - case 30: stack.push(arg1); // 27 - case 31: stack.push(arg2); // 28 - case 32: if (stack.pop() >= stack.pop()) { gt = 46; continue; } // 164 0 14 - case 35: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 38: stack.push(stack[stack.length - 1]); // 89 - case 39: stack.push(arg2); // 28 - case 40: stack.push(arg1); // 27 - case 41: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 42: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 45: // 191 - case 46: stack.push(arg4); // 21 4 - case 48: arg5 = stack.pop() // 54 5 - case 50: stack.push(arg0); // 42 - case 51: stack.push(stack.pop().offset); // 180 1 99 - case 54: stack.push(arg2); // 28 - case 55: stack.push(stack.pop() + stack.pop()); // 96 - case 56: arg6 = stack.pop() // 54 6 - case 58: stack.push(arg0); // 42 - case 59: stack.push(stack.pop().offset); // 180 1 99 - case 62: stack.push(arg1); // 27 - case 63: stack.push(stack.pop() + stack.pop()); // 96 - case 64: arg7 = stack.pop() // 54 7 - case 66: stack.push(arg0); // 42 - case 67: stack.push(stack.pop().value); // 180 1 100 - case 70: arg8 = stack.pop() // 58 8 - case 72: stack.push(arg7); // 21 7 - case 74: stack.push(arg6); // 21 6 - case 76: if (stack.pop() <= stack.pop()) { gt = 98; continue; } // 162 0 22 - case 79: stack.push(arg3); // 45 - case 80: stack.push(arg5); // 21 5 - case 82: arg5++; // 132 5 1 - case 85: stack.push(arg8); // 25 8 - case 87: stack.push(arg7); // 21 7 - case 89: arg7++; // 132 7 1 - case 92: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 93: // number conversion // 145 - case 94: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 84 - case 95: gt = 72; continue; // 167 255 233 - case 98: return; // 177 - } -} -function java_lang_String_getBytesABLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11 - case 4: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128 - case 11: // 191 - case 12: stack.push(arg1); // 43 - case 13: stack.push(arg0); // 42 - case 14: stack.push(stack.pop().value); // 180 1 100 - case 17: stack.push(arg0); // 42 - case 18: stack.push(stack.pop().offset); // 180 1 99 - case 21: stack.push(arg0); // 42 - case 22: stack.push(stack.pop().count); // 180 1 97 - case 25: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABLjava_lang_StringACAIAI(v0, v1, v2, v3)); } // 184 1 166 - case 28: return stack.pop(); // 176 - } -} -function java_lang_String_getBytesABLjava_nio_charset_Charset(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11 - case 4: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128 - case 11: // 191 - case 12: stack.push(arg1); // 43 - case 13: stack.push(arg0); // 42 - case 14: stack.push(stack.pop().value); // 180 1 100 - case 17: stack.push(arg0); // 42 - case 18: stack.push(stack.pop().offset); // 180 1 99 - case 21: stack.push(arg0); // 42 - case 22: stack.push(stack.pop().count); // 180 1 97 - case 25: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABLjava_nio_charset_CharsetACAIAI(v0, v1, v2, v3)); } // 184 1 168 - case 28: return stack.pop(); // 176 - } -} -function java_lang_String_getBytesAB(arg0) { - var arg1; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: stack.push(arg0); // 42 - case 5: stack.push(stack.pop().offset); // 180 1 99 - case 8: stack.push(arg0); // 42 - case 9: stack.push(stack.pop().count); // 180 1 97 - case 12: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_StringCoding_encodeABACAIAI(v0, v1, v2)); } // 184 1 164 - case 15: return stack.pop(); // 176 - } -} -function java_lang_String_equalsZLjava_lang_Object(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: // 166 - case 3: // 0 - case 4: stack.push(2); // 5 - case 5: stack.push(1); // 4 - case 6: return stack.pop(); // 172 - case 7: stack.push(arg1); // 43 - case 8: stack.push(stack.pop().$instOf_java_lang_String ? 1 : 0); // 193 0 200 - case 11: if (stack.pop() == 0) { gt = 86; continue; } // 153 0 75 - case 14: stack.push(arg1); // 43 - case 15: if(stack[stack.length - 1].$instOf_java_lang_String != 1) throw {}; // 192 0 200 - case 18: arg2 = stack.pop(); // 77 - case 19: stack.push(arg0); // 42 - case 20: stack.push(stack.pop().count); // 180 1 97 - case 23: arg3 = stack.pop(); // 62 - case 24: stack.push(arg3); // 29 - case 25: stack.push(arg2); // 44 - case 26: stack.push(stack.pop().count); // 180 1 97 - case 29: if (stack.pop() != stack.pop()) { gt = 86; continue; } // 160 0 57 - case 32: stack.push(arg0); // 42 - case 33: stack.push(stack.pop().value); // 180 1 100 - case 36: arg4 = stack.pop() // 58 4 - case 38: stack.push(arg2); // 44 - case 39: stack.push(stack.pop().value); // 180 1 100 - case 42: arg5 = stack.pop() // 58 5 - case 44: stack.push(arg0); // 42 - case 45: stack.push(stack.pop().offset); // 180 1 99 - case 48: arg6 = stack.pop() // 54 6 - case 50: stack.push(arg2); // 44 - case 51: stack.push(stack.pop().offset); // 180 1 99 - case 54: arg7 = stack.pop() // 54 7 - case 56: stack.push(arg3); // 29 - case 57: arg3 += 255; // 132 3 255 - case 60: if (stack.pop() == 0) { gt = 84; continue; } // 153 0 24 - case 63: stack.push(arg4); // 25 4 - case 65: stack.push(arg6); // 21 6 - case 67: arg6++; // 132 6 1 - case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 71: stack.push(arg5); // 25 5 - case 73: stack.push(arg7); // 21 7 - case 75: arg7++; // 132 7 1 - case 78: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 79: if (stack.pop() == stack.pop()) { gt = 56; continue; } // 159 255 233 - case 82: stack.push(0); // 3 - case 83: return stack.pop(); // 172 - case 84: stack.push(1); // 4 - case 85: return stack.pop(); // 172 - case 86: stack.push(0); // 3 - case 87: return stack.pop(); // 172 - } -} -function java_lang_String_contentEqualsZLjava_lang_StringBuffer(arg0,arg1) { - var arg2; - var arg3; - var arg4; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: stack.push(stack[stack.length - 1]); // 89 - case 2: arg2 = stack.pop(); // 77 - case 3: // 194 - case 4: stack.push(arg0); // 42 - case 5: stack.push(arg1); // 43 - case 6: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.contentEqualsZLjava_lang_CharSequence(self, v0)); } // 182 1 146 - case 9: stack.push(arg2); // 44 - case 10: // 195 - case 11: return stack.pop(); // 172 - case 12: arg3 = stack.pop(); // 78 - case 13: stack.push(arg2); // 44 - case 14: // 195 - case 15: stack.push(arg3); // 45 - case 16: // 191 - } -} -function java_lang_String_contentEqualsZLjava_lang_CharSequence(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().count); // 180 1 97 - case 4: stack.push(arg1); // 43 - case 5: { var self = stack.pop(); stack.push(self.lengthI(self)); } // 185 1 188 - case 8: // 1 - case 9: // 0 - case 10: if (stack.pop() == stack.pop()) { gt = 15; continue; } // 159 0 5 - case 13: stack.push(0); // 3 - case 14: return stack.pop(); // 172 - case 15: stack.push(arg1); // 43 - case 16: stack.push(stack.pop().$instOf_java_lang_AbstractStringBuilder ? 1 : 0); // 193 0 186 - case 19: if (stack.pop() == 0) { gt = 77; continue; } // 153 0 58 - case 22: stack.push(arg0); // 42 - case 23: stack.push(stack.pop().value); // 180 1 100 - case 26: arg2 = stack.pop(); // 77 - case 27: stack.push(arg1); // 43 - case 28: if(stack[stack.length - 1].$instOf_java_lang_AbstractStringBuilder != 1) throw {}; // 192 0 186 - case 31: { var self = stack.pop(); stack.push(self.getValueAC(self)); } // 182 1 103 - case 34: arg3 = stack.pop(); // 78 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().offset); // 180 1 99 - case 39: arg4 = stack.pop() // 54 4 - case 41: stack.push(0); // 3 - case 42: arg5 = stack.pop() // 54 5 - case 44: stack.push(arg0); // 42 - case 45: stack.push(stack.pop().count); // 180 1 97 - case 48: arg6 = stack.pop() // 54 6 - case 50: stack.push(arg6); // 21 6 - case 52: arg6 += 255; // 132 6 255 - case 55: if (stack.pop() == 0) { gt = 77; continue; } // 153 0 22 - case 58: stack.push(arg2); // 44 - case 59: stack.push(arg4); // 21 4 - case 61: arg4++; // 132 4 1 - case 64: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 65: stack.push(arg3); // 45 - case 66: stack.push(arg5); // 21 5 - case 68: arg5++; // 132 5 1 - case 71: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 72: if (stack.pop() == stack.pop()) { gt = 50; continue; } // 159 255 234 - case 75: stack.push(0); // 3 - case 76: return stack.pop(); // 172 - case 77: stack.push(arg1); // 43 - case 78: stack.push(arg0); // 42 - case 79: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.equalsZLjava_lang_Object(self, v0)); } // 182 1 131 - case 82: if (stack.pop() == 0) { gt = 87; continue; } // 153 0 5 - case 85: stack.push(1); // 4 - case 86: return stack.pop(); // 172 - case 87: stack.push(arg0); // 42 - case 88: stack.push(stack.pop().value); // 180 1 100 - case 91: arg2 = stack.pop(); // 77 - case 92: stack.push(arg0); // 42 - case 93: stack.push(stack.pop().offset); // 180 1 99 - case 96: arg3 = stack.pop(); // 62 - case 97: stack.push(0); // 3 - case 98: arg4 = stack.pop() // 54 4 - case 100: stack.push(arg0); // 42 - case 101: stack.push(stack.pop().count); // 180 1 97 - case 104: arg5 = stack.pop() // 54 5 - case 106: stack.push(arg5); // 21 5 - case 108: arg5 += 255; // 132 5 255 - case 111: if (stack.pop() == 0) { gt = 136; continue; } // 153 0 25 - case 114: stack.push(arg2); // 44 - case 115: stack.push(arg3); // 29 - case 116: arg3++; // 132 3 1 - case 119: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 120: stack.push(arg1); // 43 - case 121: stack.push(arg4); // 21 4 - case 123: arg4++; // 132 4 1 - case 126: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.charAtCI(self, v0)); } // 185 1 189 - case 129: // 2 - case 130: // 0 - case 131: if (stack.pop() == stack.pop()) { gt = 106; continue; } // 159 255 231 - case 134: stack.push(0); // 3 - case 135: return stack.pop(); // 172 - case 136: stack.push(1); // 4 - case 137: return stack.pop(); // 172 - } -} -function java_lang_String_equalsIgnoreCaseZLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: // 166 - case 3: // 0 - case 4: stack.push(4); // 7 - case 5: stack.push(1); // 4 - case 6: gt = 44; continue; // 167 0 38 - case 9: stack.push(arg1); // 43 - case 10: if (!stack.pop()) { gt = 43; continue; } // 198 0 33 - case 13: stack.push(arg1); // 43 - case 14: stack.push(stack.pop().count); // 180 1 97 - case 17: stack.push(arg0); // 42 - case 18: stack.push(stack.pop().count); // 180 1 97 - case 21: if (stack.pop() != stack.pop()) { gt = 43; continue; } // 160 0 22 - case 24: stack.push(arg0); // 42 - case 25: stack.push(1); // 4 - case 26: stack.push(0); // 3 - case 27: stack.push(arg1); // 43 - case 28: stack.push(0); // 3 - case 29: stack.push(arg0); // 42 - case 30: stack.push(stack.pop().count); // 180 1 97 - case 33: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.regionMatchesZZILjava_lang_StringII(self, v0, v1, v2, v3, v4)); } // 182 1 153 - case 36: if (stack.pop() == 0) { gt = 43; continue; } // 153 0 7 - case 39: stack.push(1); // 4 - case 40: gt = 44; continue; // 167 0 4 - case 43: stack.push(0); // 3 - case 44: return stack.pop(); // 172 - } -} -function java_lang_String_compareToILjava_lang_String(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().count); // 180 1 97 - case 4: arg2 = stack.pop(); // 61 - case 5: stack.push(arg1); // 43 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: arg3 = stack.pop(); // 62 - case 10: stack.push(arg2); // 28 - case 11: stack.push(arg3); // 29 - case 12: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Math_minIII(v0, v1)); } // 184 1 127 - case 15: arg4 = stack.pop() // 54 4 - case 17: stack.push(arg0); // 42 - case 18: stack.push(stack.pop().value); // 180 1 100 - case 21: arg5 = stack.pop() // 58 5 - case 23: stack.push(arg1); // 43 - case 24: stack.push(stack.pop().value); // 180 1 100 - case 27: arg6 = stack.pop() // 58 6 - case 29: stack.push(arg0); // 42 - case 30: stack.push(stack.pop().offset); // 180 1 99 - case 33: arg7 = stack.pop() // 54 7 - case 35: stack.push(arg1); // 43 - case 36: stack.push(stack.pop().offset); // 180 1 99 - case 39: arg8 = stack.pop() // 54 8 - case 41: stack.push(arg7); // 21 7 - case 43: stack.push(arg8); // 21 8 - case 45: if (stack.pop() != stack.pop()) { gt = 102; continue; } // 160 0 57 - case 48: stack.push(arg7); // 21 7 - case 50: arg9 = stack.pop() // 54 9 - case 52: stack.push(arg4); // 21 4 - case 54: stack.push(arg7); // 21 7 - case 56: stack.push(stack.pop() + stack.pop()); // 96 - case 57: arg10 = stack.pop() // 54 10 - case 59: stack.push(arg9); // 21 9 - case 61: stack.push(arg10); // 21 10 - case 63: if (stack.pop() <= stack.pop()) { gt = 99; continue; } // 162 0 36 - case 66: stack.push(arg5); // 25 5 - case 68: stack.push(arg9); // 21 9 - case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 71: arg11 = stack.pop() // 54 11 - case 73: stack.push(arg6); // 25 6 - case 75: stack.push(arg9); // 21 9 - case 77: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 78: arg12 = stack.pop() // 54 12 - case 80: stack.push(arg11); // 21 11 - case 82: stack.push(arg12); // 21 12 - case 84: if (stack.pop() == stack.pop()) { gt = 93; continue; } // 159 0 9 - case 87: stack.push(arg11); // 21 11 - case 89: stack.push(arg12); // 21 12 - case 91: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 92: return stack.pop(); // 172 - case 93: arg9++; // 132 9 1 - case 96: gt = 59; continue; // 167 255 219 - case 99: gt = 146; continue; // 167 0 47 - case 102: stack.push(arg4); // 21 4 - case 104: arg4 += 255; // 132 4 255 - case 107: if (stack.pop() == 0) { gt = 146; continue; } // 153 0 39 - case 110: stack.push(arg5); // 25 5 - case 112: stack.push(arg7); // 21 7 - case 114: arg7++; // 132 7 1 - case 117: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 118: arg9 = stack.pop() // 54 9 - case 120: stack.push(arg6); // 25 6 - case 122: stack.push(arg8); // 21 8 - case 124: arg8++; // 132 8 1 - case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 128: arg10 = stack.pop() // 54 10 - case 130: stack.push(arg9); // 21 9 - case 132: stack.push(arg10); // 21 10 - case 134: if (stack.pop() == stack.pop()) { gt = 143; continue; } // 159 0 9 - case 137: stack.push(arg9); // 21 9 - case 139: stack.push(arg10); // 21 10 - case 141: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 142: return stack.pop(); // 172 - case 143: gt = 102; continue; // 167 255 215 - case 146: stack.push(arg2); // 28 - case 147: stack.push(arg3); // 29 - case 148: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 149: return stack.pop(); // 172 - } -} -function java_lang_String_compareToIgnoreCaseILjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(java_lang_String_CASE_INSENSITIVE_ORDER); // 178 1 102 - case 3: stack.push(arg0); // 42 - case 4: stack.push(arg1); // 43 - case 5: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.compareILjava_lang_ObjectLjava_lang_Object(self, v0, v1)); } // 185 1 190 - case 8: stack.push(0); // 3 - case 9: // 0 - case 10: return stack.pop(); // 172 - } -} -function java_lang_String_regionMatchesZILjava_lang_StringII(arg0,arg1,arg2,arg3,arg4) { - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: arg5 = stack.pop() // 58 5 - case 6: stack.push(arg0); // 42 - case 7: stack.push(stack.pop().offset); // 180 1 99 - case 10: stack.push(arg1); // 27 - case 11: stack.push(stack.pop() + stack.pop()); // 96 - case 12: arg6 = stack.pop() // 54 6 - case 14: stack.push(arg2); // 44 - case 15: stack.push(stack.pop().value); // 180 1 100 - case 18: arg7 = stack.pop() // 58 7 - case 20: stack.push(arg2); // 44 - case 21: stack.push(stack.pop().offset); // 180 1 99 - case 24: stack.push(arg3); // 29 - case 25: stack.push(stack.pop() + stack.pop()); // 96 - case 26: arg8 = stack.pop() // 54 8 - case 28: stack.push(arg3); // 29 - case 29: if (stack.pop() < 0) { gt = 66; continue; } // 155 0 37 - case 32: stack.push(arg1); // 27 - case 33: if (stack.pop() < 0) { gt = 66; continue; } // 155 0 33 - case 36: stack.push(arg1); // 27 - case 37: // number conversion // 133 - case 38: stack.push(arg0); // 42 - case 39: stack.push(stack.pop().count); // 180 1 97 - case 42: // number conversion // 133 - case 43: stack.push(arg4); // 21 4 - case 45: // number conversion // 133 - case 46: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101 - case 47: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148 - case 48: if (stack.pop() > 0) { gt = 66; continue; } // 157 0 18 - case 51: stack.push(arg3); // 29 - case 52: // number conversion // 133 - case 53: stack.push(arg2); // 44 - case 54: stack.push(stack.pop().count); // 180 1 97 - case 57: // number conversion // 133 - case 58: stack.push(arg4); // 21 4 - case 60: // number conversion // 133 - case 61: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101 - case 62: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148 - case 63: if (stack.pop() <= 0) { gt = 68; continue; } // 158 0 5 - case 66: stack.push(0); // 3 - case 67: return stack.pop(); // 172 - case 68: stack.push(arg4); // 21 4 - case 70: arg4 += 255; // 132 4 255 - case 73: if (stack.pop() <= 0) { gt = 97; continue; } // 158 0 24 - case 76: stack.push(arg5); // 25 5 - case 78: stack.push(arg6); // 21 6 - case 80: arg6++; // 132 6 1 - case 83: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 84: stack.push(arg7); // 25 7 - case 86: stack.push(arg8); // 21 8 - case 88: arg8++; // 132 8 1 - case 91: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 92: if (stack.pop() == stack.pop()) { gt = 68; continue; } // 159 255 232 - case 95: stack.push(0); // 3 - case 96: return stack.pop(); // 172 - case 97: stack.push(1); // 4 - case 98: return stack.pop(); // 172 - } -} -function java_lang_String_regionMatchesZZILjava_lang_StringII(arg0,arg1,arg2,arg3,arg4,arg5) { - var arg6; - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; - var arg14; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: arg6 = stack.pop() // 58 6 - case 6: stack.push(arg0); // 42 - case 7: stack.push(stack.pop().offset); // 180 1 99 - case 10: stack.push(arg2); // 28 - case 11: stack.push(stack.pop() + stack.pop()); // 96 - case 12: arg7 = stack.pop() // 54 7 - case 14: stack.push(arg3); // 45 - case 15: stack.push(stack.pop().value); // 180 1 100 - case 18: arg8 = stack.pop() // 58 8 - case 20: stack.push(arg3); // 45 - case 21: stack.push(stack.pop().offset); // 180 1 99 - case 24: stack.push(arg4); // 21 4 - case 26: stack.push(stack.pop() + stack.pop()); // 96 - case 27: arg9 = stack.pop() // 54 9 - case 29: stack.push(arg4); // 21 4 - case 31: if (stack.pop() < 0) { gt = 69; continue; } // 155 0 38 - case 34: stack.push(arg2); // 28 - case 35: if (stack.pop() < 0) { gt = 69; continue; } // 155 0 34 - case 38: stack.push(arg2); // 28 - case 39: // number conversion // 133 - case 40: stack.push(arg0); // 42 - case 41: stack.push(stack.pop().count); // 180 1 97 - case 44: // number conversion // 133 - case 45: stack.push(arg5); // 21 5 - case 47: // number conversion // 133 - case 48: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101 - case 49: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148 - case 50: if (stack.pop() > 0) { gt = 69; continue; } // 157 0 19 - case 53: stack.push(arg4); // 21 4 - case 55: // number conversion // 133 - case 56: stack.push(arg3); // 45 - case 57: stack.push(stack.pop().count); // 180 1 97 - case 60: // number conversion // 133 - case 61: stack.push(arg5); // 21 5 - case 63: // number conversion // 133 - case 64: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 101 - case 65: { var delta = stack.pop() - stack.pop(); stack.push(delta < 0 ?-1 : (delta == 0 ? 0 : 1)); } // 148 - case 66: if (stack.pop() <= 0) { gt = 71; continue; } // 158 0 5 - case 69: stack.push(0); // 3 - case 70: return stack.pop(); // 172 - case 71: stack.push(arg5); // 21 5 - case 73: arg5 += 255; // 132 5 255 - case 76: if (stack.pop() <= 0) { gt = 155; continue; } // 158 0 79 - case 79: stack.push(arg6); // 25 6 - case 81: stack.push(arg7); // 21 7 - case 83: arg7++; // 132 7 1 - case 86: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 87: arg10 = stack.pop() // 54 10 - case 89: stack.push(arg8); // 25 8 - case 91: stack.push(arg9); // 21 9 - case 93: arg9++; // 132 9 1 - case 96: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 97: arg11 = stack.pop() // 54 11 - case 99: stack.push(arg10); // 21 10 - case 101: stack.push(arg11); // 21 11 - case 103: if (stack.pop() != stack.pop()) { gt = 109; continue; } // 160 0 6 - case 106: gt = 71; continue; // 167 255 221 - case 109: stack.push(arg1); // 27 - case 110: if (stack.pop() == 0) { gt = 153; continue; } // 153 0 43 - case 113: stack.push(arg10); // 21 10 - case 115: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCC(v0)); } // 184 1 105 - case 118: arg12 = stack.pop() // 54 12 - case 120: stack.push(arg11); // 21 11 - case 122: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCC(v0)); } // 184 1 105 - case 125: arg13 = stack.pop() // 54 13 - case 127: stack.push(arg12); // 21 12 - case 129: stack.push(arg13); // 21 13 - case 131: if (stack.pop() != stack.pop()) { gt = 137; continue; } // 160 0 6 - case 134: gt = 71; continue; // 167 255 193 - case 137: stack.push(arg12); // 21 12 - case 139: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104 - case 142: stack.push(arg13); // 21 13 - case 144: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104 - case 147: if (stack.pop() != stack.pop()) { gt = 153; continue; } // 160 0 6 - case 150: gt = 71; continue; // 167 255 177 - case 153: stack.push(0); // 3 - case 154: return stack.pop(); // 172 - case 155: stack.push(1); // 4 - case 156: return stack.pop(); // 172 - } -} -function java_lang_String_startsWithZLjava_lang_StringI(arg0,arg1,arg2) { - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: arg3 = stack.pop(); // 78 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().offset); // 180 1 99 - case 9: stack.push(arg2); // 28 - case 10: stack.push(stack.pop() + stack.pop()); // 96 - case 11: arg4 = stack.pop() // 54 4 - case 13: stack.push(arg1); // 43 - case 14: stack.push(stack.pop().value); // 180 1 100 - case 17: arg5 = stack.pop() // 58 5 - case 19: stack.push(arg1); // 43 - case 20: stack.push(stack.pop().offset); // 180 1 99 - case 23: arg6 = stack.pop() // 54 6 - case 25: stack.push(arg1); // 43 - case 26: stack.push(stack.pop().count); // 180 1 97 - case 29: arg7 = stack.pop() // 54 7 - case 31: stack.push(arg2); // 28 - case 32: if (stack.pop() < 0) { gt = 46; continue; } // 155 0 14 - case 35: stack.push(arg2); // 28 - case 36: stack.push(arg0); // 42 - case 37: stack.push(stack.pop().count); // 180 1 97 - case 40: stack.push(arg7); // 21 7 - case 42: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 43: if (stack.pop() >= stack.pop()) { gt = 48; continue; } // 164 0 5 - case 46: stack.push(0); // 3 - case 47: return stack.pop(); // 172 - case 48: arg7 += 255; // 132 7 255 - case 51: stack.push(arg7); // 21 7 - case 53: if (stack.pop() < 0) { gt = 76; continue; } // 155 0 23 - case 56: stack.push(arg3); // 45 - case 57: stack.push(arg4); // 21 4 - case 59: arg4++; // 132 4 1 - case 62: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 63: stack.push(arg5); // 25 5 - case 65: stack.push(arg6); // 21 6 - case 67: arg6++; // 132 6 1 - case 70: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 71: if (stack.pop() == stack.pop()) { gt = 48; continue; } // 159 255 233 - case 74: stack.push(0); // 3 - case 75: return stack.pop(); // 172 - case 76: stack.push(1); // 4 - case 77: return stack.pop(); // 172 - } -} -function java_lang_String_startsWithZLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(0); // 3 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.startsWithZLjava_lang_StringI(self, v0, v1)); } // 182 1 152 - case 6: return stack.pop(); // 172 - } -} -function java_lang_String_endsWithZLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().count); // 180 1 97 - case 6: stack.push(arg1); // 43 - case 7: stack.push(stack.pop().count); // 180 1 97 - case 10: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 11: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.startsWithZLjava_lang_StringI(self, v0, v1)); } // 182 1 152 - case 14: return stack.pop(); // 172 - } -} -function java_lang_String_hashCodeI(arg0) { - var arg1; - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().hash); // 180 1 98 - case 4: arg1 = stack.pop(); // 60 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: arg2 = stack.pop(); // 61 - case 10: stack.push(arg1); // 27 - case 11: if (stack.pop() != 0) { gt = 62; continue; } // 154 0 51 - case 14: stack.push(arg2); // 28 - case 15: if (stack.pop() <= 0) { gt = 62; continue; } // 158 0 47 - case 18: stack.push(arg0); // 42 - case 19: stack.push(stack.pop().offset); // 180 1 99 - case 22: arg3 = stack.pop(); // 62 - case 23: stack.push(arg0); // 42 - case 24: stack.push(stack.pop().value); // 180 1 100 - case 27: arg4 = stack.pop() // 58 4 - case 29: stack.push(0); // 3 - case 30: arg5 = stack.pop() // 54 5 - case 32: stack.push(arg5); // 21 5 - case 34: stack.push(arg2); // 28 - case 35: if (stack.pop() <= stack.pop()) { gt = 57; continue; } // 162 0 22 - case 38: stack.push(31); // 16 31 - case 40: stack.push(arg1); // 27 - case 41: stack.push(stack.pop() * stack.pop()); // 104 - case 42: stack.push(arg4); // 25 4 - case 44: stack.push(arg3); // 29 - case 45: arg3++; // 132 3 1 - case 48: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 49: stack.push(stack.pop() + stack.pop()); // 96 - case 50: arg1 = stack.pop(); // 60 - case 51: arg5++; // 132 5 1 - case 54: gt = 32; continue; // 167 255 234 - case 57: stack.push(arg0); // 42 - case 58: stack.push(arg1); // 27 - case 59: { var v = stack.pop(); stack.pop().hash = v; } // 181 1 98 - case 62: stack.push(arg1); // 27 - case 63: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfII(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 27 - case 2: stack.push(0); // 3 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfIII(self, v0, v1)); } // 182 1 135 - case 6: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfIII(arg0,arg1,arg2) { - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().offset); // 180 1 99 - case 4: stack.push(arg0); // 42 - case 5: stack.push(stack.pop().count); // 180 1 97 - case 8: stack.push(stack.pop() + stack.pop()); // 96 - case 9: arg3 = stack.pop(); // 62 - case 10: stack.push(arg0); // 42 - case 11: stack.push(stack.pop().value); // 180 1 100 - case 14: arg4 = stack.pop() // 58 4 - case 16: stack.push(arg2); // 28 - case 17: if (stack.pop() >= 0) { gt = 25; continue; } // 156 0 8 - case 20: stack.push(0); // 3 - case 21: arg2 = stack.pop(); // 61 - case 22: gt = 35; continue; // 167 0 13 - case 25: stack.push(arg2); // 28 - case 26: stack.push(arg0); // 42 - case 27: stack.push(stack.pop().count); // 180 1 97 - case 30: if (stack.pop() > stack.pop()) { gt = 35; continue; } // 161 0 5 - case 33: // 2 - case 34: return stack.pop(); // 172 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().offset); // 180 1 99 - case 39: stack.push(arg2); // 28 - case 40: stack.push(stack.pop() + stack.pop()); // 96 - case 41: arg5 = stack.pop() // 54 5 - case 43: stack.push(arg1); // 27 - case 44: stack.push(65536); // 18 3 - case 46: if (stack.pop() <= stack.pop()) { gt = 80; continue; } // 162 0 34 - case 49: stack.push(arg5); // 21 5 - case 51: stack.push(arg3); // 29 - case 52: if (stack.pop() <= stack.pop()) { gt = 78; continue; } // 162 0 26 - case 55: stack.push(arg4); // 25 4 - case 57: stack.push(arg5); // 21 5 - case 59: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 60: stack.push(arg1); // 27 - case 61: if (stack.pop() != stack.pop()) { gt = 72; continue; } // 160 0 11 - case 64: stack.push(arg5); // 21 5 - case 66: stack.push(arg0); // 42 - case 67: stack.push(stack.pop().offset); // 180 1 99 - case 70: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 71: return stack.pop(); // 172 - case 72: arg5++; // 132 5 1 - case 75: gt = 49; continue; // 167 255 230 - case 78: // 2 - case 79: return stack.pop(); // 172 - case 80: stack.push(arg1); // 27 - case 81: stack.push(1114111); // 18 4 - case 83: if (stack.pop() < stack.pop()) { gt = 149; continue; } // 163 0 66 - case 86: stack.push(arg1); // 27 - case 87: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109 - case 90: arg6 = stack.pop() // 58 6 - case 92: stack.push(arg5); // 21 5 - case 94: stack.push(arg3); // 29 - case 95: if (stack.pop() <= stack.pop()) { gt = 149; continue; } // 162 0 54 - case 98: stack.push(arg4); // 25 4 - case 100: stack.push(arg5); // 21 5 - case 102: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 103: stack.push(arg6); // 25 6 - case 105: stack.push(0); // 3 - case 106: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 107: if (stack.pop() != stack.pop()) { gt = 143; continue; } // 160 0 36 - case 110: stack.push(arg5); // 21 5 - case 112: stack.push(1); // 4 - case 113: stack.push(stack.pop() + stack.pop()); // 96 - case 114: stack.push(arg3); // 29 - case 115: if (stack.pop() != stack.pop()) { gt = 121; continue; } // 160 0 6 - case 118: gt = 149; continue; // 167 0 31 - case 121: stack.push(arg4); // 25 4 - case 123: stack.push(arg5); // 21 5 - case 125: stack.push(1); // 4 - case 126: stack.push(stack.pop() + stack.pop()); // 96 - case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 128: stack.push(arg6); // 25 6 - case 130: stack.push(1); // 4 - case 131: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 132: if (stack.pop() != stack.pop()) { gt = 143; continue; } // 160 0 11 - case 135: stack.push(arg5); // 21 5 - case 137: stack.push(arg0); // 42 - case 138: stack.push(stack.pop().offset); // 180 1 99 - case 141: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 142: return stack.pop(); // 172 - case 143: arg5++; // 132 5 1 - case 146: gt = 92; continue; // 167 255 202 - case 149: // 2 - case 150: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfII(arg0,arg1) { - var arg2; -; - var stack = new Array(4); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 27 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().count); // 180 1 97 - case 6: stack.push(1); // 4 - case 7: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 8: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.lastIndexOfIII(self, v0, v1)); } // 182 1 136 - case 11: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfIII(arg0,arg1,arg2) { - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().offset); // 180 1 99 - case 4: arg3 = stack.pop(); // 62 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().value); // 180 1 100 - case 9: arg4 = stack.pop() // 58 4 - case 11: stack.push(arg0); // 42 - case 12: stack.push(stack.pop().offset); // 180 1 99 - case 15: stack.push(arg2); // 28 - case 16: stack.push(arg0); // 42 - case 17: stack.push(stack.pop().count); // 180 1 97 - case 20: if (stack.pop() > stack.pop()) { gt = 32; continue; } // 161 0 12 - case 23: stack.push(arg0); // 42 - case 24: stack.push(stack.pop().count); // 180 1 97 - case 27: stack.push(1); // 4 - case 28: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 29: gt = 33; continue; // 167 0 4 - case 32: stack.push(arg2); // 28 - case 33: stack.push(stack.pop() + stack.pop()); // 96 - case 34: arg5 = stack.pop() // 54 5 - case 36: stack.push(arg1); // 27 - case 37: stack.push(65536); // 18 3 - case 39: if (stack.pop() <= stack.pop()) { gt = 73; continue; } // 162 0 34 - case 42: stack.push(arg5); // 21 5 - case 44: stack.push(arg3); // 29 - case 45: if (stack.pop() > stack.pop()) { gt = 71; continue; } // 161 0 26 - case 48: stack.push(arg4); // 25 4 - case 50: stack.push(arg5); // 21 5 - case 52: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 53: stack.push(arg1); // 27 - case 54: if (stack.pop() != stack.pop()) { gt = 65; continue; } // 160 0 11 - case 57: stack.push(arg5); // 21 5 - case 59: stack.push(arg0); // 42 - case 60: stack.push(stack.pop().offset); // 180 1 99 - case 63: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 64: return stack.pop(); // 172 - case 65: arg5 += 255; // 132 5 255 - case 68: gt = 42; continue; // 167 255 230 - case 71: // 2 - case 72: return stack.pop(); // 172 - case 73: stack.push(arg0); // 42 - case 74: stack.push(stack.pop().offset); // 180 1 99 - case 77: stack.push(arg0); // 42 - case 78: stack.push(stack.pop().count); // 180 1 97 - case 81: stack.push(stack.pop() + stack.pop()); // 96 - case 82: arg6 = stack.pop() // 54 6 - case 84: stack.push(arg1); // 27 - case 85: stack.push(1114111); // 18 4 - case 87: if (stack.pop() < stack.pop()) { gt = 154; continue; } // 163 0 67 - case 90: stack.push(arg1); // 27 - case 91: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109 - case 94: arg7 = stack.pop() // 58 7 - case 96: stack.push(arg5); // 21 5 - case 98: stack.push(arg3); // 29 - case 99: if (stack.pop() > stack.pop()) { gt = 154; continue; } // 161 0 55 - case 102: stack.push(arg4); // 25 4 - case 104: stack.push(arg5); // 21 5 - case 106: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 107: stack.push(arg7); // 25 7 - case 109: stack.push(0); // 3 - case 110: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 111: if (stack.pop() != stack.pop()) { gt = 148; continue; } // 160 0 37 - case 114: stack.push(arg5); // 21 5 - case 116: stack.push(1); // 4 - case 117: stack.push(stack.pop() + stack.pop()); // 96 - case 118: stack.push(arg6); // 21 6 - case 120: if (stack.pop() != stack.pop()) { gt = 126; continue; } // 160 0 6 - case 123: gt = 154; continue; // 167 0 31 - case 126: stack.push(arg4); // 25 4 - case 128: stack.push(arg5); // 21 5 - case 130: stack.push(1); // 4 - case 131: stack.push(stack.pop() + stack.pop()); // 96 - case 132: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 133: stack.push(arg7); // 25 7 - case 135: stack.push(1); // 4 - case 136: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 137: if (stack.pop() != stack.pop()) { gt = 148; continue; } // 160 0 11 - case 140: stack.push(arg5); // 21 5 - case 142: stack.push(arg0); // 42 - case 143: stack.push(stack.pop().offset); // 180 1 99 - case 146: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 147: return stack.pop(); // 172 - case 148: arg5 += 255; // 132 5 255 - case 151: gt = 96; continue; // 167 255 201 - case 154: // 2 - case 155: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfILjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(0); // 3 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfILjava_lang_StringI(self, v0, v1)); } // 182 1 150 - case 6: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfILjava_lang_StringI(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(7); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: stack.push(arg0); // 42 - case 5: stack.push(stack.pop().offset); // 180 1 99 - case 8: stack.push(arg0); // 42 - case 9: stack.push(stack.pop().count); // 180 1 97 - case 12: stack.push(arg1); // 43 - case 13: stack.push(stack.pop().value); // 180 1 100 - case 16: stack.push(arg1); // 43 - case 17: stack.push(stack.pop().offset); // 180 1 99 - case 20: stack.push(arg1); // 43 - case 21: stack.push(stack.pop().count); // 180 1 97 - case 24: stack.push(arg2); // 28 - case 25: { var v6 = stack.pop(); var v5 = stack.pop(); var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_indexOfAIACAIAIACAIAIAI(v0, v1, v2, v3, v4, v5, v6)); } // 184 1 144 - case 28: return stack.pop(); // 172 - } -} -function java_lang_String_indexOfIACIIACIII(arg0,arg1,arg2,arg3,arg4,arg5,arg6) { - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg6); // 21 6 - case 2: stack.push(arg2); // 28 - case 3: if (stack.pop() > stack.pop()) { gt = 17; continue; } // 161 0 14 - case 6: stack.push(arg5); // 21 5 - case 8: if (stack.pop() != 0) { gt = 15; continue; } // 154 0 7 - case 11: stack.push(arg2); // 28 - case 12: gt = 16; continue; // 167 0 4 - case 15: // 2 - case 16: return stack.pop(); // 172 - case 17: stack.push(arg6); // 21 6 - case 19: if (stack.pop() >= 0) { gt = 25; continue; } // 156 0 6 - case 22: stack.push(0); // 3 - case 23: arg6 = stack.pop() // 54 6 - case 25: stack.push(arg5); // 21 5 - case 27: if (stack.pop() != 0) { gt = 33; continue; } // 154 0 6 - case 30: stack.push(arg6); // 21 6 - case 32: return stack.pop(); // 172 - case 33: stack.push(arg3); // 45 - case 34: stack.push(arg4); // 21 4 - case 36: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 37: arg7 = stack.pop() // 54 7 - case 39: stack.push(arg1); // 27 - case 40: stack.push(arg2); // 28 - case 41: stack.push(arg5); // 21 5 - case 43: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 44: stack.push(stack.pop() + stack.pop()); // 96 - case 45: arg8 = stack.pop() // 54 8 - case 47: stack.push(arg1); // 27 - case 48: stack.push(arg6); // 21 6 - case 50: stack.push(stack.pop() + stack.pop()); // 96 - case 51: arg9 = stack.pop() // 54 9 - case 53: stack.push(arg9); // 21 9 - case 55: stack.push(arg8); // 21 8 - case 57: if (stack.pop() < stack.pop()) { gt = 164; continue; } // 163 0 107 - case 60: stack.push(arg0); // 42 - case 61: stack.push(arg9); // 21 9 - case 63: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 64: stack.push(arg7); // 21 7 - case 66: if (stack.pop() == stack.pop()) { gt = 91; continue; } // 159 0 25 - case 69: arg9++; // 132 9 1 - case 72: stack.push(arg9); // 21 9 - case 74: stack.push(arg8); // 21 8 - case 76: if (stack.pop() < stack.pop()) { gt = 91; continue; } // 163 0 15 - case 79: stack.push(arg0); // 42 - case 80: stack.push(arg9); // 21 9 - case 82: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 83: stack.push(arg7); // 21 7 - case 85: if (stack.pop() == stack.pop()) { gt = 91; continue; } // 159 0 6 - case 88: gt = 69; continue; // 167 255 237 - case 91: stack.push(arg9); // 21 9 - case 93: stack.push(arg8); // 21 8 - case 95: if (stack.pop() < stack.pop()) { gt = 158; continue; } // 163 0 63 - case 98: stack.push(arg9); // 21 9 - case 100: stack.push(1); // 4 - case 101: stack.push(stack.pop() + stack.pop()); // 96 - case 102: arg10 = stack.pop() // 54 10 - case 104: stack.push(arg10); // 21 10 - case 106: stack.push(arg5); // 21 5 - case 108: stack.push(stack.pop() + stack.pop()); // 96 - case 109: stack.push(1); // 4 - case 110: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 111: arg11 = stack.pop() // 54 11 - case 113: stack.push(arg4); // 21 4 - case 115: stack.push(1); // 4 - case 116: stack.push(stack.pop() + stack.pop()); // 96 - case 117: arg12 = stack.pop() // 54 12 - case 119: stack.push(arg10); // 21 10 - case 121: stack.push(arg11); // 21 11 - case 123: if (stack.pop() <= stack.pop()) { gt = 146; continue; } // 162 0 23 - case 126: stack.push(arg0); // 42 - case 127: stack.push(arg10); // 21 10 - case 129: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 130: stack.push(arg3); // 45 - case 131: stack.push(arg12); // 21 12 - case 133: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 134: if (stack.pop() != stack.pop()) { gt = 146; continue; } // 160 0 12 - case 137: arg10++; // 132 10 1 - case 140: arg12++; // 132 12 1 - case 143: gt = 119; continue; // 167 255 232 - case 146: stack.push(arg10); // 21 10 - case 148: stack.push(arg11); // 21 11 - case 150: if (stack.pop() != stack.pop()) { gt = 158; continue; } // 160 0 8 - case 153: stack.push(arg9); // 21 9 - case 155: stack.push(arg1); // 27 - case 156: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 157: return stack.pop(); // 172 - case 158: arg9++; // 132 9 1 - case 161: gt = 53; continue; // 167 255 148 - case 164: // 2 - case 165: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfILjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().count); // 180 1 97 - case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.lastIndexOfILjava_lang_StringI(self, v0, v1)); } // 182 1 151 - case 9: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfILjava_lang_StringI(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(7); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().value); // 180 1 100 - case 4: stack.push(arg0); // 42 - case 5: stack.push(stack.pop().offset); // 180 1 99 - case 8: stack.push(arg0); // 42 - case 9: stack.push(stack.pop().count); // 180 1 97 - case 12: stack.push(arg1); // 43 - case 13: stack.push(stack.pop().value); // 180 1 100 - case 16: stack.push(arg1); // 43 - case 17: stack.push(stack.pop().offset); // 180 1 99 - case 20: stack.push(arg1); // 43 - case 21: stack.push(stack.pop().count); // 180 1 97 - case 24: stack.push(arg2); // 28 - case 25: { var v6 = stack.pop(); var v5 = stack.pop(); var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_lastIndexOfAIACAIAIACAIAIAI(v0, v1, v2, v3, v4, v5, v6)); } // 184 1 145 - case 28: return stack.pop(); // 172 - } -} -function java_lang_String_lastIndexOfIACIIACIII(arg0,arg1,arg2,arg3,arg4,arg5,arg6) { - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; - var arg14; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg2); // 28 - case 1: stack.push(arg5); // 21 5 - case 3: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 4: arg7 = stack.pop() // 54 7 - case 6: stack.push(arg6); // 21 6 - case 8: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 5 - case 11: // 2 - case 12: return stack.pop(); // 172 - case 13: stack.push(arg6); // 21 6 - case 15: stack.push(arg7); // 21 7 - case 17: if (stack.pop() >= stack.pop()) { gt = 24; continue; } // 164 0 7 - case 20: stack.push(arg7); // 21 7 - case 22: arg6 = stack.pop() // 54 6 - case 24: stack.push(arg5); // 21 5 - case 26: if (stack.pop() != 0) { gt = 32; continue; } // 154 0 6 - case 29: stack.push(arg6); // 21 6 - case 31: return stack.pop(); // 172 - case 32: stack.push(arg4); // 21 4 - case 34: stack.push(arg5); // 21 5 - case 36: stack.push(stack.pop() + stack.pop()); // 96 - case 37: stack.push(1); // 4 - case 38: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 39: arg8 = stack.pop() // 54 8 - case 41: stack.push(arg3); // 45 - case 42: stack.push(arg8); // 21 8 - case 44: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 45: arg9 = stack.pop() // 54 9 - case 47: stack.push(arg1); // 27 - case 48: stack.push(arg5); // 21 5 - case 50: stack.push(stack.pop() + stack.pop()); // 96 - case 51: stack.push(1); // 4 - case 52: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 53: arg10 = stack.pop() // 54 10 - case 55: stack.push(arg10); // 21 10 - case 57: stack.push(arg6); // 21 6 - case 59: stack.push(stack.pop() + stack.pop()); // 96 - case 60: arg11 = stack.pop() // 54 11 - case 62: stack.push(arg11); // 21 11 - case 64: stack.push(arg10); // 21 10 - case 66: if (stack.pop() > stack.pop()) { gt = 84; continue; } // 161 0 18 - case 69: stack.push(arg0); // 42 - case 70: stack.push(arg11); // 21 11 - case 72: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 73: stack.push(arg9); // 21 9 - case 75: if (stack.pop() == stack.pop()) { gt = 84; continue; } // 159 0 9 - case 78: arg11 += 255; // 132 11 255 - case 81: gt = 62; continue; // 167 255 237 - case 84: stack.push(arg11); // 21 11 - case 86: stack.push(arg10); // 21 10 - case 88: if (stack.pop() <= stack.pop()) { gt = 93; continue; } // 162 0 5 - case 91: // 2 - case 92: return stack.pop(); // 172 - case 93: stack.push(arg11); // 21 11 - case 95: stack.push(1); // 4 - case 96: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 97: arg12 = stack.pop() // 54 12 - case 99: stack.push(arg12); // 21 12 - case 101: stack.push(arg5); // 21 5 - case 103: stack.push(1); // 4 - case 104: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 105: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 106: arg13 = stack.pop() // 54 13 - case 108: stack.push(arg8); // 21 8 - case 110: stack.push(1); // 4 - case 111: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 112: arg14 = stack.pop() // 54 14 - case 114: stack.push(arg12); // 21 12 - case 116: stack.push(arg13); // 21 13 - case 118: if (stack.pop() >= stack.pop()) { gt = 144; continue; } // 164 0 26 - case 121: stack.push(arg0); // 42 - case 122: stack.push(arg12); // 21 12 - case 124: arg12 += 255; // 132 12 255 - case 127: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 128: stack.push(arg3); // 45 - case 129: stack.push(arg14); // 21 14 - case 131: arg14 += 255; // 132 14 255 - case 134: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 135: if (stack.pop() == stack.pop()) { gt = 114; continue; } // 159 255 235 - case 138: arg11 += 255; // 132 11 255 - case 141: gt = 62; continue; // 167 255 177 - case 144: stack.push(arg13); // 21 13 - case 146: stack.push(arg1); // 27 - case 147: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 148: stack.push(1); // 4 - case 149: stack.push(stack.pop() + stack.pop()); // 96 - case 150: return stack.pop(); // 172 - } -} -function java_lang_String_substringLjava_lang_StringI(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 27 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().count); // 180 1 97 - case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147 - case 9: return stack.pop(); // 176 - } -} -function java_lang_String_substringLjava_lang_StringII(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: if (stack.pop() >= 0) { gt = 13; continue; } // 156 0 12 - case 4: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: stack.push(arg1); // 27 - case 9: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 12: // 191 - case 13: stack.push(arg2); // 28 - case 14: stack.push(arg0); // 42 - case 15: stack.push(stack.pop().count); // 180 1 97 - case 18: if (stack.pop() >= stack.pop()) { gt = 30; continue; } // 164 0 12 - case 21: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 24: stack.push(stack[stack.length - 1]); // 89 - case 25: stack.push(arg2); // 28 - case 26: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 29: // 191 - case 30: stack.push(arg1); // 27 - case 31: stack.push(arg2); // 28 - case 32: if (stack.pop() >= stack.pop()) { gt = 46; continue; } // 164 0 14 - case 35: stack.push(new java_lang_StringIndexOutOfBoundsException); // 187 0 206 - case 38: stack.push(stack[stack.length - 1]); // 89 - case 39: stack.push(arg2); // 28 - case 40: stack.push(arg1); // 27 - case 41: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 42: { var v0 = stack.pop(); java_lang_StringIndexOutOfBoundsException_consVI(stack.pop(), v0); } // 183 1 169 - case 45: // 191 - case 46: stack.push(arg1); // 27 - case 47: if (stack.pop() != 0) { gt = 62; continue; } // 154 0 15 - case 50: stack.push(arg2); // 28 - case 51: stack.push(arg0); // 42 - case 52: stack.push(stack.pop().count); // 180 1 97 - case 55: if (stack.pop() != stack.pop()) { gt = 62; continue; } // 160 0 7 - case 58: stack.push(arg0); // 42 - case 59: gt = 82; continue; // 167 0 23 - case 62: stack.push(new java_lang_String); // 187 0 200 - case 65: stack.push(stack[stack.length - 1]); // 89 - case 66: stack.push(arg0); // 42 - case 67: stack.push(stack.pop().offset); // 180 1 99 - case 70: stack.push(arg1); // 27 - case 71: stack.push(stack.pop() + stack.pop()); // 96 - case 72: stack.push(arg2); // 28 - case 73: stack.push(arg1); // 27 - case 74: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 75: stack.push(arg0); // 42 - case 76: stack.push(stack.pop().value); // 180 1 100 - case 79: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 82: return stack.pop(); // 176 - } -} -function java_lang_String_subSequenceLjava_lang_CharSequenceII(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 27 - case 2: stack.push(arg2); // 28 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147 - case 6: return stack.pop(); // 176 - } -} -function java_lang_String_concatLjava_lang_StringLjava_lang_String(arg0,arg1) { - var arg2; - var arg3; - var arg4; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var self = stack.pop(); stack.push(self.lengthI(self)); } // 182 1 133 - case 4: arg2 = stack.pop(); // 61 - case 5: stack.push(arg2); // 28 - case 6: if (stack.pop() != 0) { gt = 11; continue; } // 154 0 5 - case 9: stack.push(arg0); // 42 - case 10: return stack.pop(); // 176 - case 11: stack.push(arg0); // 42 - case 12: stack.push(stack.pop().count); // 180 1 97 - case 15: stack.push(arg2); // 28 - case 16: stack.push(stack.pop() + stack.pop()); // 96 - case 17: stack.push(new Array(stack.pop())); // 188 5 - case 19: arg3 = stack.pop(); // 78 - case 20: stack.push(arg0); // 42 - case 21: stack.push(0); // 3 - case 22: stack.push(arg0); // 42 - case 23: stack.push(stack.pop().count); // 180 1 97 - case 26: stack.push(arg3); // 45 - case 27: stack.push(0); // 3 - case 28: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138 - case 31: stack.push(arg1); // 43 - case 32: stack.push(0); // 3 - case 33: stack.push(arg2); // 28 - case 34: stack.push(arg3); // 45 - case 35: stack.push(arg0); // 42 - case 36: stack.push(stack.pop().count); // 180 1 97 - case 39: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138 - case 42: stack.push(new java_lang_String); // 187 0 200 - case 45: stack.push(stack[stack.length - 1]); // 89 - case 46: stack.push(0); // 3 - case 47: stack.push(arg0); // 42 - case 48: stack.push(stack.pop().count); // 180 1 97 - case 51: stack.push(arg2); // 28 - case 52: stack.push(stack.pop() + stack.pop()); // 96 - case 53: stack.push(arg3); // 45 - case 54: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 57: return stack.pop(); // 176 - } -} -function java_lang_String_replaceLjava_lang_StringCC(arg0,arg1,arg2) { - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 27 - case 1: stack.push(arg2); // 28 - case 2: if (stack.pop() == stack.pop()) { gt = 140; continue; } // 159 0 138 - case 5: stack.push(arg0); // 42 - case 6: stack.push(stack.pop().count); // 180 1 97 - case 9: arg3 = stack.pop(); // 62 - case 10: // 2 - case 11: arg4 = stack.pop() // 54 4 - case 13: stack.push(arg0); // 42 - case 14: stack.push(stack.pop().value); // 180 1 100 - case 17: arg5 = stack.pop() // 58 5 - case 19: stack.push(arg0); // 42 - case 20: stack.push(stack.pop().offset); // 180 1 99 - case 23: arg6 = stack.pop() // 54 6 - case 25: arg4++; // 132 4 1 - case 28: stack.push(arg4); // 21 4 - case 30: stack.push(arg3); // 29 - case 31: if (stack.pop() <= stack.pop()) { gt = 49; continue; } // 162 0 18 - case 34: stack.push(arg5); // 25 5 - case 36: stack.push(arg6); // 21 6 - case 38: stack.push(arg4); // 21 4 - case 40: stack.push(stack.pop() + stack.pop()); // 96 - case 41: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 42: stack.push(arg1); // 27 - case 43: if (stack.pop() != stack.pop()) { gt = 25; continue; } // 160 255 238 - case 46: gt = 49; continue; // 167 0 3 - case 49: stack.push(arg4); // 21 4 - case 51: stack.push(arg3); // 29 - case 52: if (stack.pop() <= stack.pop()) { gt = 140; continue; } // 162 0 88 - case 55: stack.push(arg3); // 29 - case 56: stack.push(new Array(stack.pop())); // 188 5 - case 58: arg7 = stack.pop() // 58 7 - case 60: stack.push(0); // 3 - case 61: arg8 = stack.pop() // 54 8 - case 63: stack.push(arg8); // 21 8 - case 65: stack.push(arg4); // 21 4 - case 67: if (stack.pop() <= stack.pop()) { gt = 89; continue; } // 162 0 22 - case 70: stack.push(arg7); // 25 7 - case 72: stack.push(arg8); // 21 8 - case 74: stack.push(arg5); // 25 5 - case 76: stack.push(arg6); // 21 6 - case 78: stack.push(arg8); // 21 8 - case 80: stack.push(stack.pop() + stack.pop()); // 96 - case 81: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 82: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 83: arg8++; // 132 8 1 - case 86: gt = 63; continue; // 167 255 233 - case 89: stack.push(arg4); // 21 4 - case 91: stack.push(arg3); // 29 - case 92: if (stack.pop() <= stack.pop()) { gt = 128; continue; } // 162 0 36 - case 95: stack.push(arg5); // 25 5 - case 97: stack.push(arg6); // 21 6 - case 99: stack.push(arg4); // 21 4 - case 101: stack.push(stack.pop() + stack.pop()); // 96 - case 102: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 103: arg8 = stack.pop() // 54 8 - case 105: stack.push(arg7); // 25 7 - case 107: stack.push(arg4); // 21 4 - case 109: stack.push(arg8); // 21 8 - case 111: stack.push(arg1); // 27 - case 112: if (stack.pop() != stack.pop()) { gt = 119; continue; } // 160 0 7 - case 115: stack.push(arg2); // 28 - case 116: gt = 121; continue; // 167 0 5 - case 119: stack.push(arg8); // 21 8 - case 121: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 122: arg4++; // 132 4 1 - case 125: gt = 89; continue; // 167 255 220 - case 128: stack.push(new java_lang_String); // 187 0 200 - case 131: stack.push(stack[stack.length - 1]); // 89 - case 132: stack.push(0); // 3 - case 133: stack.push(arg3); // 29 - case 134: stack.push(arg7); // 25 7 - case 136: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 139: return stack.pop(); // 176 - case 140: stack.push(arg0); // 42 - case 141: return stack.pop(); // 176 - } -} -function java_lang_String_matchesZLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: stack.push(arg0); // 42 - case 2: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_regex_Pattern_matchesZLjava_lang_StringLjava_lang_CharSequence(v0, v1)); } // 184 1 183 - case 5: return stack.pop(); // 172 - } -} -function java_lang_String_containsZLjava_lang_CharSequence(arg0,arg1) { - var arg2; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132 - case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.indexOfILjava_lang_String(self, v0)); } // 182 1 149 - case 8: // 2 - case 9: if (stack.pop() >= stack.pop()) { gt = 16; continue; } // 164 0 7 - case 12: stack.push(1); // 4 - case 13: gt = 17; continue; // 167 0 4 - case 16: stack.push(0); // 3 - case 17: return stack.pop(); // 172 - } -} -function java_lang_String_replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186 - case 4: stack.push(arg0); // 42 - case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185 - case 8: stack.push(arg2); // 44 - case 9: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceFirstLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 182 - case 12: return stack.pop(); // 176 - } -} -function java_lang_String_replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186 - case 4: stack.push(arg0); // 42 - case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185 - case 8: stack.push(arg2); // 44 - case 9: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceAllLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 181 - case 12: return stack.pop(); // 176 - } -} -function java_lang_String_replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132 - case 4: stack.push(16); // 16 16 - case 6: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_StringI(v0, v1)); } // 184 1 187 - case 9: stack.push(arg0); // 42 - case 10: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.matcherLjava_util_regex_MatcherLjava_lang_CharSequence(self, v0)); } // 182 1 185 - case 13: stack.push(arg2); // 44 - case 14: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132 - case 17: { var v0 = stack.pop(); stack.push(java_util_regex_Matcher_quoteReplacementLjava_lang_StringLjava_lang_String(v0)); } // 184 1 180 - case 20: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.replaceAllLjava_lang_StringLjava_lang_String(self, v0)); } // 182 1 181 - case 23: return stack.pop(); // 176 - } -} -function java_lang_String_splitALjava_lang_StringLjava_lang_StringI(arg0,arg1,arg2) { - var arg3; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: { var v0 = stack.pop(); stack.push(java_util_regex_Pattern_compileLjava_util_regex_PatternLjava_lang_String(v0)); } // 184 1 186 - case 4: stack.push(arg0); // 42 - case 5: stack.push(arg2); // 28 - case 6: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.splitALjava_lang_StringLjava_lang_CharSequenceI(self, v0, v1)); } // 182 1 184 - case 9: return stack.pop(); // 176 - } -} -function java_lang_String_splitALjava_lang_StringLjava_lang_String(arg0,arg1) { - var arg2; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: stack.push(0); // 3 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.splitALjava_lang_StringLjava_lang_StringI(self, v0, v1)); } // 182 1 157 - case 6: return stack.pop(); // 176 - } -} -function java_lang_String_toLowerCaseLjava_lang_StringLjava_util_Locale(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; - var arg14; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11 - case 4: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128 - case 11: // 191 - case 12: stack.push(0); // 3 - case 13: arg2 = stack.pop(); // 61 - case 14: stack.push(arg2); // 28 - case 15: stack.push(arg0); // 42 - case 16: stack.push(stack.pop().count); // 180 1 97 - case 19: if (stack.pop() <= stack.pop()) { gt = 94; continue; } // 162 0 75 - case 22: stack.push(arg0); // 42 - case 23: stack.push(stack.pop().value); // 180 1 100 - case 26: stack.push(arg0); // 42 - case 27: stack.push(stack.pop().offset); // 180 1 99 - case 30: stack.push(arg2); // 28 - case 31: stack.push(stack.pop() + stack.pop()); // 96 - case 32: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 33: arg3 = stack.pop(); // 62 - case 34: stack.push(arg3); // 29 - case 35: stack.push(55296); // 18 1 - case 37: if (stack.pop() > stack.pop()) { gt = 77; continue; } // 161 0 40 - case 40: stack.push(arg3); // 29 - case 41: stack.push(56319); // 18 2 - case 43: if (stack.pop() < stack.pop()) { gt = 77; continue; } // 163 0 34 - case 46: stack.push(arg0); // 42 - case 47: stack.push(arg2); // 28 - case 48: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134 - case 51: arg4 = stack.pop() // 54 4 - case 53: stack.push(arg4); // 21 4 - case 55: stack.push(arg4); // 21 4 - case 57: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseII(v0)); } // 184 1 107 - case 60: if (stack.pop() == stack.pop()) { gt = 66; continue; } // 159 0 6 - case 63: gt = 96; continue; // 167 0 33 - case 66: stack.push(arg2); // 28 - case 67: stack.push(arg4); // 21 4 - case 69: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106 - case 72: stack.push(stack.pop() + stack.pop()); // 96 - case 73: arg2 = stack.pop(); // 61 - case 74: gt = 91; continue; // 167 0 17 - case 77: stack.push(arg3); // 29 - case 78: stack.push(arg3); // 29 - case 79: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseCC(v0)); } // 184 1 104 - case 82: if (stack.pop() == stack.pop()) { gt = 88; continue; } // 159 0 6 - case 85: gt = 96; continue; // 167 0 11 - case 88: arg2++; // 132 2 1 - case 91: gt = 14; continue; // 167 255 179 - case 94: stack.push(arg0); // 42 - case 95: return stack.pop(); // 176 - case 96: stack.push(arg0); // 42 - case 97: stack.push(stack.pop().count); // 180 1 97 - case 100: stack.push(new Array(stack.pop())); // 188 5 - case 102: arg3 = stack.pop(); // 78 - case 103: stack.push(0); // 3 - case 104: arg4 = stack.pop() // 54 4 - case 106: stack.push(arg0); // 42 - case 107: stack.push(stack.pop().value); // 180 1 100 - case 110: stack.push(arg0); // 42 - case 111: stack.push(stack.pop().offset); // 180 1 99 - case 114: stack.push(arg3); // 45 - case 115: stack.push(0); // 3 - case 116: stack.push(arg2); // 28 - case 117: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171 - case 120: stack.push(arg1); // 43 - case 121: { var self = stack.pop(); stack.push(self.getLanguageLjava_lang_String(self)); } // 182 1 178 - case 124: arg5 = stack.pop() // 58 5 - case 126: stack.push(arg5); // 25 5 - case 128: stack.push("tr"); // 18 11 - case 130: // 165 - case 131: // 0 - case 132: stack.push(6405); // 17 25 5 - case 135: stack.push("az"); // 18 5 - case 137: // 165 - case 138: // 0 - case 139: stack.push(1); // 10 - case 140: stack.push(arg5); // 25 5 - case 142: stack.push("lt"); // 18 9 - case 144: // 166 - case 145: // 0 - case 146: stack.push(4); // 7 - case 147: stack.push(1); // 4 - case 148: gt = 152; continue; // 167 0 4 - case 151: stack.push(0); // 3 - case 152: arg6 = stack.pop() // 54 6 - case 154: stack.push(arg2); // 28 - case 155: arg11 = stack.pop() // 54 11 - case 157: stack.push(arg11); // 21 11 - case 159: stack.push(arg0); // 42 - case 160: stack.push(stack.pop().count); // 180 1 97 - case 163: if (stack.pop() <= stack.pop()) { gt = 419; continue; } // 162 1 0 - case 166: stack.push(arg0); // 42 - case 167: stack.push(stack.pop().value); // 180 1 100 - case 170: stack.push(arg0); // 42 - case 171: stack.push(stack.pop().offset); // 180 1 99 - case 174: stack.push(arg11); // 21 11 - case 176: stack.push(stack.pop() + stack.pop()); // 96 - case 177: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 178: arg9 = stack.pop() // 54 9 - case 180: stack.push(arg9); // 21 9 - case 182: // number conversion // 146 - case 183: stack.push(55296); // 18 1 - case 185: if (stack.pop() > stack.pop()) { gt = 214; continue; } // 161 0 29 - case 188: stack.push(arg9); // 21 9 - case 190: // number conversion // 146 - case 191: stack.push(56319); // 18 2 - case 193: if (stack.pop() < stack.pop()) { gt = 214; continue; } // 163 0 21 - case 196: stack.push(arg0); // 42 - case 197: stack.push(arg11); // 21 11 - case 199: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134 - case 202: arg9 = stack.pop() // 54 9 - case 204: stack.push(arg9); // 21 9 - case 206: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106 - case 209: arg10 = stack.pop() // 54 10 - case 211: gt = 217; continue; // 167 0 6 - case 214: stack.push(1); // 4 - case 215: arg10 = stack.pop() // 54 10 - case 217: stack.push(arg6); // 21 6 - case 219: if (stack.pop() != 0) { gt = 230; continue; } // 154 0 11 - case 222: stack.push(arg9); // 21 9 - case 224: stack.push(931); // 17 3 163 - case 227: if (stack.pop() != stack.pop()) { gt = 242; continue; } // 160 0 15 - case 230: stack.push(arg0); // 42 - case 231: stack.push(arg11); // 21 11 - case 233: stack.push(arg1); // 43 - case 234: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toLowerCaseExILjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 117 - case 237: arg8 = stack.pop() // 54 8 - case 239: gt = 249; continue; // 167 0 10 - case 242: stack.push(arg9); // 21 9 - case 244: { var v0 = stack.pop(); stack.push(java_lang_Character_toLowerCaseII(v0)); } // 184 1 107 - case 247: arg8 = stack.pop() // 54 8 - case 249: stack.push(arg8); // 21 8 - case 251: // 2 - case 252: if (stack.pop() == stack.pop()) { gt = 262; continue; } // 159 0 10 - case 255: stack.push(arg8); // 21 8 - case 257: stack.push(65536); // 18 3 - case 259: if (stack.pop() > stack.pop()) { gt = 399; continue; } // 161 0 140 - case 262: stack.push(arg8); // 21 8 - case 264: // 2 - case 265: if (stack.pop() != stack.pop()) { gt = 280; continue; } // 160 0 15 - case 268: stack.push(arg0); // 42 - case 269: stack.push(arg11); // 21 11 - case 271: stack.push(arg1); // 43 - case 272: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toLowerCaseCharArrayACLjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 119 - case 275: arg7 = stack.pop() // 58 7 - case 277: gt = 315; continue; // 167 0 38 - case 280: stack.push(arg10); // 21 10 - case 282: stack.push(2); // 5 - case 283: if (stack.pop() != stack.pop()) { gt = 308; continue; } // 160 0 25 - case 286: stack.push(arg4); // 21 4 - case 288: stack.push(arg8); // 21 8 - case 290: stack.push(arg3); // 45 - case 291: stack.push(arg11); // 21 11 - case 293: stack.push(arg4); // 21 4 - case 295: stack.push(stack.pop() + stack.pop()); // 96 - case 296: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_toCharsAIIACAI(v0, v1, v2)); } // 184 1 111 - case 299: stack.push(arg10); // 21 10 - case 301: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 302: stack.push(stack.pop() + stack.pop()); // 96 - case 303: arg4 = stack.pop() // 54 4 - case 305: gt = 409; continue; // 167 0 104 - case 308: stack.push(arg8); // 21 8 - case 310: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109 - case 313: arg7 = stack.pop() // 58 7 - case 315: stack.push(arg7); // 25 7 - case 317: stack.push(stack.pop().length); // 190 - case 318: arg12 = stack.pop() // 54 12 - case 320: stack.push(arg12); // 21 12 - case 322: stack.push(arg10); // 21 10 - case 324: if (stack.pop() >= stack.pop()) { gt = 355; continue; } // 164 0 31 - case 327: stack.push(arg3); // 45 - case 328: stack.push(stack.pop().length); // 190 - case 329: stack.push(arg12); // 21 12 - case 331: stack.push(stack.pop() + stack.pop()); // 96 - case 332: stack.push(arg10); // 21 10 - case 334: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 335: stack.push(new Array(stack.pop())); // 188 5 - case 337: arg13 = stack.pop() // 58 13 - case 339: stack.push(arg3); // 45 - case 340: stack.push(0); // 3 - case 341: stack.push(arg13); // 25 13 - case 343: stack.push(0); // 3 - case 344: stack.push(arg11); // 21 11 - case 346: stack.push(arg4); // 21 4 - case 348: stack.push(stack.pop() + stack.pop()); // 96 - case 349: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171 - case 352: stack.push(arg13); // 25 13 - case 354: arg3 = stack.pop(); // 78 - case 355: stack.push(0); // 3 - case 356: arg13 = stack.pop() // 54 13 - case 358: stack.push(arg13); // 21 13 - case 360: stack.push(arg12); // 21 12 - case 362: if (stack.pop() <= stack.pop()) { gt = 386; continue; } // 162 0 24 - case 365: stack.push(arg3); // 45 - case 366: stack.push(arg11); // 21 11 - case 368: stack.push(arg4); // 21 4 - case 370: stack.push(stack.pop() + stack.pop()); // 96 - case 371: stack.push(arg13); // 21 13 - case 373: stack.push(stack.pop() + stack.pop()); // 96 - case 374: stack.push(arg7); // 25 7 - case 376: stack.push(arg13); // 21 13 - case 378: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 379: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 380: arg13++; // 132 13 1 - case 383: gt = 358; continue; // 167 255 231 - case 386: stack.push(arg4); // 21 4 - case 388: stack.push(arg12); // 21 12 - case 390: stack.push(arg10); // 21 10 - case 392: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 393: stack.push(stack.pop() + stack.pop()); // 96 - case 394: arg4 = stack.pop() // 54 4 - case 396: gt = 409; continue; // 167 0 13 - case 399: stack.push(arg3); // 45 - case 400: stack.push(arg11); // 21 11 - case 402: stack.push(arg4); // 21 4 - case 404: stack.push(stack.pop() + stack.pop()); // 96 - case 405: stack.push(arg8); // 21 8 - case 407: // number conversion // 146 - case 408: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 409: stack.push(arg11); // 21 11 - case 411: stack.push(arg10); // 21 10 - case 413: stack.push(stack.pop() + stack.pop()); // 96 - case 414: arg11 = stack.pop() // 54 11 - case 416: gt = 157; continue; // 167 254 253 - case 419: stack.push(new java_lang_String); // 187 0 200 - case 422: stack.push(stack[stack.length - 1]); // 89 - case 423: stack.push(0); // 3 - case 424: stack.push(arg0); // 42 - case 425: stack.push(stack.pop().count); // 180 1 97 - case 428: stack.push(arg4); // 21 4 - case 430: stack.push(stack.pop() + stack.pop()); // 96 - case 431: stack.push(arg3); // 45 - case 432: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 435: return stack.pop(); // 176 - } -} -function java_lang_String_toLowerCaseLjava_lang_String(arg0) { - var arg1; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { stack.push(java_util_Locale_getDefaultLjava_util_Locale()); } // 184 1 179 - case 4: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.toLowerCaseLjava_lang_StringLjava_util_Locale(self, v0)); } // 182 1 158 - case 7: return stack.pop(); // 176 - } -} -function java_lang_String_toUpperCaseLjava_lang_StringLjava_util_Locale(arg0,arg1) { - var arg2; - var arg3; - var arg4; - var arg5; - var arg6; - var arg7; - var arg8; - var arg9; - var arg10; - var arg11; - var arg12; - var arg13; - var arg14; -; - var stack = new Array(6); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg1); // 43 - case 1: if (stack.pop()) { gt = 12; continue; } // 199 0 11 - case 4: stack.push(new java_lang_NullPointerException); // 187 0 198 - case 7: stack.push(stack[stack.length - 1]); // 89 - case 8: { java_lang_NullPointerException_consV(stack.pop()); } // 183 1 128 - case 11: // 191 - case 12: stack.push(0); // 3 - case 13: arg2 = stack.pop(); // 61 - case 14: stack.push(arg2); // 28 - case 15: stack.push(arg0); // 42 - case 16: stack.push(stack.pop().count); // 180 1 97 - case 19: if (stack.pop() <= stack.pop()) { gt = 93; continue; } // 162 0 74 - case 22: stack.push(arg0); // 42 - case 23: stack.push(stack.pop().value); // 180 1 100 - case 26: stack.push(arg0); // 42 - case 27: stack.push(stack.pop().offset); // 180 1 99 - case 30: stack.push(arg2); // 28 - case 31: stack.push(stack.pop() + stack.pop()); // 96 - case 32: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 33: arg3 = stack.pop(); // 62 - case 34: stack.push(arg3); // 29 - case 35: stack.push(55296); // 18 1 - case 37: if (stack.pop() > stack.pop()) { gt = 61; continue; } // 161 0 24 - case 40: stack.push(arg3); // 29 - case 41: stack.push(56319); // 18 2 - case 43: if (stack.pop() < stack.pop()) { gt = 61; continue; } // 163 0 18 - case 46: stack.push(arg0); // 42 - case 47: stack.push(arg2); // 28 - case 48: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134 - case 51: arg3 = stack.pop(); // 62 - case 52: stack.push(arg3); // 29 - case 53: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106 - case 56: arg4 = stack.pop() // 54 4 - case 58: gt = 64; continue; // 167 0 6 - case 61: stack.push(1); // 4 - case 62: arg4 = stack.pop() // 54 4 - case 64: stack.push(arg3); // 29 - case 65: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseExII(v0)); } // 184 1 108 - case 68: arg5 = stack.pop() // 54 5 - case 70: stack.push(arg5); // 21 5 - case 72: // 2 - case 73: if (stack.pop() == stack.pop()) { gt = 95; continue; } // 159 0 22 - case 76: stack.push(arg3); // 29 - case 77: stack.push(arg5); // 21 5 - case 79: if (stack.pop() == stack.pop()) { gt = 85; continue; } // 159 0 6 - case 82: gt = 95; continue; // 167 0 13 - case 85: stack.push(arg2); // 28 - case 86: stack.push(arg4); // 21 4 - case 88: stack.push(stack.pop() + stack.pop()); // 96 - case 89: arg2 = stack.pop(); // 61 - case 90: gt = 14; continue; // 167 255 180 - case 93: stack.push(arg0); // 42 - case 94: return stack.pop(); // 176 - case 95: stack.push(arg0); // 42 - case 96: stack.push(stack.pop().count); // 180 1 97 - case 99: stack.push(new Array(stack.pop())); // 188 5 - case 101: arg3 = stack.pop(); // 78 - case 102: stack.push(0); // 3 - case 103: arg4 = stack.pop() // 54 4 - case 105: stack.push(arg0); // 42 - case 106: stack.push(stack.pop().value); // 180 1 100 - case 109: stack.push(arg0); // 42 - case 110: stack.push(stack.pop().offset); // 180 1 99 - case 113: stack.push(arg3); // 45 - case 114: stack.push(0); // 3 - case 115: stack.push(arg2); // 28 - case 116: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171 - case 119: stack.push(arg1); // 43 - case 120: { var self = stack.pop(); stack.push(self.getLanguageLjava_lang_String(self)); } // 182 1 178 - case 123: arg5 = stack.pop() // 58 5 - case 125: stack.push(arg5); // 25 5 - case 127: stack.push("tr"); // 18 11 - case 129: // 165 - case 130: // 0 - case 131: stack.push(6405); // 17 25 5 - case 134: stack.push("az"); // 18 5 - case 136: // 165 - case 137: // 0 - case 138: stack.push(1); // 10 - case 139: stack.push(arg5); // 25 5 - case 141: stack.push("lt"); // 18 9 - case 143: // 166 - case 144: // 0 - case 145: stack.push(4); // 7 - case 146: stack.push(1); // 4 - case 147: gt = 151; continue; // 167 0 4 - case 150: stack.push(0); // 3 - case 151: arg6 = stack.pop() // 54 6 - case 153: stack.push(arg2); // 28 - case 154: arg11 = stack.pop() // 54 11 - case 156: stack.push(arg11); // 21 11 - case 158: stack.push(arg0); // 42 - case 159: stack.push(stack.pop().count); // 180 1 97 - case 162: if (stack.pop() <= stack.pop()) { gt = 425; continue; } // 162 1 7 - case 165: stack.push(arg0); // 42 - case 166: stack.push(stack.pop().value); // 180 1 100 - case 169: stack.push(arg0); // 42 - case 170: stack.push(stack.pop().offset); // 180 1 99 - case 173: stack.push(arg11); // 21 11 - case 175: stack.push(stack.pop() + stack.pop()); // 96 - case 176: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 177: arg9 = stack.pop() // 54 9 - case 179: stack.push(arg9); // 21 9 - case 181: // number conversion // 146 - case 182: stack.push(55296); // 18 1 - case 184: if (stack.pop() > stack.pop()) { gt = 213; continue; } // 161 0 29 - case 187: stack.push(arg9); // 21 9 - case 189: // number conversion // 146 - case 190: stack.push(56319); // 18 2 - case 192: if (stack.pop() < stack.pop()) { gt = 213; continue; } // 163 0 21 - case 195: stack.push(arg0); // 42 - case 196: stack.push(arg11); // 21 11 - case 198: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.codePointAtII(self, v0)); } // 182 1 134 - case 201: arg9 = stack.pop() // 54 9 - case 203: stack.push(arg9); // 21 9 - case 205: { var v0 = stack.pop(); stack.push(java_lang_Character_charCountII(v0)); } // 184 1 106 - case 208: arg10 = stack.pop() // 54 10 - case 210: gt = 216; continue; // 167 0 6 - case 213: stack.push(1); // 4 - case 214: arg10 = stack.pop() // 54 10 - case 216: stack.push(arg6); // 21 6 - case 218: if (stack.pop() == 0) { gt = 233; continue; } // 153 0 15 - case 221: stack.push(arg0); // 42 - case 222: stack.push(arg11); // 21 11 - case 224: stack.push(arg1); // 43 - case 225: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toUpperCaseExILjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 118 - case 228: arg8 = stack.pop() // 54 8 - case 230: gt = 240; continue; // 167 0 10 - case 233: stack.push(arg9); // 21 9 - case 235: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseExII(v0)); } // 184 1 108 - case 238: arg8 = stack.pop() // 54 8 - case 240: stack.push(arg8); // 21 8 - case 242: // 2 - case 243: if (stack.pop() == stack.pop()) { gt = 253; continue; } // 159 0 10 - case 246: stack.push(arg8); // 21 8 - case 248: stack.push(65536); // 18 3 - case 250: if (stack.pop() > stack.pop()) { gt = 405; continue; } // 161 0 155 - case 253: stack.push(arg8); // 21 8 - case 255: // 2 - case 256: if (stack.pop() != stack.pop()) { gt = 286; continue; } // 160 0 30 - case 259: stack.push(arg6); // 21 6 - case 261: if (stack.pop() == 0) { gt = 276; continue; } // 153 0 15 - case 264: stack.push(arg0); // 42 - case 265: stack.push(arg11); // 21 11 - case 267: stack.push(arg1); // 43 - case 268: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_ConditionalSpecialCasing_toUpperCaseCharArrayACLjava_lang_StringILjava_util_Locale(v0, v1, v2)); } // 184 1 120 - case 271: arg7 = stack.pop() // 58 7 - case 273: gt = 321; continue; // 167 0 48 - case 276: stack.push(arg9); // 21 9 - case 278: { var v0 = stack.pop(); stack.push(java_lang_Character_toUpperCaseCharArrayACI(v0)); } // 184 1 110 - case 281: arg7 = stack.pop() // 58 7 - case 283: gt = 321; continue; // 167 0 38 - case 286: stack.push(arg10); // 21 10 - case 288: stack.push(2); // 5 - case 289: if (stack.pop() != stack.pop()) { gt = 314; continue; } // 160 0 25 - case 292: stack.push(arg4); // 21 4 - case 294: stack.push(arg8); // 21 8 - case 296: stack.push(arg3); // 45 - case 297: stack.push(arg11); // 21 11 - case 299: stack.push(arg4); // 21 4 - case 301: stack.push(stack.pop() + stack.pop()); // 96 - case 302: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Character_toCharsAIIACAI(v0, v1, v2)); } // 184 1 111 - case 305: stack.push(arg10); // 21 10 - case 307: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 308: stack.push(stack.pop() + stack.pop()); // 96 - case 309: arg4 = stack.pop() // 54 4 - case 311: gt = 415; continue; // 167 0 104 - case 314: stack.push(arg8); // 21 8 - case 316: { var v0 = stack.pop(); stack.push(java_lang_Character_toCharsACI(v0)); } // 184 1 109 - case 319: arg7 = stack.pop() // 58 7 - case 321: stack.push(arg7); // 25 7 - case 323: stack.push(stack.pop().length); // 190 - case 324: arg12 = stack.pop() // 54 12 - case 326: stack.push(arg12); // 21 12 - case 328: stack.push(arg10); // 21 10 - case 330: if (stack.pop() >= stack.pop()) { gt = 361; continue; } // 164 0 31 - case 333: stack.push(arg3); // 45 - case 334: stack.push(stack.pop().length); // 190 - case 335: stack.push(arg12); // 21 12 - case 337: stack.push(stack.pop() + stack.pop()); // 96 - case 338: stack.push(arg10); // 21 10 - case 340: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 341: stack.push(new Array(stack.pop())); // 188 5 - case 343: arg13 = stack.pop() // 58 13 - case 345: stack.push(arg3); // 45 - case 346: stack.push(0); // 3 - case 347: stack.push(arg13); // 25 13 - case 349: stack.push(0); // 3 - case 350: stack.push(arg11); // 21 11 - case 352: stack.push(arg4); // 21 4 - case 354: stack.push(stack.pop() + stack.pop()); // 96 - case 355: { var v4 = stack.pop(); var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_System_arraycopyVLjava_lang_ObjectILjava_lang_ObjectII(v0, v1, v2, v3, v4); } // 184 1 171 - case 358: stack.push(arg13); // 25 13 - case 360: arg3 = stack.pop(); // 78 - case 361: stack.push(0); // 3 - case 362: arg13 = stack.pop() // 54 13 - case 364: stack.push(arg13); // 21 13 - case 366: stack.push(arg12); // 21 12 - case 368: if (stack.pop() <= stack.pop()) { gt = 392; continue; } // 162 0 24 - case 371: stack.push(arg3); // 45 - case 372: stack.push(arg11); // 21 11 - case 374: stack.push(arg4); // 21 4 - case 376: stack.push(stack.pop() + stack.pop()); // 96 - case 377: stack.push(arg13); // 21 13 - case 379: stack.push(stack.pop() + stack.pop()); // 96 - case 380: stack.push(arg7); // 25 7 - case 382: stack.push(arg13); // 21 13 - case 384: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 385: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 386: arg13++; // 132 13 1 - case 389: gt = 364; continue; // 167 255 231 - case 392: stack.push(arg4); // 21 4 - case 394: stack.push(arg12); // 21 12 - case 396: stack.push(arg10); // 21 10 - case 398: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 399: stack.push(stack.pop() + stack.pop()); // 96 - case 400: arg4 = stack.pop() // 54 4 - case 402: gt = 415; continue; // 167 0 13 - case 405: stack.push(arg3); // 45 - case 406: stack.push(arg11); // 21 11 - case 408: stack.push(arg4); // 21 4 - case 410: stack.push(stack.pop() + stack.pop()); // 96 - case 411: stack.push(arg8); // 21 8 - case 413: // number conversion // 146 - case 414: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 415: stack.push(arg11); // 21 11 - case 417: stack.push(arg10); // 21 10 - case 419: stack.push(stack.pop() + stack.pop()); // 96 - case 420: arg11 = stack.pop() // 54 11 - case 422: gt = 156; continue; // 167 254 246 - case 425: stack.push(new java_lang_String); // 187 0 200 - case 428: stack.push(stack[stack.length - 1]); // 89 - case 429: stack.push(0); // 3 - case 430: stack.push(arg0); // 42 - case 431: stack.push(stack.pop().count); // 180 1 97 - case 434: stack.push(arg4); // 21 4 - case 436: stack.push(stack.pop() + stack.pop()); // 96 - case 437: stack.push(arg3); // 45 - case 438: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 441: return stack.pop(); // 176 - } -} -function java_lang_String_toUpperCaseLjava_lang_String(arg0) { - var arg1; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: { stack.push(java_util_Locale_getDefaultLjava_util_Locale()); } // 184 1 179 - case 4: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.toUpperCaseLjava_lang_StringLjava_util_Locale(self, v0)); } // 182 1 159 - case 7: return stack.pop(); // 176 - } -} -function java_lang_String_trimLjava_lang_String(arg0) { - var arg1; - var arg2; - var arg3; - var arg4; - var arg5; -; - var stack = new Array(3); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().count); // 180 1 97 - case 4: arg1 = stack.pop(); // 60 - case 5: stack.push(0); // 3 - case 6: arg2 = stack.pop(); // 61 - case 7: stack.push(arg0); // 42 - case 8: stack.push(stack.pop().offset); // 180 1 99 - case 11: arg3 = stack.pop(); // 62 - case 12: stack.push(arg0); // 42 - case 13: stack.push(stack.pop().value); // 180 1 100 - case 16: arg4 = stack.pop() // 58 4 - case 18: stack.push(arg2); // 28 - case 19: stack.push(arg1); // 27 - case 20: if (stack.pop() <= stack.pop()) { gt = 40; continue; } // 162 0 20 - case 23: stack.push(arg4); // 25 4 - case 25: stack.push(arg3); // 29 - case 26: stack.push(arg2); // 28 - case 27: stack.push(stack.pop() + stack.pop()); // 96 - case 28: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 29: stack.push(32); // 16 32 - case 31: if (stack.pop() < stack.pop()) { gt = 40; continue; } // 163 0 9 - case 34: arg2++; // 132 2 1 - case 37: gt = 18; continue; // 167 255 237 - case 40: stack.push(arg2); // 28 - case 41: stack.push(arg1); // 27 - case 42: if (stack.pop() <= stack.pop()) { gt = 64; continue; } // 162 0 22 - case 45: stack.push(arg4); // 25 4 - case 47: stack.push(arg3); // 29 - case 48: stack.push(arg1); // 27 - case 49: stack.push(stack.pop() + stack.pop()); // 96 - case 50: stack.push(1); // 4 - case 51: { var tmp = stack.pop(); stack.push(stack.pop() - tmp); } // 100 - case 52: { var indx = stack.pop(); stack.push(stack.pop()[indx]); } // 52 - case 53: stack.push(32); // 16 32 - case 55: if (stack.pop() < stack.pop()) { gt = 64; continue; } // 163 0 9 - case 58: arg1 += 255; // 132 1 255 - case 61: gt = 40; continue; // 167 255 235 - case 64: stack.push(arg2); // 28 - case 65: if (stack.pop() > 0) { gt = 76; continue; } // 157 0 11 - case 68: stack.push(arg1); // 27 - case 69: stack.push(arg0); // 42 - case 70: stack.push(stack.pop().count); // 180 1 97 - case 73: if (stack.pop() <= stack.pop()) { gt = 85; continue; } // 162 0 12 - case 76: stack.push(arg0); // 42 - case 77: stack.push(arg2); // 28 - case 78: stack.push(arg1); // 27 - case 79: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.substringLjava_lang_StringII(self, v0, v1)); } // 182 1 147 - case 82: gt = 86; continue; // 167 0 4 - case 85: stack.push(arg0); // 42 - case 86: return stack.pop(); // 176 - } -} -*/ -function java_lang_String_toStringLjava_lang_String(arg0) { - return arg0.toString(); -} -/* -function java_lang_String_toCharArrayAC(arg0) { - var arg1; - var arg2; -; - var stack = new Array(5); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(stack.pop().count); // 180 1 97 - case 4: stack.push(new Array(stack.pop())); // 188 5 - case 6: arg1 = stack.pop(); // 76 - case 7: stack.push(arg0); // 42 - case 8: stack.push(0); // 3 - case 9: stack.push(arg0); // 42 - case 10: stack.push(stack.pop().count); // 180 1 97 - case 13: stack.push(arg1); // 43 - case 14: stack.push(0); // 3 - case 15: { var v3 = stack.pop(); var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); self.getCharsVIIACAI(self, v0, v1, v2, v3); } // 182 1 138 - case 18: stack.push(arg1); // 43 - case 19: return stack.pop(); // 176 - } -} -function java_lang_String_formatLjava_lang_StringLjava_lang_StringLjava_lang_Object(arg0,arg1) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_util_Formatter); // 187 0 211 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: { java_util_Formatter_consV(stack.pop()); } // 183 1 174 - case 7: stack.push(arg0); // 42 - case 8: stack.push(arg1); // 43 - case 9: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.formatALjava_util_FormatterLjava_lang_StringALjava_lang_Object(self, v0, v1)); } // 182 1 177 - case 12: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 175 - case 15: return stack.pop(); // 176 - } -} -function java_lang_String_formatLjava_lang_StringLjava_util_LocaleLjava_lang_StringLjava_lang_Object(arg0,arg1,arg2) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_util_Formatter); // 187 0 211 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(arg0); // 42 - case 5: { var v0 = stack.pop(); java_util_Formatter_consVLjava_util_Locale(stack.pop(), v0); } // 183 1 176 - case 8: stack.push(arg1); // 43 - case 9: stack.push(arg2); // 44 - case 10: { var v1 = stack.pop(); var v0 = stack.pop(); var self = stack.pop(); stack.push(self.formatALjava_util_FormatterLjava_lang_StringALjava_lang_Object(self, v0, v1)); } // 182 1 177 - case 13: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 175 - case 16: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringLjava_lang_Object(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: if (stack.pop()) { gt = 9; continue; } // 199 0 8 - case 4: stack.push("null"); // 18 10 - case 6: gt = 13; continue; // 167 0 7 - case 9: stack.push(arg0); // 42 - case 10: { var self = stack.pop(); stack.push(self.toStringLjava_lang_String(self)); } // 182 1 132 - case 13: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringAC(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_lang_String); // 187 0 200 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(arg0); // 42 - case 5: { var v0 = stack.pop(); java_lang_String_consVAC(stack.pop(), v0); } // 183 1 142 - case 8: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringACII(arg0,arg1,arg2) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_lang_String); // 187 0 200 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(arg0); // 42 - case 5: stack.push(arg1); // 27 - case 6: stack.push(arg2); // 28 - case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVACAIAI(stack.pop(), v0, v1, v2); } // 183 1 143 - case 10: return stack.pop(); // 176 - } -} -function java_lang_String_copyValueOfLjava_lang_StringACII(arg0,arg1,arg2) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(new java_lang_String); // 187 0 200 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(arg0); // 42 - case 5: stack.push(arg1); // 27 - case 6: stack.push(arg2); // 28 - case 7: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVACAIAI(stack.pop(), v0, v1, v2); } // 183 1 143 - case 10: return stack.pop(); // 176 - } -} -function java_lang_String_copyValueOfLjava_lang_StringAC(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(0); // 3 - case 2: stack.push(arg0); // 42 - case 3: stack.push(stack.pop().length); // 190 - case 4: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_String_copyValueOfALjava_lang_StringACAIAI(v0, v1, v2)); } // 184 1 155 - case 7: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringZ(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 26 - case 1: if (stack.pop() == 0) { gt = 9; continue; } // 153 0 8 - case 4: stack.push("true"); // 18 12 - case 6: gt = 11; continue; // 167 0 5 - case 9: stack.push("false"); // 18 8 - case 11: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringC(arg0) { - var arg1; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(1); // 4 - case 1: stack.push(new Array(stack.pop())); // 188 5 - case 3: stack.push(stack[stack.length - 1]); // 89 - case 4: stack.push(0); // 3 - case 5: stack.push(arg0); // 26 - case 6: { var value = stack.pop(); var indx = stack.pop(); stack.pop()[indx] = value; } // 85 - case 7: arg1 = stack.pop(); // 76 - case 8: stack.push(new java_lang_String); // 187 0 200 - case 11: stack.push(stack[stack.length - 1]); // 89 - case 12: stack.push(0); // 3 - case 13: stack.push(1); // 4 - case 14: stack.push(arg1); // 43 - case 15: { var v2 = stack.pop(); var v1 = stack.pop(); var v0 = stack.pop(); java_lang_String_consVIIAC(stack.pop(), v0, v1, v2); } // 183 1 137 - case 18: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringI(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 26 - case 1: stack.push(10); // 16 10 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Integer_toStringLjava_lang_StringII(v0, v1)); } // 184 1 125 - case 6: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringJ(arg0) { - var arg1; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 30 - case 1: stack.push(10); // 16 10 - case 3: { var v1 = stack.pop(); var v0 = stack.pop(); stack.push(java_lang_Long_toStringLjava_lang_StringJI(v0, v1)); } // 184 1 126 - case 6: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringF(arg0) { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 34 - case 1: { var v0 = stack.pop(); stack.push(java_lang_Float_toStringLjava_lang_StringF(v0)); } // 184 1 122 - case 4: return stack.pop(); // 176 - } -} -function java_lang_String_valueOfLjava_lang_StringD(arg0) { - var arg1; - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 38 - case 1: { var v0 = stack.pop(); stack.push(java_lang_Double_toStringLjava_lang_StringD(v0)); } // 184 1 121 - case 4: return stack.pop(); // 176 - } -} -function java_lang_String_internLjava_lang_String(arg0) { - // no code found for null -} -function java_lang_String_compareToILjava_lang_Object(arg0,arg1) { - var arg2; -; - var stack = new Array(2); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(arg0); // 42 - case 1: stack.push(arg1); // 43 - case 2: if(stack[stack.length - 1].$instOf_java_lang_String != 1) throw {}; // 192 0 200 - case 5: { var v0 = stack.pop(); var self = stack.pop(); stack.push(self.compareToILjava_lang_String(self, v0)); } // 182 1 148 - case 8: return stack.pop(); // 172 - } -} -function java_lang_String_classV() { - var stack = new Array(); - var gt = 0; - for(;;) switch(gt) { - case 0: stack.push(0); // 3 - case 1: stack.push(new Array(stack.pop())); // 189 0 183 - case 4: java_lang_String_serialPersistentFields = stack.pop(); // 179 1 101 - case 7: stack.push(new java_lang_String$CaseInsensitiveComparator); // 187 0 202 - case 10: stack.push(stack[stack.length - 1]); // 89 - case 11: // 1 - case 12: { var v0 = stack.pop(); java_lang_String$CaseInsensitiveComparator_consVLjava_lang_String$1(stack.pop(), v0); } // 183 1 160 - case 15: java_lang_String_CASE_INSENSITIVE_ORDER = stack.pop(); // 179 1 102 - case 18: return; // 177 - } -} -*/ -var java_lang_String_serialVersionUID = 0; -var java_lang_String_serialPersistentFields = 0; -var java_lang_String_CASE_INSENSITIVE_ORDER = 0; -function java_lang_String() { - /** the real value of this 'string' we delegate to */ - this.r = ''; - - var self = this; - /* - this.value = 0; - this.offset = 0; - this.count = 0; - this.hash = 0; - */ - this.toString = function() { return self.r; }; -} -java_lang_String.prototype = new String; -//java_lang_String_classV(); - -/* new method for JavaScript String */ -String.prototype.charAtCI = java_lang_String_charAtCI; -String.prototype.lengthI = java_lang_String_lengthI; -String.prototype.isEmptyZ = java_lang_String_isEmptyZ; -String.prototype.getCharsVIIACAI = java_lang_String_getCharsVIIACAI; -String.prototype.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String; -String.prototype.$instOf_java_lang_String = true; -String.prototype.$instOf_java_io_Serializable = true; -String.prototype.$instOf_java_lang_Comparable = true; -String.prototype.$instOf_java_lang_CharSequence = true; - -/* - this.lengthI = java_lang_String_lengthI; - this.isEmptyZ = java_lang_String_isEmptyZ; - this.charAtCI = java_lang_String_charAtCI; - this.codePointAtII = java_lang_String_codePointAtII; - this.codePointBeforeII = java_lang_String_codePointBeforeII; - this.codePointCountIII = java_lang_String_codePointCountIII; - this.offsetByCodePointsIII = java_lang_String_offsetByCodePointsIII; - this.getCharsVACI = java_lang_String_getCharsVACI; - this.getCharsVIIACI = java_lang_String_getCharsVIIACI; - this.getBytesVIIABI = java_lang_String_getBytesVIIABI; - this.getBytesABLjava_lang_String = java_lang_String_getBytesABLjava_lang_String; - this.getBytesABLjava_nio_charset_Charset = java_lang_String_getBytesABLjava_nio_charset_Charset; - this.getBytesAB = java_lang_String_getBytesAB; - this.equalsZLjava_lang_Object = java_lang_String_equalsZLjava_lang_Object; - this.contentEqualsZLjava_lang_StringBuffer = java_lang_String_contentEqualsZLjava_lang_StringBuffer; - this.contentEqualsZLjava_lang_CharSequence = java_lang_String_contentEqualsZLjava_lang_CharSequence; - this.equalsIgnoreCaseZLjava_lang_String = java_lang_String_equalsIgnoreCaseZLjava_lang_String; - this.compareToILjava_lang_String = java_lang_String_compareToILjava_lang_String; - this.compareToIgnoreCaseILjava_lang_String = java_lang_String_compareToIgnoreCaseILjava_lang_String; - this.regionMatchesZILjava_lang_StringII = java_lang_String_regionMatchesZILjava_lang_StringII; - this.regionMatchesZZILjava_lang_StringII = java_lang_String_regionMatchesZZILjava_lang_StringII; - this.startsWithZLjava_lang_StringI = java_lang_String_startsWithZLjava_lang_StringI; - this.startsWithZLjava_lang_String = java_lang_String_startsWithZLjava_lang_String; - this.endsWithZLjava_lang_String = java_lang_String_endsWithZLjava_lang_String; - this.hashCodeI = java_lang_String_hashCodeI; - this.indexOfII = java_lang_String_indexOfII; - this.indexOfIII = java_lang_String_indexOfIII; - this.lastIndexOfII = java_lang_String_lastIndexOfII; - this.lastIndexOfIII = java_lang_String_lastIndexOfIII; - this.indexOfILjava_lang_String = java_lang_String_indexOfILjava_lang_String; - this.indexOfILjava_lang_StringI = java_lang_String_indexOfILjava_lang_StringI; - this.lastIndexOfILjava_lang_String = java_lang_String_lastIndexOfILjava_lang_String; - this.lastIndexOfILjava_lang_StringI = java_lang_String_lastIndexOfILjava_lang_StringI; - this.substringLjava_lang_StringI = java_lang_String_substringLjava_lang_StringI; - this.substringLjava_lang_StringII = java_lang_String_substringLjava_lang_StringII; - this.subSequenceLjava_lang_CharSequenceII = java_lang_String_subSequenceLjava_lang_CharSequenceII; - this.concatLjava_lang_StringLjava_lang_String = java_lang_String_concatLjava_lang_StringLjava_lang_String; - this.replaceLjava_lang_StringCC = java_lang_String_replaceLjava_lang_StringCC; - this.matchesZLjava_lang_String = java_lang_String_matchesZLjava_lang_String; - this.containsZLjava_lang_CharSequence = java_lang_String_containsZLjava_lang_CharSequence; - this.replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String = java_lang_String_replaceFirstLjava_lang_StringLjava_lang_StringLjava_lang_String; - this.replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String = java_lang_String_replaceAllLjava_lang_StringLjava_lang_StringLjava_lang_String; - this.replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence = java_lang_String_replaceLjava_lang_StringLjava_lang_CharSequenceLjava_lang_CharSequence; - this.splitALjava_lang_StringLjava_lang_StringI = java_lang_String_splitALjava_lang_StringLjava_lang_StringI; - this.splitALjava_lang_StringLjava_lang_String = java_lang_String_splitALjava_lang_StringLjava_lang_String; - this.toLowerCaseLjava_lang_StringLjava_util_Locale = java_lang_String_toLowerCaseLjava_lang_StringLjava_util_Locale; - this.toLowerCaseLjava_lang_String = java_lang_String_toLowerCaseLjava_lang_String; - this.toUpperCaseLjava_lang_StringLjava_util_Locale = java_lang_String_toUpperCaseLjava_lang_StringLjava_util_Locale; - this.toUpperCaseLjava_lang_String = java_lang_String_toUpperCaseLjava_lang_String; - this.trimLjava_lang_String = java_lang_String_trimLjava_lang_String; - this.toStringLjava_lang_String = java_lang_String_toStringLjava_lang_String; - this.toCharArrayAC = java_lang_String_toCharArrayAC; - this.internLjava_lang_String = java_lang_String_internLjava_lang_String; - this.compareToILjava_lang_Object = java_lang_String_compareToILjava_lang_Object; - */ - - - diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/Array.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Array.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,20 +1,20 @@ -/* -Java 4 Browser Bytecode Translator -Copyright (C) 2012-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. -*/ +/** + * 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; /** @@ -51,10 +51,24 @@ return doubles[4][0]; } + static double[][] dbls = new double[1][2]; + public static double twoDoubles() { + return dbls[0][0] + dbls[0][0]; + } + + static int[][] tints = new int[1][2]; + public static int twoInts() { + return tints[0][0] + tints[0][0]; + } + private static final Array[] ARR = { new Array(), new Array(), new Array() }; - private static Array[] arr() { - return ARR; + private static Array[][] arr() { + Array[][] matrix = new Array[3][3]; + for (int i = 0; i < ARR.length; i++) { + matrix[i][i] = ARR[i]; + } + return matrix; } private static T[] filter(T[] in) { return in; @@ -62,22 +76,52 @@ public static double sum() { double sum = 0.0; - for (int i = 0; i < arr().length; i++) { - sum += arr()[i].bytes(); - sum += arr()[i].shorts(); - sum += arr()[i].ints()[2]; - sum += arr()[i].floats(); - sum += filter(arr())[i].doubles(); + for (Array[] row : arr()) { + int indx = -1; + for (Array a : row) { + indx++; + if (a == null) { + continue; + } + sum += a.bytes(); + sum += a.shorts(); + sum += a.ints()[2]; + sum += a.floats(); + sum += filter(row)[indx].doubles(); + } } return sum; } - public static int simple() { - int[] arr = { 0, 1, 2, 3, 4, 5 }; + private static final int[] arr = { 0, 1, 2, 3, 4, 5 }; + public static int simple(boolean clone) { + int[] ar; + if (clone) { + ar = arr.clone(); + } else { + ar = arr; + } int sum = 0; - for (int i = 0; i < arr.length; i++) { - sum += arr[i]; + for (int a : ar) { + sum += a; } return sum; } + + public static int sum(int size) { + int[] arr = new int[size]; + return arr[0] + arr[1]; + } + + static void arraycopy(char[] value, int srcBegin, char[] dst, int dstBegin, int count) { + while (count-- > 0) { + dst[dstBegin++] = value[srcBegin++]; + } + } + + public static char copyArray() { + char[] arr = { '0' }; + arraycopy(arr()[0][0].chars, 0, arr, 0, 1); + return arr[0]; + } } diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,63 +1,86 @@ -/* -Java 4 Browser Bytecode Translator -Copyright (C) 2012-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. -*/ +/** + * 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 javax.script.Invocable; -import javax.script.ScriptException; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import static org.testng.Assert.*; /** * * @author Jaroslav Tulach */ public class ArrayTest { - @Test public void verifySimpleIntOperation() throws Exception { - assertExec("CheckTheSum", "org_apidesign_vm4brwsr_Array_simpleI", - Double.valueOf(15) + @Test public void intArrayShouldBeFilledWithZeroes() throws Exception { + assertExec("0 + 0", Array.class, "sum__II", + Double.valueOf(0), 2 ); } + @Test public void verifySimpleIntOperation() throws Exception { + assertExec("CheckTheSum", Array.class, "simple__IZ", + Double.valueOf(15), false + ); + } + + @Test public void cloneOnArray() throws Exception { + assertExec("CheckTheSum on clone", Array.class, "simple__IZ", + Double.valueOf(15), true + ); + } + + @Test public void realOperationOnArrays() throws Exception { + assertEquals(Array.sum(), 105.0, "Computes to 105"); + } + @Test public void verifyOperationsOnArrays() throws Exception { - assertExec("The sum is 105", "org_apidesign_vm4brwsr_Array_sumD", + assertExec("The sum is 105", Array.class, "sum__D", Double.valueOf(105) ); } + + @Test public void twoDoubles() throws Exception { + assertExec("Elements are initialized", Array.class, "twoDoubles__D", + Double.valueOf(0) + ); + } + @Test public void twoInts() throws Exception { + assertExec("Elements are initialized", Array.class, "twoInts__I", + Double.valueOf(0) + ); + } - private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception { + @Test public void doesCopyArrayWork() throws Exception { + assertExec("Returns 'a'", Array.class, "copyArray__C", Double.valueOf('a')); + } + + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { StringBuilder sb = new StringBuilder(); - Invocable i = StaticMethodTest.compileClass(sb, + code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Array" ); - - Object ret = null; - try { - ret = i.invokeFunction(methodName, args); - } catch (ScriptException ex) { - fail("Execution failed in " + sb, ex); - } catch (NoSuchMethodException ex) { - fail("Cannot find method in " + sb, ex); - } - if (ret == null && expRes == null) { - return; - } - if (expRes.equals(ret)) { - return; - } - assertEquals(ret, expRes, msg + "was: " + ret + "\n" + sb); + codeSeq = sb; + } + private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception { + StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args); } } diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ByteCodeToJavaScriptTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ByteCodeToJavaScriptTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,55 @@ +/** + * 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.Test; + +/** + * + * @author Jaroslav Tulach + */ +public class ByteCodeToJavaScriptTest { + + public ByteCodeToJavaScriptTest() { + } + + @Test + public void findMethodNameManglesObjectsCorrectly() { + StringBuilder cnt = new StringBuilder(); + char[] returnType = { 'V' }; + String ret = ByteCodeToJavaScript.findMethodName(new String[] { + "StringTest", "replace", "(Ljava/lang/String;CC)Ljava/lang/String;" + }, cnt, returnType); + assertEquals(cnt.toString(), "000", "No doubles or longs"); + assertTrue(returnType[0] != 'V', "Returns string"); + assertEquals(ret, "replace__Ljava_lang_String_2Ljava_lang_String_2CC"); + } + + @Test + public void manglingArrays() { + StringBuilder cnt = new StringBuilder(); + char[] returnType = { 'V' }; + String ret = ByteCodeToJavaScript.findMethodName(new String[] { + "VMinVM", "toJavaScript", "([B)Ljava/lang/String;" + }, cnt, returnType); + assertEquals(cnt.toString(), "0", "No doubles or longs"); + assertTrue(returnType[0] != 'V', "Returns string"); + assertEquals(ret, "toJavaScript__Ljava_lang_String_2_3B"); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,76 @@ +/** + * 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; +import java.net.URL; +import java.util.Enumeration; +import java.util.Set; +import java.util.TreeSet; + +/** + * + * @author Jaroslav Tulach + */ +public final class BytesLoader { + private static Set requested = new TreeSet(); + + public byte[] get(String name) throws IOException { + if (!requested.add(name)) { + throw new IllegalStateException("Requested for second time: " + name); + } + byte[] arr = readClass(name); + /* + System.err.print("loader['" + name + "'] = ["); + for (int i = 0; i < arr.length; i++) { + if (i > 0) { + System.err.print(", "); + } + System.err.print(arr[i]); + } + System.err.println("]"); + */ + return arr; + } + + static byte[] readClass(String name) throws IOException { + URL u = null; + Enumeration en = BytesLoader.class.getClassLoader().getResources(name); + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u == null) { + throw new IOException("Can't find " + name); + } + try (InputStream is = u.openStream()) { + byte[] arr; + arr = new byte[is.available()]; + int offset = 0; + while (offset < arr.length) { + int len = is.read(arr, offset, arr.length - offset); + if (len == -1) { + throw new IOException("Can't read " + name); + } + offset += len; + } + return arr; + } + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,185 @@ +/** + * 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 javax.script.Invocable; +import org.testng.annotations.Test; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; + +/** + * + * @author Jaroslav Tulach + */ +public class ClassTest { + + @Test public void superClassEqualsGetSuperclass() { + assertTrue(Classes.equalsClassesOfExceptions(), "Classes are equal"); + } + + @Test public void jsSuperClassEqualsGetSuperclass() throws Exception { + assertExec("Classes are equal", Classes.class, "equalsClassesOfExceptions__Z", Double.valueOf(1.0)); + } + + @Test public void classesAreDifferent() { + assertTrue(Classes.differenceInClasses(), "Classes are not equal"); + } + + @Test public void jsClassesAreDifferent() throws Exception { + assertExec("Classes are not equal", Classes.class, "differenceInClasses__Z", Double.valueOf(1.0)); + } + + @Test public void javaInstanceName() throws Exception { + assertEquals(Classes.classForInstance(), "java.io.IOException"); + } + @Test public void jsInstanceName() throws Exception { + assertExec("I/O name", Classes.class, "classForInstance__Ljava_lang_String_2", "java.io.IOException"); + } + @Test public void javaName() throws Exception { + assertEquals(Classes.name(), "java.io.IOException"); + } + @Test public void jsName() throws Exception { + assertExec("I/O name", Classes.class, "name__Ljava_lang_String_2", "java.io.IOException"); + } + @Test public void javaSimpleName() throws Exception { + assertEquals(Classes.simpleName(), "IOException"); + } + @Test public void jsGetsSimpleName() throws Exception { + assertExec("I/O simple name", Classes.class, "simpleName__Ljava_lang_String_2", "IOException"); + } + @Test public void javaCanonicalName() { + assertEquals(Classes.canonicalName(), "java.io.IOException"); + } + @Test public void jsCanonicalName() throws Exception { + assertExec("I/O simple name", Classes.class, "canonicalName__Ljava_lang_String_2", "java.io.IOException"); + } + @Test public void javaNewInstance() throws Exception { + assertTrue(Classes.newInstance()); + } + @Test public void jsNewInstance() throws Exception { + assertExec("Check new instance", Classes.class, "newInstance__Z", Double.valueOf(1)); + } + @Test public void javaNoNewInstance() throws Exception { + assertEquals("java.lang.InstantiationException:java.lang.Float", + Classes.newInstanceNoPubConstructor() + ); + } + @Test public void jsNoNewInstance() throws Exception { + assertExec("Check problems with new instance", Classes.class, "newInstanceNoPubConstructor__Ljava_lang_String_2", + "java.lang.InstantiationException:java.lang.Float" + ); + } + @Test public void jsAnnotation() throws Exception { + assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10)); + } + @Test public void jsStringAnnotation() throws Exception { + assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", true); + } + @Test public void jsStringAnnotationFromArray() throws Exception { + assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", false); + } + @Test public void javaInvokeMethod() throws Exception { + assertEquals(Classes.reflectiveMethodCall(true, "name"), "java.io.IOException", "Calls the name() method via reflection"); + } + @Test public void jsInvokeMethod() throws Exception { + assertExec("Calls the name() method via reflection", Classes.class, + "reflectiveMethodCall__Ljava_lang_Object_2ZLjava_lang_String_2", + "java.io.IOException", true, "name" + ); + } + @Test public void jsInvokeParamMethod() throws Exception { + assertExec("sums two numbers via reflection", Classes.class, + "reflectiveSum__III", Double.valueOf(5), 2, 3 + ); + } + @Test public void javaFindMethod() throws Exception { + assertEquals(Classes.reflectiveMethodCall(false, "name"), "java.io.IOException", "Calls the name() method via reflection"); + } + @Test public void jsFindMethod() throws Exception { + assertExec("Calls the name() method via reflection", Classes.class, + "reflectiveMethodCall__Ljava_lang_Object_2ZLjava_lang_String_2", + "java.io.IOException", false, "name" + ); + } + @Test public void primitiveReturnType() throws Exception { + assertExec("Tries to get an integer via reflection", Classes.class, + "primitiveType__Ljava_lang_String_2Ljava_lang_String_2", + Classes.primitiveType("primitive"), "primitive" + ); + } + @Test public void primitiveBoolReturnType() throws Exception { + assertExec("Tries to get an integer via reflection", Classes.class, + "primitiveType__Ljava_lang_String_2Ljava_lang_String_2", + Classes.primitiveType("primitiveB"), "primitiveB" + ); + } + @Test public void javaAnnotatedMethod() throws Exception { + assertEquals(Classes.reflectiveMethodCall(false, null), "java.io.IOException", "Calls the name() method via reflection"); + } + @Test public void jsAnnotatedMethod() throws Exception { + assertExec("Calls the name() method via reflection", Classes.class, + "reflectiveMethodCall__Ljava_lang_Object_2ZLjava_lang_String_2", + "java.io.IOException", false, null + ); + } + @Test public void jsClassParam() throws Exception { + assertExec("Calls the nameOfIO()", Classes.class, + "nameOfIO__Ljava_lang_String_2", + "java.io.IOException" + ); + } + @Test public void noInterface() throws Exception { + assertExec("Calls Class.isInterface", Classes.class, + "isInterface__ZLjava_lang_String_2", + 0.0, "java.lang.String" + ); + } + /* + @Test public void isInterface() throws Exception { + assertExec("Calls Class.isInterface", Classes.class, + "isInterface__ZLjava_lang_String_2", + 1.0, "java.lang.Runnable" + ); + } + */ + @Test public void integerType() throws Exception { + assertExec("Computes the type", Classes.class, + "intType__Ljava_lang_String_2", + Classes.intType() + ); + } + + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { + if (codeSeq == null) { + StringBuilder sb = new StringBuilder(); + code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Classes"); + codeSeq = sb; + } + } + + private void assertExec( + String msg, Class clazz, String method, Object expRes, Object... args + ) throws Exception { + StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args); + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/Classes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,154 @@ +/** + * 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.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Jaroslav Tulach + */ +@ClassesMarker(number = 10) +@ClassesNamer(name = "my text") +public class Classes { + public static String nameOfIO() { + return nameFor(IOException.class); + } + + private static String nameFor(Class c) { + return c.getName(); + } + + public static boolean isInterface(String s) throws ClassNotFoundException { + return Class.forName(s).isInterface(); + } + + public static boolean equalsClassesOfExceptions() { + return MalformedURLException.class.getSuperclass() == IOException.class; + } + public static boolean differenceInClasses() { + Class c1 = MalformedURLException.class; + Class c2 = IOException.class; + return c1 != c2; + } + + public static String classForInstance() { + return new IOException().getClass().getName().toString(); + } + + @ClassesMarker(number = 1) + public static String name() { + return IOException.class.getName().toString(); + } + public static String simpleName() { + return IOException.class.getSimpleName(); + } + public static String canonicalName() { + return IOException.class.getCanonicalName(); + } + public static boolean newInstance() throws Exception { + IOException ioe = IOException.class.newInstance(); + if (ioe instanceof IOException) { + return ioe.getClass() == IOException.class; + } + throw new IllegalStateException("Not a subtype: " + ioe); + } + public static String newInstanceNoPubConstructor() throws Exception { + try { + Float f = Float.class.newInstance(); + return "wrong, can't instantiate: " + f; + } catch (Exception ex) { + return (ex.getClass().getName() + ":" + ex.getMessage()).toString().toString(); + } + } + public static int getMarker() { + if (!Classes.class.isAnnotationPresent(ClassesMarker.class)) { + return -2; + } + ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class); + return cm == null ? -1 : cm.number(); + } + public static String getNamer(boolean direct) { + if (direct) { + ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class); + return cm == null ? null : cm.name(); + } + for (Annotation a : Classes.class.getAnnotations()) { + if (a instanceof ClassesNamer) { + return ((ClassesNamer)a).name(); + } + } + return null; + } + + public static String intType() { + return Integer.TYPE.getName(); + } + + public static int primitive() { + return 1; + } + public static boolean primitiveB() { + return true; + } + + public static String primitiveType(String method) throws Exception { + return reflectiveMethodCall(false, method).getClass().getName(); + } + + @JavaScriptBody(args = "msg", body = "throw msg;") + private static native void thrw(String msg); + + public static Object reflectiveMethodCall(boolean direct, String mn) throws Exception { + Method find = null; + StringBuilder sb = new StringBuilder(); + if (!direct) { + final Class v = ClassesMarker.class; + for (Method m : Classes.class.getMethods()) { + sb.append("\n").append(m.getName()); + if (mn != null) { + if (m.getName().equals(mn)) { + find = m; + break; + } + } else { + if (m.getAnnotation(v) != null) { + find = m; + break; + } + } + } + } else { + find = Classes.class.getMethod(mn); + } + if (find == null) { + thrw(sb.toString()); + throw new NullPointerException(sb.toString()); + } + return find.invoke(null); + } + + public static int reflectiveSum(int a, int b) throws Exception { + Method m = StaticMethod.class.getMethod("sum", int.class, int.class); + return (int) m.invoke(null, a, b); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,30 @@ +/** + * 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.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface ClassesMarker { + int number(); +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,30 @@ +/** + * 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.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface ClassesNamer { + String name(); +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/Exceptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Exceptions.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,88 @@ +/** + * 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 org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author tom + */ +public class Exceptions { + private Exceptions() { + } + + public static int methodWithTryCatchNoThrow() { + int res = 0; + try { + res = 1; + } catch (IllegalArgumentException e) { + res = 2; + } + //join point + return res; + } + + public static int methodWithTryCatchThrow() { + int res = 0; + try { + res = 1; + throw new IllegalArgumentException(); + } catch (IllegalArgumentException e) { + res = 2; + } + //join point + return res; + } + + @JavaScriptBody(args = "msg", body = "throw msg;") + public static void thrw(String msg) {} + + public static String catchThrowableCatchesAll() { + try { + thrw("Hello!"); + return "Not here!"; + } catch (Throwable ex) { + return ex.getMessage(); + } + } + + public static String newInstance(String n) { + try { + Class c; + try { + c = Class.forName(n); + } catch (ClassNotFoundException ex) { + return ("CNFE:" + ex.getMessage()).toString(); + } + return c.newInstance().getClass().getName(); + } catch (InstantiationException | IllegalAccessException ex) { + return ex.getMessage(); + } + } + + private static int counter; + public static int readCounter(String n) throws ClassNotFoundException { + try { + Class.forName(n); + } finally { + counter++; + } + return counter; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,121 @@ +/** + * 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 javax.script.Invocable; +import javax.script.ScriptException; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author Tomas Zezula + */ +public class ExceptionsTest { + @Test + public void verifyMethodWithTryCatchNoThrow() throws Exception { + assertExec( + "No throw", + Exceptions.class, + "methodWithTryCatchNoThrow__I", + new Double(1.0)); + } + + @Test + public void catchJavaScriptStringAsThrowable() throws Exception { + assertExec( + "Throw hello!", + Exceptions.class, + "catchThrowableCatchesAll__Ljava_lang_String_2", + "Hello!" + ); + } + + @Test + public void verifyMethodWithTryCatchThrow() throws Exception { + assertExec( + "Throw", + Exceptions.class, + "methodWithTryCatchThrow__I", + new Double(2.0)); + } + + @Test public void createObject() throws Exception { + assertExec("Object created", Exceptions.class, + "newInstance__Ljava_lang_String_2Ljava_lang_String_2", + "java.lang.Object", + "java.lang.Object" + ); + } + + @Test public void createFloatFails() throws Exception { + assertExec("Float not created", Exceptions.class, + "newInstance__Ljava_lang_String_2Ljava_lang_String_2", + "java.lang.Float", + "java.lang.Float" + ); + } + + @Test public void createUnknownFails() throws Exception { + assertExec("Object created", Exceptions.class, + "newInstance__Ljava_lang_String_2Ljava_lang_String_2", + "CNFE:org.apidesign.Unknown", + "org.apidesign.Unknown" + ); + } + + @Test public void testThreeCalls() throws Exception { + Object vm = code.invokeFunction("bck2brwsr"); + Object clazz = code.invokeMethod(vm, "loadClass", Exceptions.class.getName()); + + String method = "readCounter__ILjava_lang_String_2"; + + try { + Object ret = code.invokeMethod(clazz, method, "org.apidesign.Unknown"); + fail("We expect an CNFE!"); + } catch (ScriptException scriptException) { + // script exception should be OK + } + { + // 2nd invocation + Object ret = code.invokeMethod(clazz, method, "java.lang.String"); + assertEquals(ret, Double.valueOf(2)); + } + { + // 3rd invocation + Object ret = code.invokeMethod(clazz, method, "java.lang.Integer"); + assertEquals(ret, Double.valueOf(3)); + } + } + + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { + StringBuilder sb = new StringBuilder(); + code = StaticMethodTest.compileClass(sb, + "org/apidesign/vm4brwsr/Exceptions" + ); + codeSeq = sb; + } + private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception { + StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/GetByte.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/GetByte.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/GetByte.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,6 +1,6 @@ /** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-2012 Jaroslav Tulach + * 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 diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/Instance.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,6 +1,6 @@ /** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-2012 Jaroslav Tulach + * 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 @@ -17,12 +17,14 @@ */ package org.apidesign.vm4brwsr; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * * @author Jaroslav Tulach */ public class Instance { - private int i; + private int in; protected short s; public double d; private float f; @@ -32,7 +34,7 @@ } public Instance(int i, double d) { - this.i = i; + this.in = i; this.d = d; } public byte getByte() { @@ -53,7 +55,7 @@ public static double magicOne() { Instance i = new Instance(10, 3.3d); i.b = (byte)0x09; - return (i.i - i.b) * i.d; + return (i.in - i.b) * i.d; } public static int virtualBytes() { Instance i = new InstanceSub(7, 2.2d); @@ -89,4 +91,45 @@ private static boolean isNull() { return createInstance(true) == null; } + + @JavaScriptBody(args = "obj", body = "return obj.constructor;") + static Object constructor(Object obj) { + return obj; + } + + public static boolean sharedConstructor() { + class X { + } + + X x1 = new X(); + X x2 = new X(); + + return constructor(x1) == constructor(x2); + } + public static boolean differentConstructor() { + class X { + } + class Y { + } + + X x = new X(); + Y y = new Y(); + + return constructor(x) == constructor(y); + } + @JavaScriptBody(args = {}, body = "return {};") + private static Object jsObj() { + return null; + } + + public static boolean iofObject() { + return jsObj() instanceof Object; + } + + public static int jscall() { + return jsgetbytes(new Instance()); + } + + @JavaScriptBody(args = { "instance" }, body = "return instance.getByte__B();") + private static native int jsgetbytes(Instance instance); } diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/InstanceSub.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceSub.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceSub.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,6 +1,6 @@ /** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-2012 Jaroslav Tulach + * 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 @@ -22,12 +22,19 @@ * @author Jaroslav Tulach */ public class InstanceSub extends Instance implements GetByte { + private double in; + public InstanceSub(int i, double d) { super(i, d); + in = 555.55; } @Override public void setByte(byte b) { super.setByte((byte) (b + 1)); } + + public static double recallDbl() { + return defaultDblValue(); + } } diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/InstanceSubTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceSubTest.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceSubTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,3 +1,20 @@ +/** + * 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; /** Checks if everything works OK, when we switch the diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,6 +1,6 @@ /** - * Java 4 Browser Bytecode Translator - * Copyright (C) 2012-2012 Jaroslav Tulach + * 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 @@ -18,9 +18,8 @@ package org.apidesign.vm4brwsr; import javax.script.Invocable; -import javax.script.ScriptException; import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; /** * @@ -30,35 +29,42 @@ @Test public void verifyDefaultDoubleValue() throws Exception { assertExec( "Will be zero", - "org_apidesign_vm4brwsr_Instance_defaultDblValueD", + Instance.class, "defaultDblValue__D", + Double.valueOf(0) + ); + } + @Test public void verifyStaticMethodCall() throws Exception { + assertExec( + "Will be zero", + InstanceSub.class, "recallDbl__D", Double.valueOf(0) ); } @Test public void verifyAssignedByteValue() throws Exception { assertExec( "Will one thirty one", - "org_apidesign_vm4brwsr_Instance_assignedByteValueB", + Instance.class, "assignedByteValue__B", Double.valueOf(31) ); } @Test public void verifyMagicOne() throws Exception { assertExec( "Should be three and something", - "org_apidesign_vm4brwsr_Instance_magicOneD", + Instance.class, "magicOne__D", Double.valueOf(3.3) ); } @Test public void verifyInstanceMethods() throws Exception { assertExec( "Should be eleven as we invoke overwritten method, plus 44", - "org_apidesign_vm4brwsr_Instance_virtualBytesI", + Instance.class, "virtualBytes__I", Double.valueOf(55) ); } @Test public void verifyInterfaceMethods() throws Exception { assertExec( "Retruns default value", - "org_apidesign_vm4brwsr_Instance_interfaceBytesF", + Instance.class, "interfaceBytes__F", Double.valueOf(31) ); } @@ -66,7 +72,7 @@ @Test public void isNull() throws Exception { assertExec( "Yes, we are instance", - "org_apidesign_vm4brwsr_Instance_isNullZ", + Instance.class, "isNull__Z", Double.valueOf(0.0) ); } @@ -74,7 +80,7 @@ @Test public void isInstanceOf() throws Exception { assertExec( "Yes, we are instance", - "org_apidesign_vm4brwsr_Instance_instanceOfZZ", + Instance.class, "instanceOf__ZZ", Double.valueOf(1.0), true ); } @@ -82,7 +88,7 @@ @Test public void notInstanceOf() throws Exception { assertExec( "No, we are not an instance", - "org_apidesign_vm4brwsr_Instance_instanceOfZZ", + Instance.class, "instanceOf__ZZ", Double.valueOf(0.0), false ); } @@ -90,44 +96,70 @@ @Test public void verifyCastToClass() throws Exception { assertExec( "Five signals all is good", - "org_apidesign_vm4brwsr_Instance_castsWorkIZ", + Instance.class, "castsWork__IZ", Double.valueOf(5.0), false ); } @Test public void verifyCastToInterface() throws Exception { assertExec( "Five signals all is good", - "org_apidesign_vm4brwsr_Instance_castsWorkIZ", + Instance.class, "castsWork__IZ", Double.valueOf(5.0), true ); } + @Test public void sharedConstructor() throws Exception { + assertExec( + "Constructor of first and 2nd instance should be the same", + Instance.class, "sharedConstructor__Z", + Double.valueOf(1.0) + ); + } + + @Test public void differentConstructor() throws Exception { + assertExec( + "Constructor of X and Y should be the different", + Instance.class, "differentConstructor__Z", + Double.valueOf(0) + ); + } + + @Test public void jsObjectIsLikeJavaObject() throws Exception { + assertExec( + "JavaScript object is instance of Java Object", + Instance.class, "iofObject__Z", + Double.valueOf(1) + ); + } + + @Test public void jsCallingConvention() throws Exception { + assertExec( + "Pointer to 'this' is passed automatically (and not as a first argument)", + Instance.class, "jscall__I", + Double.valueOf(31) + ); + } + protected String startCompilationWith() { return "org/apidesign/vm4brwsr/Instance"; } + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { + if (codeSeq == null) { + StringBuilder sb = new StringBuilder(); + code = StaticMethodTest.compileClass(sb, startCompilationWith()); + codeSeq = sb; + } + } + private void assertExec( - String msg, String methodName, Object expRes, Object... args + String msg, Class clazz, String method, Object expRes, Object... args ) throws Exception { - StringBuilder sb = new StringBuilder(); - Invocable i = StaticMethodTest.compileClass(sb, startCompilationWith()); - - Object ret = null; - try { - ret = i.invokeFunction(methodName, args); - } catch (ScriptException ex) { - fail("Execution failed in " + sb, ex); - } catch (NoSuchMethodException ex) { - fail("Cannot find method in " + sb, ex); - } - if (ret == null && expRes == null) { - return; - } - if (expRes.equals(ret)) { - return; - } - assertEquals(ret, expRes, msg + "was: " + ret + "\n" + sb); - + StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args); } } diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,187 @@ +/** + * 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 javax.script.Invocable; +import javax.script.ScriptException; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public class NumberTest { + @Test public void integerFromString() throws Exception { + assertExec("Can convert string to integer", Integer.class, "parseInt__ILjava_lang_String_2", + Double.valueOf(333), "333" + ); + } + + @Test public void doubleFromString() throws Exception { + assertExec("Can convert string to double", Double.class, "parseDouble__DLjava_lang_String_2", + Double.valueOf(33.3), "33.3" + ); + } + + @Test public void autoboxDouble() throws Exception { + assertExec("Autoboxing of doubles is OK", Numbers.class, "autoboxDblToString__Ljava_lang_String_2", + "3.3" + ); + } + + @Test public void javalog1000() throws Exception { + assertEquals(3.0, Math.log10(1000.0), 0.00003, "log_10(1000) == 3"); + } + + @Test public void jslog1000() throws Exception { + assertExec("log_10(1000) == 3", Math.class, "log10__DD", + Double.valueOf(3.0), 1000.0 + ); + } + + @Test public void javaRem() { + assertEquals(3, Numbers.rem(303, 10)); + } + @Test public void jsRem() throws Exception { + assertExec("Should be three", Numbers.class, "rem__III", + Double.valueOf(3.0), 303, 10 + ); + } + + @Test public void deserializeInt() throws Exception { + int exp = Numbers.deserInt(); + assertExec("Should be the same", Numbers.class, "deserInt__I", + Double.valueOf(exp) + ); + } + + @Test public void deserializeSimpleLong() throws Exception { + assertExec("Should be 3454", Numbers.class, "deserLong__J_3B", + Double.valueOf(3454), + new byte[] { (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)13, (byte)126 } + ); + } + /* XXX: JavaScript cannot represent as big longs as Java. + @Test public void deserializeLargeLong() throws Exception { + final byte[] arr = new byte[] { + (byte)64, (byte)8, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 + }; + long exp = Numbers.deserLong(arr); + assertExec("Should be " + exp, "org_apidesign_vm4brwsr_Numbers_deserLong__JAB", + Double.valueOf(exp), arr); + } + */ + + @Test public void deserializeFloatInJava() throws Exception { + float f = 54324.32423f; + float r = Numbers.deserFloat(); + assertEquals(r, f, "Floats are the same"); + } + + @Test public void deserializeFloatInJS() throws Exception { + float f = 54324.32423f; + assertExec("Should be the same", Numbers.class, "deserFloat__F", + Double.valueOf(f) + ); + } + + @Test public void deserializeDoubleInJava() throws Exception { + double f = 3.0; + double r = Numbers.deserDouble(); + assertEquals(r, f, 0.001, "Doubles are the same"); + } + + @Test public void deserializeDoubleInJS() throws Exception { + double f = 3.0; + assertExec("Should be the same", Numbers.class, "deserDouble__D", f); + } + /* + @Test public void serDouble() throws IOException { + double f = 3.0; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + DataOutputStream d = new DataOutputStream(os); + d.writeLong(3454); + d.close(); + + StringBuilder sb = new StringBuilder(); + byte[] arr = os.toByteArray(); + for (int i = 0; i < arr.length; i++) { + sb.append("(byte)").append(arr[i]).append(", "); + } + fail("" + sb); + } +*/ + @Test public void fiveInStringJS() throws Exception { + String s = Numbers.intToString(); + assertExec("Should be the same: " + s, + Numbers.class, "intToString__Ljava_lang_String_2", + s + ); + } + + @Test public void sevenInStringJS() throws Exception { + String s = Numbers.floatToString(); + assertExec("Should be the same: " + s, + Numbers.class, "floatToString__Ljava_lang_String_2", + s + ); + } + + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { + if (codeSeq == null) { + StringBuilder sb = new StringBuilder(); + code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Numbers"); + codeSeq = sb; + } + } + + private static void assertExec( + String msg, Class clazz, String method, Object expRes, Object... args) throws Exception { + + Object ret = null; + try { + ret = code.invokeFunction("bck2brwsr"); + ret = code.invokeMethod(ret, "loadClass", clazz.getName()); + ret = code.invokeMethod(ret, method, args); + } catch (ScriptException ex) { + fail("Execution failed in\n" + StaticMethodTest.dumpJS(codeSeq), ex); + } catch (NoSuchMethodException ex) { + fail("Cannot find method in\n" + StaticMethodTest.dumpJS(codeSeq), ex); + } + if (ret == null && expRes == null) { + return; + } + if (expRes.equals(ret)) { + return; + } + if (expRes instanceof Double && ret instanceof Double) { + double expD = ((Double)expRes).doubleValue(); + double retD = ((Double)ret).doubleValue(); + assertEquals(retD, expD, 0.000004, msg + " was " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq)); + return; + } + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq)); + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,70 @@ +/** + * 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.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author Jaroslav Tulach + */ +public class Numbers { + private static Double autoboxDbl() { + return 3.3; + } + public static String autoboxDblToString() { + return autoboxDbl().toString().toString(); + } + public static int rem(int a, int b) { + return a % b; + } + + static float deserFloat() throws IOException { + byte[] arr = {(byte) 71, (byte) 84, (byte) 52, (byte) 83}; + ByteArrayInputStream is = new ByteArrayInputStream(arr); + DataInputStream dis = new DataInputStream(is); + float r = dis.readFloat(); + return r; + } + static double deserDouble() throws IOException { + byte[] arr = {(byte)64, (byte)8, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0}; + ByteArrayInputStream is = new ByteArrayInputStream(arr); + DataInputStream dis = new DataInputStream(is); + return dis.readDouble(); + } + static long deserLong(byte[] arr) throws IOException { + ByteArrayInputStream is = new ByteArrayInputStream(arr); + DataInputStream dis = new DataInputStream(is); + return dis.readLong(); + } + static int deserInt() throws IOException { + byte[] arr = {(byte) 71, (byte) 84, (byte) 52, (byte) 83}; + ByteArrayInputStream is = new ByteArrayInputStream(arr); + DataInputStream dis = new DataInputStream(is); + return dis.readInt(); + } + + static String intToString() { + return new Integer(5).toString().toString(); + } + static String floatToString() { + return new Float(7.0).toString().toString(); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/Script.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Script.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,31 @@ +/** + * 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 org.apidesign.bck2brwsr.core.ExtraJavaScript; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** Test to verify external scripts are processed in lazy mode. + * + * @author Jaroslav Tulach + */ +@ExtraJavaScript(resource = "/org/apidesign/vm4brwsr/ko.js") +public class Script { + @JavaScriptBody(args = { }, body = "return ko !== null;") + public static native boolean checkNotNull(); +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,20 +1,20 @@ -/* -Java 4 Browser Bytecode Translator -Copyright (C) 2012-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. -*/ +/** + * 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 org.apidesign.bck2brwsr.core.JavaScriptBody; @@ -25,6 +25,7 @@ */ public class StaticMethod { private static int cnt; + private static Object NULL; public static int minusOne() { return -1; @@ -42,6 +43,10 @@ return toRet; } + public static boolean isNull() { + return NULL == null; + } + public static int sum(int x, int y) { return x + y; } @@ -95,12 +100,34 @@ } @JavaScriptBody( - args={"i","j"}, body="return (i + j).toString();" + args={"i","j"}, body="\n\r\treturn (i + j).toString();" ) public static String i2s(int i, int j) { throw new IllegalStateException(); } + public static String castNull(boolean n) { + Object value = n ? null : "Ahoj"; + return (String)value; + } + + public static String swtch(int what) { + switch (what) { + case 0: return "Jarda"; + case 1: return "Darda"; + case 2: return "Parda"; + default: return "Marda"; + } + } + public static String swtch2(int what) { + switch (what) { + case 0: return "Jarda"; + case 11: return "Darda"; + case 22: return "Parda"; + default: return "Marda"; + } + } + static { // check order of initializers StaticUse.NON_NULL.equals(new Object()); diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,28 +1,34 @@ -/* -Java 4 Browser Bytecode Translator -Copyright (C) 2012-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. -*/ +/** + * 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.File; +import java.io.FileWriter; import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Enumeration; import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** Checks the basic behavior of the translator. @@ -33,16 +39,24 @@ @Test public void threePlusFour() throws Exception { assertExec( "Should be seven", - "org_apidesign_vm4brwsr_StaticMethod_sumIII", + StaticMethod.class, "sum__III", Double.valueOf(7), 3, 4 ); } + @Test public void checkReallyInitializedValues() throws Exception { + assertExec( + "Return true", + StaticMethod.class, "isNull__Z", + Double.valueOf(1) + ); + } + @Test public void powerOfThree() throws Exception { assertExec( "Should be nine", - "org_apidesign_vm4brwsr_StaticMethod_powerFF", + StaticMethod.class, "power__FF", Double.valueOf(9), 3.0f ); @@ -51,7 +65,7 @@ @Test public void minusOne() throws Exception { assertExec( "Should be minus one", - "org_apidesign_vm4brwsr_StaticMethod_minusOneI", + StaticMethod.class, "minusOne__I", Double.valueOf(-1) ); } @@ -59,7 +73,7 @@ @Test public void doubleWithoutLong() throws Exception { assertExec( "Should be two", - "org_apidesign_vm4brwsr_StaticMethod_minusDDJ", + StaticMethod.class, "minus__DDJ", Double.valueOf(2), 3.0d, 1l ); @@ -68,7 +82,7 @@ @Test public void divAndRound() throws Exception { assertExec( "Should be rounded to one", - "org_apidesign_vm4brwsr_StaticMethod_divIBD", + StaticMethod.class, "div__IBD", Double.valueOf(1), 3, 3.75 ); @@ -76,7 +90,7 @@ @Test public void mixedMethodFourParams() throws Exception { assertExec( "Should be two", - "org_apidesign_vm4brwsr_StaticMethod_mixIIJBD", + StaticMethod.class, "mix__IIJBD", Double.valueOf(20), 2, 10l, 5, 2.0 ); @@ -84,7 +98,7 @@ @Test public void factRec() throws Exception { assertExec( "Factorial of 5 is 120", - "org_apidesign_vm4brwsr_StaticMethod_factRecJI", + StaticMethod.class, "factRec__JI", Double.valueOf(120), 5 ); @@ -92,7 +106,7 @@ @Test public void factIter() throws Exception { assertExec( "Factorial of 5 is 120", - "org_apidesign_vm4brwsr_StaticMethod_factIterJI", + StaticMethod.class, "factIter__JI", Double.valueOf(120), 5 ); @@ -101,7 +115,7 @@ @Test public void xor() throws Exception { assertExec( "Xor is 4", - "org_apidesign_vm4brwsr_StaticMethod_xorJIJ", + StaticMethod.class, "xor__JIJ", Double.valueOf(4), 7, 3 @@ -111,7 +125,7 @@ @Test public void or() throws Exception { assertExec( "Or will be 7", - "org_apidesign_vm4brwsr_StaticMethod_orOrAndJZII", + StaticMethod.class, "orOrAnd__JZII", Double.valueOf(7), true, 4, @@ -121,14 +135,14 @@ @Test public void nullCheck() throws Exception { assertExec( "Returns nothing", - "org_apidesign_vm4brwsr_StaticMethod_noneLjava_lang_ObjectII", + StaticMethod.class, "none__Ljava_lang_Object_2II", null, 1, 3 ); } @Test public void and() throws Exception { assertExec( "And will be 3", - "org_apidesign_vm4brwsr_StaticMethod_orOrAndJZII", + StaticMethod.class, "orOrAnd__JZII", Double.valueOf(3), false, 7, @@ -138,7 +152,7 @@ @Test public void inc4() throws Exception { assertExec( "It will be 4", - "org_apidesign_vm4brwsr_StaticMethod_inc4I", + StaticMethod.class, "inc4__I", Double.valueOf(4) ); } @@ -151,7 +165,7 @@ @Test public void shiftLeftInJS() throws Exception { assertExec( "Setting 9th bit", - "org_apidesign_vm4brwsr_StaticMethod_shiftLeftIII", + StaticMethod.class, "shiftLeft__III", Double.valueOf(256), 1, 8 ); @@ -165,7 +179,7 @@ @Test public void shiftRightInJS() throws Exception { assertExec( "Get -1", - "org_apidesign_vm4brwsr_StaticMethod_shiftArithmRightIIIZ", + StaticMethod.class, "shiftArithmRight__IIIZ", Double.valueOf(-1), -8, 3, true ); @@ -178,7 +192,7 @@ @Test public void unsignedShiftRightInJS() throws Exception { assertExec( "Get -1", - "org_apidesign_vm4brwsr_StaticMethod_shiftArithmRightIIIZ", + StaticMethod.class, "shiftArithmRight__IIIZ", Double.valueOf(1), 8, 3, false ); @@ -187,23 +201,84 @@ @Test public void javaScriptBody() throws Exception { assertExec( "JavaScript string", - "org_apidesign_vm4brwsr_StaticMethod_i2sLjava_lang_StringII", + StaticMethod.class, "i2s__Ljava_lang_String_2II", "333", 330, 3 ); } - private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception { + @Test public void switchJarda() throws Exception { + assertExec( + "The expected value", + StaticMethod.class, "swtch__Ljava_lang_String_2I", + "Jarda", + 0 + ); + } + + @Test public void switchDarda() throws Exception { + assertExec( + "The expected value", + StaticMethod.class, "swtch__Ljava_lang_String_2I", + "Darda", + 1 + ); + } + @Test public void switchParda() throws Exception { + assertExec( + "The expected value", + StaticMethod.class, "swtch2__Ljava_lang_String_2I", + "Parda", + 22 + ); + } + @Test public void switchMarda() throws Exception { + assertExec( + "The expected value", + StaticMethod.class, "swtch__Ljava_lang_String_2I", + "Marda", + -433 + ); + } + + @Test public void checkNullCast() throws Exception { + assertExec("Null can be cast to any type", + StaticMethod.class, "castNull__Ljava_lang_String_2Z", + null, true + ); + } + + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { StringBuilder sb = new StringBuilder(); - Invocable i = compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod"); - + code = compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod"); + codeSeq = sb; + } + + + private static void assertExec( + String msg, Class clazz, String method, + Object expRes, Object... args + ) throws Exception { + assertExec(code, codeSeq, msg, clazz, method, expRes, args); + } + static void assertExec( + Invocable toRun, CharSequence theCode, + String msg, Class clazz, String method, + Object expRes, Object... args + ) throws Exception { Object ret = null; try { - ret = i.invokeFunction(methodName, args); + ret = toRun.invokeFunction("bck2brwsr"); + ret = toRun.invokeMethod(ret, "loadClass", clazz.getName()); + ret = toRun.invokeMethod(ret, method, args); } catch (ScriptException ex) { - fail("Execution failed in " + sb, ex); + fail("Execution failed in\n" + dumpJS(theCode), ex); } catch (NoSuchMethodException ex) { - fail("Cannot find method in " + sb, ex); + fail("Cannot find method in\n" + dumpJS(theCode), ex); } if (ret == null && expRes == null) { return; @@ -211,24 +286,59 @@ if (expRes != null && expRes.equals(ret)) { return; } - assertEquals(ret, expRes, msg + "was: " + ret + "\n" + sb); + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + dumpJS(theCode)); } static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException { + return compileClass(sb, null, names); + } + static Invocable compileClass( + StringBuilder sb, ScriptEngine[] eng, String... names + ) throws ScriptException, IOException { if (sb == null) { sb = new StringBuilder(); } - GenJS.compile(sb, names); + Bck2Brwsr.generate(sb, new EmulationResources(), names); 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 (Invocable)js; - } catch (ScriptException ex) { - fail("Could not compile:\n" + sb, ex); + } catch (Exception ex) { + if (sb.length() > 2000) { + sb = dumpJS(sb); + } + fail("Could not evaluate:\n" + sb, ex); return null; } } + static StringBuilder dumpJS(CharSequence sb) throws IOException { + File f = File.createTempFile("execution", ".js"); + FileWriter w = new FileWriter(f); + w.append(sb); + w.close(); + return new StringBuilder(f.getPath()); + } + private static class EmulationResources implements Bck2Brwsr.Resources { + @Override + public InputStream get(String name) throws IOException { + Enumeration en = StaticMethodTest.class.getClassLoader().getResources(name); + URL u = null; + while (en.hasMoreElements()) { + u = en.nextElement(); + } + if (u == null) { + throw new IOException("Can't find " + name); + } + if (u.toExternalForm().contains("rt.jar!")) { + throw new IOException("No emulation for " + u); + } + return u.openStream(); + } + } } diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/StaticUse.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticUse.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticUse.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,3 +1,20 @@ +/** + * 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; public class StaticUse { diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/StringArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringArrayTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,50 @@ +/** + * 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 org.testng.annotations.Test; +import static org.testng.Assert.*; + +public class StringArrayTest { + @Test public void deleteMinusIndex() throws Exception { + String[] arr = { "Ahoj", "Kluci" }; + StringArray list = StringArray.asList(arr); + list.delete(-1); + assertEquals(list.toArray().length, 2, "No element removed"); + } + @Test public void deleteTooHighIndex() throws Exception { + String[] arr = { "Ahoj", "Kluci" }; + StringArray list = StringArray.asList(arr); + list.delete(5); + assertEquals(list.toArray().length, 2, "No element removed"); + } + @Test public void deleteFirst() throws Exception { + String[] arr = { "Ahoj", "Kluci" }; + StringArray list = StringArray.asList(arr); + list.delete(0); + assertEquals(list.toArray().length, 1, "First element removed"); + assertEquals(list.toArray()[0], "Kluci"); + } + @Test public void deleteSecond() throws Exception { + String[] arr = { "Ahoj", "Kluci" }; + StringArray list = StringArray.asList(arr); + list.delete(1); + assertEquals(list.toArray().length, 1, "Second element removed"); + assertEquals(list.toArray()[0], "Ahoj"); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,3 +1,20 @@ +/** + * 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; /** @@ -18,18 +35,80 @@ return HELLO.charAt(indx); } + public static boolean equalToHello(int from, int to) { + return "Hello".equals(HELLO.substring(from, to)); + } + public static String fromChars(char a, char b, char c) { char[] arr = { a, b, c }; return new String(arr).toString(); } + public static String charsFromNumbers() { + return chars((char)65, (char)66, (char)67); + } + + public static String charsFromChars() { + return chars('A', 'B', 'C'); + } + + public static String chars(char a, char b, char c) { + return ("" + a + b +c).toString(); + } + + public static String replace(String s, char a, char b) { + return s.replace(a, b); + } + + public static int hashCode(String h) { + return h.hashCode(); + } + + public static boolean isStringInstance() { + return chars('a', (char)30, 'b') instanceof String; + } + + public static String insertBuffer() { + StringBuilder sb = new StringBuilder(); + sb.append("Jardo!"); + sb.insert(0, "Ahoj "); + sb.delete(4, 8); + return sb.toString().toString(); + } + + public static int countAB(String txt) { + int cnt = 0; + for (int i = 0; i < txt.length(); i++) { + switch (txt.charAt(i)) { + case 'A': cnt++; break; + case 'B': cnt += 2; break; + } + } + return cnt; + } + + public static int stringSwitch(String txt) { + switch (txt) { + case "jedna": return 1; + case "dve": return 2; + case "tri": return 3; + case "ctyri": return 4; + } + return -1; + } + public static String toStringTest(int howMuch) { + counter = 0; StringSample ss = null; for (int i = 0; i < howMuch; i++) { ss = new StringSample(); } return ss.toString().toString(); } + + public static String concatStrings() { + return (toStringTest(1) + "\\\n\r\t").toString(); + } @Override public String toString() { diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Thu Oct 11 06:15:22 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -1,9 +1,26 @@ +/** + * 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 javax.script.Invocable; -import javax.script.ScriptException; import org.testng.annotations.Test; import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; /** * @@ -13,23 +30,55 @@ @Test public void firstChar() throws Exception { assertExec( "First char in Hello is H", - "org_apidesign_vm4brwsr_StringSample_sayHelloCI", - "H", 0 + StringSample.class, "sayHello__CI", + 72, 0 ); } @Test public void fromChars() throws Exception { assertExec( "First char in Hello is ABC", - "org_apidesign_vm4brwsr_StringSample_fromCharsLjava_lang_StringCCC", + StringSample.class, "fromChars__Ljava_lang_String_2CCC", "ABC", 'A', 'B', 'C' ); } + @Test public void concatChars() throws Exception { + assertExec( + "Composing yields ABC", + StringSample.class, "chars__Ljava_lang_String_2CCC", + "ABC", 'A', 'B', 'C' + ); + } + + @Test public void concatCharsFromInts() throws Exception { + assertExec( + "Composing yields ABC", + StringSample.class, "charsFromNumbers__Ljava_lang_String_2", + "ABC" + ); + } + + @Test public void concatCharsFromChars() throws Exception { + assertExec( + "Composing yields ABC", + StringSample.class, "charsFromChars__Ljava_lang_String_2", + "ABC" + ); + } + + @Test public void instanceOfWorks() throws Exception { + assertExec( + "It is string", + StringSample.class, "isStringInstance__Z", + Double.valueOf(1.0) + ); + } + @Test(timeOut=10000) public void toStringConcatenation() throws Exception { assertExec( "Five executions should generate 5Hello World!", - "org_apidesign_vm4brwsr_StringSample_toStringTestLjava_lang_StringI", + StringSample.class, "toStringTest__Ljava_lang_String_2I", "Hello World!5", 5 ); } @@ -37,29 +86,111 @@ assertEquals("Hello World!5", StringSample.toStringTest(5)); } - private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception { + @Test(timeOut=10000) public void stringStringConcat() throws Exception { + assertExec( + "Composes strings OK", + StringSample.class, "concatStrings__Ljava_lang_String_2", + "Hello World!1" + "\\\n\r\t" + ); + } + + @Test public void equalsAndSubstring() throws Exception { + assertExec( + "Composes are OK", + StringSample.class, "equalToHello__ZII", + true, 0, 5 + ); + } + @Test public void replaceChars() throws Exception { + assertExec( + "Can replace slashes by underscores", + StringSample.class, "replace__Ljava_lang_String_2Ljava_lang_String_2CC", + "x_y_z", "x/y/z", '/', '_' + ); + } + @Test public void replaceIntChars() throws Exception { + assertExec( + "Can replace slashes by underscores", + StringSample.class, "replace__Ljava_lang_String_2Ljava_lang_String_2CC", + "x_y_z", "x/y/z", (int)'/', (int)'_' + ); + } + + @Test public void insertBuilder() throws Exception { + assertExec( + "Can insert something into a buffer?", + StringSample.class, "insertBuffer__Ljava_lang_String_2", + "Ahojdo!" + ); + } + + @Test public void compareHashCodeHi() throws Exception { + String j = "Hi"; + int jh = StringSample.hashCode(j); + assertExec( + "Hashcode is the same " +jh, + StringSample.class, "hashCode__ILjava_lang_String_2", + Double.valueOf(jh), j + ); + } + @Test public void compareHashCode1() throws Exception { + String j = "Hello Java!"; + int jh = StringSample.hashCode(j); + assertExec( + "Hashcode is the same " + jh, + StringSample.class, "hashCode__ILjava_lang_String_2", + Double.valueOf(jh), j + ); + } + @Test public void stringSwitch1() throws Exception { + assertExec( + "Get one", + StringSample.class, "stringSwitch__ILjava_lang_String_2", + Double.valueOf(1), "jedna" + ); + } + @Test public void stringSwitch2() throws Exception { + assertExec( + "Get two", + StringSample.class, "stringSwitch__ILjava_lang_String_2", + Double.valueOf(2), "dve" + ); + } + @Test public void stringSwitchDefault() throws Exception { + assertExec( + "Get -1", + StringSample.class, "stringSwitch__ILjava_lang_String_2", + Double.valueOf(-1), "none" + ); + } + + @Test public void countAB() throws Exception { + assertEquals(StringSample.countAB("Ahoj Bedo!"), 3, "Verify Java code is sane"); + assertExec( + "One A and one B adds to 3", + StringSample.class, "countAB__ILjava_lang_String_2", + Double.valueOf(3), "Ahoj Bedo!" + ); + + } + + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { StringBuilder sb = new StringBuilder(); - Invocable i = StaticMethodTest.compileClass(sb, + code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/StringSample", "java/lang/String" ); - - Object ret = null; - try { - ret = i.invokeFunction(methodName, args); - } catch (ScriptException ex) { - fail("Execution failed in " + sb, ex); - } catch (NoSuchMethodException ex) { - fail("Cannot find method in " + sb, ex); - } - if (ret == null && expRes == null) { - return; - } - if (expRes.equals(ret)) { - return; - } - assertEquals(ret, expRes, msg + "was: " + ret + "\n" + sb); - + codeSeq = sb; + } + + private static void assertExec(String msg, + Class clazz, String method, Object expRes, Object... args + ) throws Exception { + StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args); } } diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,98 @@ +/** + * 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 javax.script.Invocable; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptException; +import org.testng.annotations.BeforeClass; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +/** Implements loading class by class. + * + * @author Jaroslav Tulach + */ +public class VMLazyTest { + + + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { + StringBuilder sb = new StringBuilder(); + sb.append("\nvar data = {};"); + sb.append("\nfunction test(clazz, method) {"); + sb.append("\n if (!data.bck2brwsr) data.bck2brwsr = bck2brwsr(function(name) { return loader.get(name); });"); + sb.append("\n var c = data.bck2brwsr.loadClass(clazz);"); + sb.append("\n return c[method]();"); + sb.append("\n}"); + + sb.append("\nfunction checkKO() {"); + sb.append("\n return ko !== null;"); + sb.append("\n}"); + + ScriptEngine[] arr = { null }; + code = StaticMethodTest.compileClass(sb, arr, + "org/apidesign/vm4brwsr/VM" + ); + arr[0].getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE); + codeSeq = sb; + } + + @Test public void invokeStaticMethod() throws Exception { + assertExec("Trying to get -1", "test", Double.valueOf(-1), + StaticMethod.class.getName(), "minusOne__I" + ); + } + + @Test public void loadDependantClass() throws Exception { + assertExec("Expecting zero", "test", Double.valueOf(0), + InstanceSub.class.getName(), "recallDbl__D" + ); + } + + @Test public void loadClassWithAssociatedScript() throws Exception { + assertExec("ko is defined", "test", true, + Script.class.getName(), "checkNotNull__Z" + ); + + Object res = code.invokeFunction("checkKO"); + assertEquals(res, true, "KO is defined on a global level"); + } + + private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception { + Object ret = null; + try { + ret = code.invokeFunction(methodName, args); + } catch (ScriptException ex) { + fail("Execution failed in\n" + StaticMethodTest.dumpJS(codeSeq), ex); + } catch (NoSuchMethodException ex) { + fail("Cannot find method in\n" + StaticMethodTest.dumpJS(codeSeq), ex); + } + if (ret == null && expRes == null) { + return; + } + if (expRes.equals(ret)) { + return; + } + assertEquals(ret, expRes, msg + "was: " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq)); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,46 @@ +/** + * 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.ByteArrayInputStream; +import java.io.IOException; + +/** + * + * @author Jaroslav Tulach + */ +class VMinVM extends ByteCodeToJavaScript { + private VMinVM(Appendable out) { + super(out); + } + + static String toJavaScript(byte[] is) throws IOException { + StringBuilder sb = new StringBuilder(); + new VMinVM(sb).compile(new ByteArrayInputStream(is)); + return sb.toString().toString(); + } + + @Override + protected boolean requireReference(String internalClassName) { + return false; + } + + @Override + protected void requireScript(String resourcePath) { + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,94 @@ +/** + * 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.File; +import java.io.FileWriter; +import java.io.IOException; +import static org.testng.Assert.*; +import javax.script.Invocable; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public class VMinVMTest { + + private static CharSequence codeSeq; + private static Invocable code; + + @Test public void compareGeneratedCodeForArrayClass() throws Exception { + compareCode("org/apidesign/vm4brwsr/Array.class"); + } + + @Test public void compareGeneratedCodeForClassesClass() throws Exception { + compareCode("org/apidesign/vm4brwsr/Classes.class"); + } + + @BeforeClass + public void compileTheCode() throws Exception { + StringBuilder sb = new StringBuilder(); + code = StaticMethodTest.compileClass(sb, + "org/apidesign/vm4brwsr/VMinVM" + ); + codeSeq = sb; + } + + private void compareCode(final String nm) throws Exception, IOException { + byte[] arr = BytesLoader.readClass(nm); + String ret1 = VMinVM.toJavaScript(arr); + + Object ret; + try { + ret = code.invokeFunction("bck2brwsr"); + ret = code.invokeMethod(ret, "loadClass", VMinVM.class.getName()); + ret = code.invokeMethod(ret, "toJavaScript__Ljava_lang_String_2_3B", arr); + } catch (Exception ex) { + File f = File.createTempFile("execution", ".js"); + FileWriter w = new FileWriter(f); + w.append("var byteCode = [\n "); + String sep = ""; + for (int i = 0; i < arr.length; i++) { + w.append(sep).append(Integer.toString((arr[i] + 256) % 256)); + sep = ", "; + if (i % 20 == 0) { + w.append("\n "); + } + } + w.append("\n];\n"); + w.append(codeSeq); + w.close(); + throw new Exception(ex.getMessage() + " file: " + f, ex); + } + + + assertTrue(ret instanceof String, "It is string: " + ret); + + if (!ret1.toString().equals(ret)) { + StringBuilder msg = new StringBuilder("Difference found between "); + msg.append(StaticMethodTest.dumpJS(ret1)); + msg.append(" "); + msg.append(StaticMethodTest.dumpJS((CharSequence) ret)); + msg.append(" compiled by "); + msg.append(StaticMethodTest.dumpJS(codeSeq)); + fail(msg.toString()); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vm/src/test/resources/org/apidesign/vm4brwsr/ko.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/resources/org/apidesign/vm4brwsr/ko.js Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,20 @@ +/* + * 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. + */ +this.ko = {}; + + diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/pom.xml Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,62 @@ + + + 4.0.0 + + org.apidesign + bck2brwsr + 0.3-SNAPSHOT + + org.apidesign.bck2brwsr + vmtest + 0.3-SNAPSHOT + + VM Testing APIs + http://bck2brwsr.apidesign.org + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + + UTF-8 + + + + org.testng + testng + compile + + + junit + junit + + + + + ${project.groupId} + vm4brwsr + ${project.version} + jar + + + ${project.groupId} + emul + ${project.version} + test + + + ${project.groupId} + launcher + ${project.version} + + + diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/BrwsrTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/BrwsrTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,38 @@ +/** + * 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.bck2brwsr.vmtest; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Annotation to indicate that given method should be executed + * in a browser environment. Has to be used in conjunction with {@link VMTest#create(java.lang.Class)} + * factory method. + *

    + * The browser to is by default executed via {@link java.awt.Desktop#browse(java.net.URI)}, + * but one can change that by specifying -Dvmtest.brwsrs=firefox,google-chrome + * property. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface BrwsrTest { +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Compare.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Compare.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,45 @@ +/** + * 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.bck2brwsr.vmtest; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Can be applied on a method that yields a return value. + * Together with {@link VMTest#create} it can be used to write + * methods which are executed in real VM as well as JavaScript VMs and + * their results are compared. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Compare { + /** Specifies whether the system should internal JavaScript interpreter + * as available via {@link javax.script.ScriptEngine}. Defaults to true, + * but in some situations (benchmarking comes to my mind), one may set this + * to false. In such case only browsers provided via + * vmtest.brwsrs property are used. For example + * "vmtest.brwsrs=firefox,google-chrome" would run the test + * in HotSpot VM, firefox and chrome and would compare the results. + * @return + */ + boolean scripting() default true; +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/HtmlFragment.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/HtmlFragment.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,38 @@ +/** + * 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.bck2brwsr.vmtest; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Allows to specify an HTML fragment for a given {@link BrwsrTest}. + * Apply either to the method or to enclosing class. The fragment will be + * made available in the page that executes given test. Its elements shall + * be regularly accessible from the test. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD, ElementType.TYPE}) +public @interface HtmlFragment { + /** HTML code fragment to be exposed on the testing page. + */ + String value(); +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,43 @@ +/** + * 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.bck2brwsr.vmtest; + +import org.apidesign.bck2brwsr.vmtest.impl.CompareCase; +import org.testng.annotations.Factory; + +/** A TestNG {@link Factory} that seeks for {@link Compare} annotations + * in provided class and builds set of tests that compare the computations + * in real as well as JavaScript virtual machines. Use as:

    + * {@code @}{@link Factory} public static create() {
    + *   return @{link VMTest}.{@link #create(YourClass.class);
    + * }
    + * + * @author Jaroslav Tulach + */ +public final class VMTest { + /** Inspects clazz and for each {@lik Compare} method creates + * instances of tests. Each instance runs the test in different virtual + * machine and at the end they compare the results. + * + * @param clazz the class to inspect + * @return the set of created tests + */ + public static Object[] create(Class clazz) { + return CompareCase.create(clazz); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,116 @@ +/** + * 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.bck2brwsr.vmtest.impl; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.WeakHashMap; +import org.apidesign.bck2brwsr.launcher.Launcher; +import org.apidesign.bck2brwsr.launcher.MethodInvocation; +import org.testng.ITest; +import org.testng.annotations.Test; + +/** + * + * @author Jaroslav Tulach + */ +public final class Bck2BrwsrCase implements ITest { + private final Method m; + private final Launcher l; + private final String type; + private final boolean fail; + Object value; + private final String html; + + Bck2BrwsrCase(Method m, String type, Launcher l, boolean fail, String html) { + this.l = l; + this.m = m; + this.type = type; + this.fail = fail; + this.html = html; + } + + @Test(groups = "run") + public void executeCode() throws Throwable { + if (l != null) { + MethodInvocation c = l.invokeMethod(m.getDeclaringClass(), m.getName(), html); + String res = c.toString(); + value = res; + if (fail) { + int idx = res.indexOf(':'); + if (idx >= 0) { + Class thrwbl = null; + try { + Class exCls = Class.forName(res.substring(0, idx)); + if (Throwable.class.isAssignableFrom(exCls)) { + thrwbl = exCls.asSubclass(Throwable.class); + } + } catch (Exception ex) { + // ignore + } + if (thrwbl != null) { + Throwable t = null; + try { + for (Constructor cnstr : thrwbl.getConstructors()) { + if (cnstr.getParameterTypes().length == 1 && cnstr.getParameterTypes()[0].isAssignableFrom(String.class)) { + t = (Throwable) cnstr.newInstance(res.substring(idx + 1)); + break; + } + } + } catch (Throwable ex) { + t = thrwbl.newInstance().initCause(ex); + } + if (t == null) { + t = thrwbl.newInstance().initCause(new Exception(res.substring(idx))); + } + throw t; + } + throw new AssertionError(res); + } + } + } else { + try { + value = m.invoke(m.getDeclaringClass().newInstance()); + } catch (InvocationTargetException ex) { + Throwable t = ex.getTargetException(); + value = t.getClass().getName() + ":" + t.getMessage(); + } + } + } + + @Override + public String getTestName() { + return m.getName() + "[" + typeName() + "]"; + } + + final String typeName() { + return type; + } + static void dumpJS(StringBuilder sb, Bck2BrwsrCase c) throws IOException { + File f = File.createTempFile(c.m.getName(), ".js"); + try (final FileWriter w = new FileWriter(f)) { + w.append(c.l.toString()); + } + sb.append("Path: ").append(f.getPath()); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,151 @@ +/** + * 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.bck2brwsr.vmtest.impl; + +import org.apidesign.bck2brwsr.vmtest.*; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import org.apidesign.bck2brwsr.launcher.Launcher; +import org.testng.Assert; +import org.testng.ITest; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +/** A TestNG {@link Factory} that seeks for {@link Compare} annotations + * in provided class and builds set of tests that compare the computations + * in real as well as JavaScript virtual machines. Use as:
    + * {@code @}{@link Factory} public static create() {
    + *   return @{link VMTest}.{@link #create(YourClass.class);
    + * }
    + * + * @author Jaroslav Tulach + */ +public final class CompareCase implements ITest { + private final Bck2BrwsrCase first, second; + private final Method m; + + private CompareCase(Method m, Bck2BrwsrCase first, Bck2BrwsrCase second) { + this.first = first; + this.second = second; + this.m = m; + } + + /** Inspects clazz and for each {@lik Compare} method creates + * instances of tests. Each instance runs the test in different virtual + * machine and at the end they compare the results. + * + * @param clazz the class to inspect + * @return the set of created tests + */ + public static Object[] create(Class clazz) { + Method[] arr = clazz.getMethods(); + List ret = new ArrayList<>(); + + final LaunchSetup l = LaunchSetup.INSTANCE; + ret.add(l); + + String[] brwsr; + { + String p = System.getProperty("vmtest.brwsrs"); + if (p != null) { + brwsr = p.split(","); + } else { + brwsr = new String[0]; + } + } + + for (Method m : arr) { + registerCompareCases(m, l, ret, brwsr); + registerBrwsrCases(m, l, ret, brwsr); + } + return ret.toArray(); + } + + /** Test that compares the previous results. + * @throws Throwable + */ + @Test(dependsOnGroups = "run") public void compareResults() throws Throwable { + Object v1 = first.value; + Object v2 = second.value; + if (v1 != null) { + v1 = v1.toString(); + } else { + v1 = "null"; + } + try { + Assert.assertEquals(v2, v1, "Comparing results"); + } catch (AssertionError e) { + StringBuilder sb = new StringBuilder(); + sb.append(e.getMessage()); + Bck2BrwsrCase.dumpJS(sb, second); + throw new AssertionError(sb.toString()); + } + } + + /** Test name. + * @return name of the tested method followed by a suffix + */ + @Override + public String getTestName() { + return m.getName() + "[Compare " + second.typeName() + "]"; + } + + private static void registerCompareCases(Method m, final LaunchSetup l, List ret, String[] brwsr) { + Compare c = m.getAnnotation(Compare.class); + if (c == null) { + return; + } + final Bck2BrwsrCase real = new Bck2BrwsrCase(m, "Java", null, false, null); + ret.add(real); + if (c.scripting()) { + final Bck2BrwsrCase js = new Bck2BrwsrCase(m, "JavaScript", l.javaScript(), false, null); + ret.add(js); + ret.add(new CompareCase(m, real, js)); + } + for (String b : brwsr) { + final Launcher s = l.brwsr(b); + ret.add(s); + final Bck2BrwsrCase cse = new Bck2BrwsrCase(m, b, s, false, null); + ret.add(cse); + ret.add(new CompareCase(m, real, cse)); + } + } + private static void registerBrwsrCases(Method m, final LaunchSetup l, List ret, String[] brwsr) { + BrwsrTest c = m.getAnnotation(BrwsrTest.class); + if (c == null) { + return; + } + HtmlFragment f = m.getAnnotation(HtmlFragment.class); + if (f == null) { + f = m.getDeclaringClass().getAnnotation(HtmlFragment.class); + } + String html = f == null ? null : f.value(); + if (brwsr.length == 0) { + final Launcher s = l.brwsr(null); + ret.add(s); + ret.add(new Bck2BrwsrCase(m, "Brwsr", s, true, html)); + } else { + for (String b : brwsr) { + final Launcher s = l.brwsr(b); + ret.add(s); + ret.add(new Bck2BrwsrCase(m, b, s, true, html)); + } + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/LaunchSetup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/LaunchSetup.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,68 @@ +/** + * 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.bck2brwsr.vmtest.impl; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apidesign.bck2brwsr.launcher.Launcher; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; + +/** + * + * @author Jaroslav Tulach + */ +public final class LaunchSetup { + static LaunchSetup INSTANCE = new LaunchSetup(); + + private final Launcher js = Launcher.createJavaScript(); + private final Map brwsrs = new LinkedHashMap<>(); + + private LaunchSetup() { + } + + public Launcher javaScript() { + return js; + } + + public synchronized Launcher brwsr(String cmd) { + Launcher s = brwsrs.get(cmd); + if (s == null) { + s = Launcher.createBrowser(cmd); + brwsrs.put(cmd, s); + } + return s; + } + + @BeforeGroups("run") + public void initializeLauncher() throws IOException { + js.initialize(); + for (Launcher launcher : brwsrs.values()) { + launcher.initialize(); + } + } + + @AfterGroups("run") + public void shutDownLauncher() throws IOException, InterruptedException { + js.shutdown(); + for (Launcher launcher : brwsrs.values()) { + launcher.shutdown(); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,39 @@ +/** + * 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.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class AssertionTest { + + @Compare public Object checkAssert() throws ClassNotFoundException { + assert false : "Is assertion status on?"; + return null; + } + + @Factory + public static Object[] create() { + return VMTest.create(AssertionTest.class); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -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.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.vmtest.BrwsrTest; +import org.apidesign.bck2brwsr.vmtest.HtmlFragment; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class BrwsrCheckTest { + + @BrwsrTest public void assertWindowObjectIsDefined() { + assert window() != null : "No window object found!"; + } + + + + + @HtmlFragment("

    \n" + + "Hello!\n" + + "

    \n") + @BrwsrTest public void accessProvidedFragment() { + assert getElementById("hello") != null : "Element with 'hello' ID found"; + } + + @Factory + public static Object[] create() { + return VMTest.create(BrwsrCheckTest.class); + } + + + @JavaScriptBody(args = {}, body = "return window;") + private static native Object window(); + + @JavaScriptBody(args = { "id" }, body = "return window.document.getElementById(id);") + private static native Object getElementById(String id); +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,102 @@ +/** + * 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.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ByteArithmeticTest { + + private static byte add(byte x, byte y) { + return (byte)(x + y); + } + + private static byte sub(byte x, byte y) { + return (byte)(x - y); + } + + private static byte mul(byte x, byte y) { + return (byte)(x * y); + } + + private static byte div(byte x, byte y) { + return (byte)(x / y); + } + + private static byte mod(byte x, byte y) { + return (byte)(x % y); + } + + @Compare public byte conversion() { + return (byte)123456; + } + + @Compare public byte addOverflow() { + return add(Byte.MAX_VALUE, (byte)1); + } + + @Compare public byte subUnderflow() { + return sub(Byte.MIN_VALUE, (byte)1); + } + + @Compare public byte addMaxByteAndMaxByte() { + return add(Byte.MAX_VALUE, Byte.MAX_VALUE); + } + + @Compare public byte subMinByteAndMinByte() { + return sub(Byte.MIN_VALUE, Byte.MIN_VALUE); + } + + @Compare public byte multiplyMaxByte() { + return mul(Byte.MAX_VALUE, (byte)2); + } + + @Compare public byte multiplyMaxByteAndMaxByte() { + return mul(Byte.MAX_VALUE, Byte.MAX_VALUE); + } + + @Compare public byte multiplyMinByte() { + return mul(Byte.MIN_VALUE, (byte)2); + } + + @Compare public byte multiplyMinByteAndMinByte() { + return mul(Byte.MIN_VALUE, Byte.MIN_VALUE); + } + + @Compare public byte multiplyPrecision() { + return mul((byte)17638, (byte)1103); + } + + @Compare public byte division() { + return div((byte)1, (byte)2); + } + + @Compare public byte divisionReminder() { + return mod((byte)1, (byte)2); + } + + @Factory + public static Object[] create() { + return VMTest.create(ByteArithmeticTest.class); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,73 @@ +/** + * 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.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CloneTest { + private int value; + + @Compare + public Object notSupported() throws CloneNotSupportedException { + return this.clone(); + } + + @Compare public String sameClass() throws CloneNotSupportedException { + return new Clnbl().clone().getClass().getName(); + } + + @Compare public boolean differentInstance() throws CloneNotSupportedException { + Clnbl orig = new Clnbl(); + return orig == orig.clone(); + } + + @Compare public int sameReference() throws CloneNotSupportedException { + CloneTest self = this; + Clnbl orig = new Clnbl(); + self.value = 33; + orig.ref = self; + return ((Clnbl)orig.clone()).ref.value; + } + + @Compare public int sameValue() throws CloneNotSupportedException { + Clnbl orig = new Clnbl(); + orig.value = 10; + return ((Clnbl)orig.clone()).value; + } + + @Factory + public static Object[] create() { + return VMTest.create(CloneTest.class); + } + + public static final class Clnbl implements Cloneable { + public CloneTest ref; + private int value; + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,93 @@ +/** + * 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.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CompareByteArrayTest { + @Compare public int byteArraySum() { + byte[] arr = createArray(); + return sumByteArr(arr); + } + + @Compare public int countZeros() { + int zeros = 0; + for (Byte b : createArray()) { + if (b == 0) { + zeros++; + } + } + return zeros; + } + + private static int sumByteArr(byte[] arr) { + int sum = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + } + return sum; + } + + @Compare public String noOutOfBounds() { + return atIndex(1); + } + + @Compare public String outOfBounds() { + return atIndex(5); + } + + @Compare public String outOfBoundsMinus() { + return atIndex(-1); + } + + @Compare public String toOfBounds() { + return toIndex(5); + } + + @Compare public String toOfBoundsMinus() { + return toIndex(-1); + } + + private static final int[] arr = { 0, 1, 2 }; + public static String atIndex(int at) { + return "at@" + arr[at]; + } + public static String toIndex(int at) { + arr[at] = 10; + return "ok"; + } + + + @Factory + public static Object[] create() { + return VMTest.create(CompareByteArrayTest.class); + } + + private byte[] createArray() { + byte[] arr = new byte[10]; + arr[5] = 3; + arr[7] = 8; + return arr; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,50 @@ +/** + * 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.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CompareHashTest { + @Compare public int hashOfString() { + return "Ahoj".hashCode(); + } + + @Compare public int hashRemainsYieldsZero() { + Object o = new Object(); + return o.hashCode() - o.hashCode(); + } + + @Compare public int initializeInStatic() { + return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode(); + } + + @Compare public int hashOfInt() { + return Integer.valueOf(Integer.MAX_VALUE).hashCode(); + } + + @Factory + public static Object[] create() { + return VMTest.create(CompareHashTest.class); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,63 @@ +/** + * 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.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CompareIntArrayTest { + @Compare public int integerArraySum() { + int[] arr = createArray(); + return sumIntArr(arr); + } + + @Compare public int countZeros() { + int zeros = 0; + for (Integer i : createArray()) { + if (i == 0) { + zeros++; + } + } + return zeros; + } + + private static int sumIntArr(int[] arr) { + int sum = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + } + return sum; + } + + @Factory + public static Object[] create() { + return VMTest.create(CompareIntArrayTest.class); + } + + private int[] createArray() { + int[] arr = new int[10]; + arr[5] = 3; + arr[7] = 8; + return arr; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,133 @@ +/** + * 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.bck2brwsr.tck; + +import java.net.MalformedURLException; +import java.net.URL; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class CompareStringsTest { + @Compare public String firstChar() { + return "" + ("Hello".toCharArray()[0]); + } + + @Compare public String classCast() { + Object o = firstChar(); + return String.class.cast(o); + } + + @Compare public String classCastThrown() { + Object o = null; + return String.class.cast(o); + } + + @Compare public boolean equalToNull() { + return "Ahoj".equals(null); + } + + @Compare public static Object compareURLs() throws MalformedURLException { + return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString(); + } + + @Compare public String deleteLastTwoCharacters() { + StringBuilder sb = new StringBuilder(); + sb.append("453.0"); + if (sb.toString().endsWith(".0")) { + final int l = sb.length(); + sb.delete(l - 2, l); + } + return sb.toString().toString(); + } + + @Compare public String nameOfStringClass() throws Exception { + return Class.forName("java.lang.String").getName(); + } + @Compare public String nameOfArrayClass() throws Exception { + return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName(); + } + + @Compare public String lowerHello() { + return "HeLlO".toLowerCase(); + } + + @Compare public String lowerA() { + return String.valueOf(Character.toLowerCase('A')).toString(); + } + @Compare public String upperHello() { + return "hello".toUpperCase(); + } + + @Compare public String upperA() { + return String.valueOf(Character.toUpperCase('a')).toString(); + } + + @Compare public boolean matchRegExp() throws Exception { + return "58038503".matches("\\d*"); + } + + @Compare public boolean doesNotMatchRegExp() throws Exception { + return "58038503GH".matches("\\d*"); + } + + @Compare public boolean doesNotMatchRegExpFully() throws Exception { + return "Hello".matches("Hell"); + } + + @Compare public String emptyCharArray() { + char[] arr = new char[10]; + return new String(arr); + } + + @Compare public String variousCharacterTests() throws Exception { + StringBuilder sb = new StringBuilder(); + + sb.append(Character.isUpperCase('a')); + sb.append(Character.isUpperCase('A')); + sb.append(Character.isLowerCase('a')); + sb.append(Character.isLowerCase('A')); + + sb.append(Character.isLetter('A')); + sb.append(Character.isLetterOrDigit('9')); + sb.append(Character.isLetterOrDigit('A')); + sb.append(Character.isLetter('0')); + + return sb.toString().toString(); + } + + @Compare + public String nullFieldInitialized() { + NullField nf = new NullField(); + return ("" + nf.name).toString(); + } + + @Factory + public static Object[] create() { + return VMTest.create(CompareStringsTest.class); + } + + private static final class NullField { + + String name; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,108 @@ +/** + * 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.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class IntegerArithmeticTest { + + private static int add(int x, int y) { + return x + y; + } + + private static int sub(int x, int y) { + return x - y; + } + + private static int mul(int x, int y) { + return x * y; + } + + private static int div(int x, int y) { + return x / y; + } + + private static int mod(int x, int y) { + return x % y; + } + + @Compare public int addOverflow() { + return add(Integer.MAX_VALUE, 1); + } + + @Compare public int subUnderflow() { + return sub(Integer.MIN_VALUE, 1); + } + + @Compare public int addMaxIntAndMaxInt() { + return add(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Compare public int subMinIntAndMinInt() { + return sub(Integer.MIN_VALUE, Integer.MIN_VALUE); + } + + @Compare public int multiplyMaxInt() { + return mul(Integer.MAX_VALUE, 2); + } + + @Compare public int multiplyMaxIntAndMaxInt() { + return mul(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Compare public int multiplyMinInt() { + return mul(Integer.MIN_VALUE, 2); + } + + @Compare public int multiplyMinIntAndMinInt() { + return mul(Integer.MIN_VALUE, Integer.MIN_VALUE); + } + + @Compare public int multiplyPrecision() { + return mul(119106029, 1103515245); + } + + @Compare public int division() { + return div(1, 2); + } + + @Compare public int divisionReminder() { + return mod(1, 2); + } + + @Compare public int sumTwoDimensions() { + int[][] matrix = createMatrix(4, 3); + matrix[0][0] += 10; + return matrix[0][0]; + } + + static int[][] createMatrix(int x, int y) { + return new int[x][y]; + } + + @Factory + public static Object[] create() { + return VMTest.create(IntegerArithmeticTest.class); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,135 @@ +/** + * 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.bck2brwsr.tck; + +import java.lang.reflect.Array; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ReflectionArrayTest { + @Compare public int lengthOfStringArray() { + String[] arr = (String[]) Array.newInstance(String.class, 10); + return arr.length; + } + + @Compare public int reflectiveLengthOfStringArray() { + Object arr = Array.newInstance(String.class, 10); + return Array.getLength(arr); + } + + @Compare public int reflectiveLengthOneNonArray() { + Object arr = "non-array"; + return Array.getLength(arr); + } + + @Compare public String compTypeOfStringArray() { + String[] arr = (String[]) Array.newInstance(String.class, 10); + return arr.getClass().getComponentType().getName(); + } + + @Compare public Object negativeArrayExcp() { + return Array.newInstance(String.class, -5); + } + + @Compare public int lengthOfIntArray() { + int[] arr = (int[]) Array.newInstance(Integer.TYPE, 10); + return arr.length; + } + + @Compare public int reflectiveLengthOfIntArray() { + Object arr = Array.newInstance(Integer.TYPE, 10); + return Array.getLength(arr); + } + + @Compare public String compTypeOfIntArray() { + int[] arr = (int[]) Array.newInstance(int.class, 10); + return arr.getClass().getComponentType().getName(); + } + + @Compare public Object intNegativeArrayExcp() { + return Array.newInstance(int.class, -5); + } + + @Compare public Integer verifyAutobox() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + return (Integer) Array.get(arr, 0); + } + @Compare public String verifyObjectArray() { + String[] arr = (String[]) Array.newInstance(String.class, 5); + Array.set(arr, 0, "Hello"); + return (String) Array.get(arr, 0); + } + @Compare public int verifyInt() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + return Array.getInt(arr, 0); + } + @Compare public long verifyConvertToLong() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + return Array.getLong(arr, 0); + } + + @Compare public Object verifySetIntToObject() { + try { + Object[] arr = (Object[]) Array.newInstance(Object.class, 5); + Array.setInt(arr, 0, 10); + return Array.get(arr, 0); + } catch (Exception exception) { + return exception.getClass().getName(); + } + } + @Compare public long verifySetShort() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + Array.setShort(arr, 0, (short)10); + return Array.getLong(arr, 0); + } + @Compare public long verifyCantSetLong() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + Array.setLong(arr, 0, 10); + return Array.getLong(arr, 0); + } + @Compare public float verifyLongToFloat() { + Object arr = Array.newInstance(float.class, 5); + Array.setLong(arr, 0, 10); + return Array.getFloat(arr, 0); + } + + @Compare public double verifyConvertToDouble() { + int[] arr = (int[]) Array.newInstance(int.class, 5); + return Array.getDouble(arr, 0); + } + + @Compare public int multiIntArray() { + int[][][] arr = (int[][][]) Array.newInstance(int.class, 3, 3, 3); + return arr[0][1][2] + 5 + arr[2][2][0]; + } + + @Compare public String multiIntArrayCompType() { + return Array.newInstance(int.class, 3, 3, 3).getClass().getName(); + } + + + @Factory + public static Object[] create() { + return VMTest.create(ReflectionArrayTest.class); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,192 @@ +/** + * 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.bck2brwsr.tck; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ReflectionTest { + @Compare public boolean nonNullThis() { + return this == null; + } + + @Compare public String intType() { + return Integer.TYPE.toString(); + } + + @Compare public String voidType() throws Exception { + return void.class.toString(); + } + + @Compare public String longClass() { + return long.class.toString(); + } + + @Compare public String namesOfMethods() { + StringBuilder sb = new StringBuilder(); + String[] arr = new String[20]; + int i = 0; + for (Method m : StaticUse.class.getMethods()) { + arr[i++] = m.getName(); + } + for (String s : sort(arr, i)) { + sb.append(s).append("\n"); + } + return sb.toString(); + } + + @Compare public String cannotCallNonStaticMethodWithNull() throws Exception { + StaticUse.class.getMethod("instanceMethod").invoke(null); + return "should not happen"; + } + + @Compare public Object voidReturnType() throws Exception { + return StaticUse.class.getMethod("instanceMethod").getReturnType(); + } + + @Compare public String newInstanceFails() throws InstantiationException { + try { + return "success: " + StaticUse.class.newInstance(); + } catch (IllegalAccessException ex) { + return ex.getClass().getName(); + } + } + + @Compare public String paramTypes() throws Exception { + Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE); + final Class[] pt = plus.getParameterTypes(); + return pt[0].getName(); + } + @Compare public String paramTypesNotFound() throws Exception { + return StaticUse.class.getMethod("plus", int.class, double.class).toString(); + } + @Compare public int methodWithArgs() throws Exception { + Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE); + return (Integer)plus.invoke(null, 2, 3); + } + + @Compare public String classGetNameForByte() { + return byte.class.getName(); + } + @Compare public String classGetNameForBaseObject() { + return newObject().getClass().getName(); + } + @Compare public String classGetNameForJavaObject() { + return new Object().getClass().getName(); + } + @Compare public String classGetNameForObjectArray() { + return (new Object[3]).getClass().getName(); + } + @Compare public String classGetNameForSimpleIntArray() { + return (new int[3]).getClass().getName(); + } + @Compare public boolean sameClassGetNameForSimpleCharArray() { + return (new char[3]).getClass() == (new char[34]).getClass(); + } + @Compare public String classGetNameForMultiIntArray() { + return (new int[3][4][5][6][7][8][9]).getClass().getName(); + } + @Compare public String classGetNameForMultiIntArrayInner() { + final int[][][][][][][] arr = new int[3][4][5][6][7][8][9]; + int[][][][][][] subarr = arr[0]; + int[][][][][] subsubarr = subarr[0]; + return subsubarr.getClass().getName(); + } + @Compare public String classGetNameForMultiStringArray() { + return (new String[3][4][5][6][7][8][9]).getClass().getName(); + } + + @Compare public String classForByte() throws Exception { + return Class.forName("[Z").getName(); + } + + @Compare public String classForUnknownArray() { + try { + return Class.forName("[W").getName(); + } catch (Exception ex) { + return ex.getClass().getName(); + } + } + + @Compare public String classForUnknownDeepArray() { + try { + return Class.forName("[[[[[W").getName(); + } catch (Exception ex) { + return ex.getClass().getName(); + } + } + + @Compare public String componentGetNameForObjectArray() { + return (new Object[3]).getClass().getComponentType().getName(); + } + @Compare public boolean sameComponentGetNameForObjectArray() { + return (new Object[3]).getClass().getComponentType() == Object.class; + } + @Compare public String componentGetNameForSimpleIntArray() { + return (new int[3]).getClass().getComponentType().getName(); + } + @Compare public String componentGetNameForMultiIntArray() { + return (new int[3][4][5][6][7][8][9]).getClass().getComponentType().getName(); + } + @Compare public String componentGetNameForMultiStringArray() { + Class c = (new String[3][4][5][6][7][8][9]).getClass(); + StringBuilder sb = new StringBuilder(); + for (;;) { + sb.append(c.getName()).append("\n"); + c = c.getComponentType(); + if (c == null) { + break; + } + } + return sb.toString(); + } + + @Compare public boolean isArray() { + return new Object[0].getClass().isArray(); + } + + @JavaScriptBody(args = { "arr", "len" }, body="var a = arr.slice(0, len); a.sort(); return a;") + private static String[] sort(String[] arr, int len) { + List list = Arrays.asList(arr).subList(0, len); + Collections.sort(list); + return list.toArray(new String[0]); + } + + @JavaScriptBody(args = {}, body = "return new Object();") + private static Object newObject() { + return new Object(); + } + + @Factory + public static Object[] create() { + return VMTest.create(ReflectionTest.class); + } + +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,45 @@ +/** + * 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.bck2brwsr.tck; + +import java.io.InputStream; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ResourcesTest { + + @Compare public String readResourceAsStream() throws Exception { + InputStream is = getClass().getResourceAsStream("Resources.txt"); + byte[] b = new byte[30]; + int len = is.read(b); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < len; i++) { + sb.append((char)b[i]); + } + return sb.toString(); + } + + @Factory public static Object[] create() { + return VMTest.create(ResourcesTest.class); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,102 @@ +/** + * 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.bck2brwsr.tck; + +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ShortArithmeticTest { + + private static short add(short x, short y) { + return (short)(x + y); + } + + private static short sub(short x, short y) { + return (short)(x - y); + } + + private static short mul(short x, short y) { + return (short)(x * y); + } + + private static short div(short x, short y) { + return (short)(x / y); + } + + private static short mod(short x, short y) { + return (short)(x % y); + } + + @Compare public short conversion() { + return (short)123456; + } + + @Compare public short addOverflow() { + return add(Short.MAX_VALUE, (short)1); + } + + @Compare public short subUnderflow() { + return sub(Short.MIN_VALUE, (short)1); + } + + @Compare public short addMaxShortAndMaxShort() { + return add(Short.MAX_VALUE, Short.MAX_VALUE); + } + + @Compare public short subMinShortAndMinShort() { + return sub(Short.MIN_VALUE, Short.MIN_VALUE); + } + + @Compare public short multiplyMaxShort() { + return mul(Short.MAX_VALUE, (short)2); + } + + @Compare public short multiplyMaxShortAndMaxShort() { + return mul(Short.MAX_VALUE, Short.MAX_VALUE); + } + + @Compare public short multiplyMinShort() { + return mul(Short.MIN_VALUE, (short)2); + } + + @Compare public short multiplyMinShortAndMinShort() { + return mul(Short.MIN_VALUE, Short.MIN_VALUE); + } + + @Compare public short multiplyPrecision() { + return mul((short)17638, (short)1103); + } + + @Compare public short division() { + return div((short)1, (short)2); + } + + @Compare public short divisionReminder() { + return mod((short)1, (short)2); + } + + @Factory + public static Object[] create() { + return VMTest.create(ShortArithmeticTest.class); + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,31 @@ +/** + * 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.bck2brwsr.tck; + +class StaticUse { + public static final Object NON_NULL = new Object(); + private StaticUse() { + } + + public void instanceMethod() { + } + + public static int plus(int a, int b) { + return a + b; + } +} diff -r 029e6eed60e9 -r 388e48c0a37a vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt Wed Jan 23 20:16:48 2013 +0100 @@ -0,0 +1,1 @@ +Ahoj